linux设备驱动之时间,延迟及延缓操作(实践)

2024-02-21 09:48

本文主要是介绍linux设备驱动之时间,延迟及延缓操作(实践),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一 jit.函数源码

/** jit.c -- the just-in-time module** Copyright (C) 2001,2003 Alessandro Rubini and Jonathan Corbet* Copyright (C) 2001,2003 O'Reilly & Associates** The source code in this file can be freely used, adapted,* and redistributed in source or binary form, so long as an* acknowledgment appears in derived source files.  The citation* should list that the code comes from the book "Linux Device* Drivers" by Alessandro Rubini and Jonathan Corbet, published* by O'Reilly & Associates.   No warranty is attached;* we cannot take responsibility for errors or fitness for use.** $Id: jit.c,v 1.16 2004/09/26 07:02:43 gregkh Exp $*/#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>#include <linux/time.h>
#include <linux/timer.h>
#include <linux/kernel.h>
#include <linux/proc_fs.h>
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>#include <linux/param.h>
#include <linux/wait.h>
#include <linux/jiffies.h>
#include <linux/sched.h>#include <asm/hardirq.h>
/** This module is a silly one: it only embeds short code fragments* that show how time delays can be handled in the kernel.*/int delay = HZ; /* the default delay, expressed in jiffies */module_param(delay, int, 0);MODULE_AUTHOR("Alessandro Rubini");
MODULE_LICENSE("Dual BSD/GPL");/* use these as data pointers, to implement four files in one function */
enum jit_files {JIT_BUSY,JIT_SCHED,JIT_QUEUE,JIT_SCHEDTO
};/** This function prints one line of data, after sleeping one second.* It can sleep in different ways, according to the data pointer*/
int jit_fn(char *buf, char **start, off_t offset,int len, int *eof, void *data)
{unsigned long j0, j1; /* jiffies */wait_queue_head_t wait;init_waitqueue_head (&wait);j0 = jiffies;j1 = j0 + delay;switch((long)data) {case JIT_BUSY:while (time_before(jiffies, j1))cpu_relax();break;case JIT_SCHED:while (time_before(jiffies, j1)) {schedule();}break;case JIT_QUEUE:wait_event_interruptible_timeout(wait, 0, delay); break;case JIT_SCHEDTO:set_current_state(TASK_INTERRUPTIBLE);schedule_timeout (delay);break;}j1 = jiffies; /* actual value after we delayed */len = sprintf(buf, "%9li %9li\n", j0, j1);*start = buf;return len;
}/** This file, on the other hand, returns the current time forever*/
int jit_currentime(char *buf, char **start, off_t offset,int len, int *eof, void *data)
{struct timeval tv1;struct timespec tv2;unsigned long j1;u64 j2;/* get them four */j1 = jiffies;j2 = get_jiffies_64();do_gettimeofday(&tv1);tv2 = current_kernel_time();/* print */len=0;len += sprintf(buf,"0x%08lx 0x%016Lx %10i.%06i\n""%40i.%09i\n",j1, j2,(int) tv1.tv_sec, (int) tv1.tv_usec,(int) tv2.tv_sec, (int) tv2.tv_nsec);*start = buf;return len;
}/** The timer example follows*/int tdelay = 10;
module_param(tdelay, int, 0);/* This data structure used as "data" for the timer and tasklet functions */
struct jit_data {struct timer_list timer;struct tasklet_struct tlet;int hi; /* tasklet or tasklet_hi */wait_queue_head_t wait;unsigned long prevjiffies;unsigned char *buf;int loops;
};
#define JIT_ASYNC_LOOPS 5void jit_timer_fn(unsigned long arg)
{struct jit_data *data = (struct jit_data *)arg;unsigned long j = jiffies;data->buf += sprintf(data->buf, "%9li  %3li     %i    %6i   %i   %s\n",j, j - data->prevjiffies, in_interrupt() ? 1 : 0,current->pid, smp_processor_id(), current->comm);if (--data->loops) {data->timer.expires += tdelay;data->prevjiffies = j;add_timer(&data->timer);} else {wake_up_interruptible(&data->wait);}
}/* the /proc function: allocate everything to allow concurrency */
int jit_timer(char *buf, char **start, off_t offset,int len, int *eof, void *unused_data)
{struct jit_data *data;char *buf2 = buf;unsigned long j = jiffies;data = kmalloc(sizeof(*data), GFP_KERNEL);if (!data)return -ENOMEM;init_timer(&data->timer);init_waitqueue_head (&data->wait);/* write the first lines in the buffer */buf2 += sprintf(buf2, "   time   delta  inirq    pid   cpu command\n");buf2 += sprintf(buf2, "%9li  %3li     %i    %6i   %i   %s\n",j, 0L, in_interrupt() ? 1 : 0,current->pid, smp_processor_id(), current->comm);/* fill the data for our timer function */data->prevjiffies = j;data->buf = buf2;data->loops = JIT_ASYNC_LOOPS;/* register the timer */data->timer.data = (unsigned long)data;data->timer.function = jit_timer_fn;data->timer.expires = j + tdelay; /* parameter */add_timer(&data->timer);/* wait for the buffer to fill */wait_event_interruptible(data->wait, !data->loops);if (signal_pending(current))return -ERESTARTSYS;buf2 = data->buf;kfree(data);*eof = 1;return buf2 - buf;
}void jit_tasklet_fn(unsigned long arg)
{struct jit_data *data = (struct jit_data *)arg;unsigned long j = jiffies;data->buf += sprintf(data->buf, "%9li  %3li     %i    %6i   %i   %s\n",j, j - data->prevjiffies, in_interrupt() ? 1 : 0,current->pid, smp_processor_id(), current->comm);if (--data->loops) {data->prevjiffies = j;if (data->hi)tasklet_hi_schedule(&data->tlet);elsetasklet_schedule(&data->tlet);} else {wake_up_interruptible(&data->wait);}
}/* the /proc function: allocate everything to allow concurrency */
int jit_tasklet(char *buf, char **start, off_t offset,int len, int *eof, void *arg)
{struct jit_data *data;char *buf2 = buf;unsigned long j = jiffies;long hi = (long)arg;data = kmalloc(sizeof(*data), GFP_KERNEL);if (!data)return -ENOMEM;init_waitqueue_head (&data->wait);/* write the first lines in the buffer */buf2 += sprintf(buf2, "   time   delta  inirq    pid   cpu command\n");buf2 += sprintf(buf2, "%9li  %3li     %i    %6i   %i   %s\n",j, 0L, in_interrupt() ? 1 : 0,current->pid, smp_processor_id(), current->comm);/* fill the data for our tasklet function */data->prevjiffies = j;data->buf = buf2;data->loops = JIT_ASYNC_LOOPS;/* register the tasklet */tasklet_init(&data->tlet, jit_tasklet_fn, (unsigned long)data);data->hi = hi;if (hi)tasklet_hi_schedule(&data->tlet);elsetasklet_schedule(&data->tlet);/* wait for the buffer to fill */wait_event_interruptible(data->wait, !data->loops);if (signal_pending(current))return -ERESTARTSYS;buf2 = data->buf;kfree(data);*eof = 1;return buf2 - buf;
}int __init jit_init(void)
{create_proc_read_entry("currentime", 0, NULL, jit_currentime, NULL);create_proc_read_entry("jitbusy", 0, NULL, jit_fn, (void *)JIT_BUSY);create_proc_read_entry("jitsched",0, NULL, jit_fn, (void *)JIT_SCHED);create_proc_read_entry("jitqueue",0, NULL, jit_fn, (void *)JIT_QUEUE);create_proc_read_entry("jitschedto", 0, NULL, jit_fn, (void *)JIT_SCHEDTO);create_proc_read_entry("jitimer", 0, NULL, jit_timer, NULL);create_proc_read_entry("jitasklet", 0, NULL, jit_tasklet, NULL);create_proc_read_entry("jitasklethi", 0, NULL, jit_tasklet, (void *)1);return 0; /* success */
}void __exit jit_cleanup(void)
{remove_proc_entry("currentime", NULL);remove_proc_entry("jitbusy", NULL);remove_proc_entry("jitsched", NULL);remove_proc_entry("jitqueue", NULL);remove_proc_entry("jitschedto", NULL);remove_proc_entry("jitimer", NULL);remove_proc_entry("jitasklet", NULL);remove_proc_entry("jitasklethi", NULL);
}module_init(jit_init);
module_exit(jit_cleanup);

