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

相关文章

MySQL 日期时间格式化函数 DATE_FORMAT() 的使用示例详解

《MySQL日期时间格式化函数DATE_FORMAT()的使用示例详解》`DATE_FORMAT()`是MySQL中用于格式化日期时间的函数,本文详细介绍了其语法、格式化字符串的含义以及常见日期... 目录一、DATE_FORMAT()语法二、格式化字符串详解三、常见日期时间格式组合四、业务场景五、总结一、

Spring Retry 实现乐观锁重试实践记录

《SpringRetry实现乐观锁重试实践记录》本文介绍了在秒杀商品SKU表中使用乐观锁和MybatisPlus配置乐观锁的方法,并分析了测试环境和生产环境的隔离级别对乐观锁的影响,通过简单验证,... 目录一、场景分析 二、简单验证 2.1、可重复读 2.2、读已提交 三、最佳实践 3.1、配置重试模板

linux打包解压命令方式

《linux打包解压命令方式》文章介绍了Linux系统中常用的打包和解压命令,包括tar和zip,使用tar命令可以创建和解压tar格式的归档文件,使用zip命令可以创建和解压zip格式的压缩文件,每... 目录Lijavascriptnux 打包和解压命令打包命令解压命令总结linux 打包和解压命令打

mac安装nvm(node.js)多版本管理实践步骤

《mac安装nvm(node.js)多版本管理实践步骤》:本文主要介绍mac安装nvm(node.js)多版本管理的相关资料,NVM是一个用于管理多个Node.js版本的命令行工具,它允许开发者在... 目录NVM功能简介MAC安装实践一、下载nvm二、安装nvm三、安装node.js总结NVM功能简介N

linux如何复制文件夹并重命名

《linux如何复制文件夹并重命名》在Linux系统中,复制文件夹并重命名可以通过使用“cp”和“mv”命令来实现,使用“cp-r”命令可以递归复制整个文件夹及其子文件夹和文件,而使用“mv”命令可以... 目录linux复制文件夹并重命名我们需要使用“cp”命令来复制文件夹我们还可以结合使用“mv”命令总

Spring Boot 3 整合 Spring Cloud Gateway实践过程

《SpringBoot3整合SpringCloudGateway实践过程》本文介绍了如何使用SpringCloudAlibaba2023.0.0.0版本构建一个微服务网关,包括统一路由、限... 目录引子为什么需要微服务网关实践1.统一路由2.限流防刷3.登录鉴权小结引子当前微服务架构已成为中大型系统的标

Linux使用cut进行文本提取的操作方法

《Linux使用cut进行文本提取的操作方法》Linux中的cut命令是一个命令行实用程序,用于从文件或标准输入中提取文本行的部分,本文给大家介绍了Linux使用cut进行文本提取的操作方法,文中有详... 目录简介基础语法常用选项范围选择示例用法-f:字段选择-d:分隔符-c:字符选择-b:字节选择--c

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

Linux使用nload监控网络流量的方法

《Linux使用nload监控网络流量的方法》Linux中的nload命令是一个用于实时监控网络流量的工具,它提供了传入和传出流量的可视化表示,帮助用户一目了然地了解网络活动,本文给大家介绍了Linu... 目录简介安装示例用法基础用法指定网络接口限制显示特定流量类型指定刷新率设置流量速率的显示单位监控多个

ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法

《ElasticSearch+Kibana通过Docker部署到Linux服务器中操作方法》本文介绍了Elasticsearch的基本概念,包括文档和字段、索引和映射,还详细描述了如何通过Docker... 目录1、ElasticSearch概念2、ElasticSearch、Kibana和IK分词器部署