二 Makefilewenjian源码

KERNELDIR = /usr/src/linux-headers-2.6.38-8-generic
PWD := $(shell pwd)obj-m := jit.o modules:$(MAKE) -C $(KERNELDIR) M=$(PWD) modules

三 编译及安装驱动

1  caoyin@caoyin:~/jit$ make

2 root@caoyin:/home/caoyin/jit# insmod ./jit.ko

四 测试例子

a 获取当前时间

root@caoyin:/home/caoyin/jit# head -8 /proc/currentime

b 忙等待

root@caoyin:/home/caoyin/jit# dd bs=20 count=5 < /proc/jitbusy

c 让出处理器

root@caoyin:/home/caoyin/jit# dd bs=20 count=5 < /proc/jitshed

d 超时

root@caoyin:/home/caoyin/jit# dd bs=20 count=5 < /proc/jitqueue

e tasklet的实现

root@caoyin:/home/caoyin/jit# cat /proc/jitasklet



这篇关于linux设备驱动之时间,延迟及延缓操作(实践)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/731364

相关文章

SQLite3命令行工具最佳实践指南

《SQLite3命令行工具最佳实践指南》SQLite3是轻量级嵌入式数据库,无需服务器支持,具备ACID事务与跨平台特性,适用于小型项目和学习,sqlite3.exe作为命令行工具,支持SQL执行、数... 目录1. SQLite3简介和特点2. sqlite3.exe使用概述2.1 sqlite3.exe

Linux脚本(shell)的使用方式

《Linux脚本(shell)的使用方式》:本文主要介绍Linux脚本(shell)的使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录概述语法详解数学运算表达式Shell变量变量分类环境变量Shell内部变量自定义变量:定义、赋值自定义变量:引用、修改、删

C++ 函数 strftime 和时间格式示例详解

《C++函数strftime和时间格式示例详解》strftime是C/C++标准库中用于格式化日期和时间的函数,定义在ctime头文件中,它将tm结构体中的时间信息转换为指定格式的字符串,是处理... 目录C++ 函数 strftipythonme 详解一、函数原型二、功能描述三、格式字符串说明四、返回值五

SQL中JOIN操作的条件使用总结与实践

《SQL中JOIN操作的条件使用总结与实践》在SQL查询中,JOIN操作是多表关联的核心工具,本文将从原理,场景和最佳实践三个方面总结JOIN条件的使用规则,希望可以帮助开发者精准控制查询逻辑... 目录一、ON与WHERE的本质区别二、场景化条件使用规则三、最佳实践建议1.优先使用ON条件2.WHERE用

Springboot整合Redis主从实践

《Springboot整合Redis主从实践》:本文主要介绍Springboot整合Redis主从的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录前言原配置现配置测试LettuceConnectionFactory.setShareNativeConnect

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据

Linux链表操作方式

《Linux链表操作方式》:本文主要介绍Linux链表操作方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、链表基础概念与内核链表优势二、内核链表结构与宏解析三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势六、典型应用场景七、调试技巧与

详解Linux中常见环境变量的特点与设置

《详解Linux中常见环境变量的特点与设置》环境变量是操作系统和用户设置的一些动态键值对,为运行的程序提供配置信息,理解环境变量对于系统管理、软件开发都很重要,下面小编就为大家详细介绍一下吧... 目录前言一、环境变量的概念二、常见的环境变量三、环境变量特点及其相关指令3.1 环境变量的全局性3.2、环境变

Linux系统中的firewall-offline-cmd详解(收藏版)

《Linux系统中的firewall-offline-cmd详解(收藏版)》firewall-offline-cmd是firewalld的一个命令行工具,专门设计用于在没有运行firewalld服务的... 目录主要用途基本语法选项1. 状态管理2. 区域管理3. 服务管理4. 端口管理5. ICMP 阻断

Linux实现线程同步的多种方式汇总

《Linux实现线程同步的多种方式汇总》本文详细介绍了Linux下线程同步的多种方法,包括互斥锁、自旋锁、信号量以及它们的使用示例,通过这些同步机制,可以解决线程安全问题,防止资源竞争导致的错误,示例... 目录什么是线程同步?一、互斥锁(单人洗手间规则)适用场景:特点:二、条件变量(咖啡厅取餐系统)工作流