首页 > 学院 > 开发设计 > 正文

Linux OS内核 作业一:kthread和workqueue

2019-11-06 08:57:30
字体:
来源:转载
供稿:网友

实验题目:

http://gauss.ececs.uc.edu/Courses/c4029/labs/lab2.html

题目是来自国外某知名大学的作业。具体翻译就不说了,大致就是用kthread和workqueue循环打印日志。

因为是第一次编译内核模块,而且c语言的水平也是渣渣,所以中间遇到了不少的坑。

写在这里,大家共勉。

实验环境: uname -a linux GSX 3.10.0-514.6.2.el7.x86_64 #1 SMP Thu Feb 23 03:04:39 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

发行版本:CentOS 7

kthread

源码

#include <linux/kernel.h>#include <linux/module.h>#include <linux/timer.h>#include <linux/kthread.h>MODULE_LICENSE("GPL");static struct timer_list my_timer;static struct task_struct *ts;int id = 101;static int count = 0;//标志:如果function()运行结束,kthread也就结束,那么卸载内核模块的时候就不用调用kthread_stop(ts)函数(否则会出现严重错误);反之,需要调用kthread_stop(ts)函数来使kthread终止。static bool fun_flag = true;int function(void * data){ int n = *(int*)data;//注意到这里调用了kthread_should_stop()函数,用来检查终止信号:判断是继续执行还是终止执行 while(!kthread_should_stop() && count <10 ) { PRintk(KERN_EMERG "thread_function: %d data/n", n); count++; set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(HZ); } fun_flag = false; return 0;}//关键函数一:加载内核模块时调用int init_module( void ) { printk("Timer module installing/n"); ts = kthread_run(function,(void*)&id , "spawn"); return 0;}//关键函数二:卸载内核模块时调用void cleanup_module( void ) { if(fun_flag) { int ret = kthread_stop(ts); printk(KERN_INFO "thread has been stopped . %d", ret ); }else{ printk(KERN_INFO "kthread is already dead."); } return;}

编译:

#保存文件为Makefile。。。。注意一定是大写的Makefile,大写的M,M。。。。obj-m := kthread_module.oall : make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modulesclean: make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) clean

由于时间久远,忘了从那位大神博客那里弄来的Makefile文件,抱歉抱歉。。。 这个Makefile文件具有通用性。以后编译内核时,只需要修改开头的目标文件名,就可以了。欢迎收藏!

运行

#加载内核模块sudo insmod kthread_module.ko #在上面编译好后,会出现以ko结尾的文件#查看日志dmesg#卸载模块sudo remmod kthread_module

总结:万事开头难。。第一个作业就写了好久。。。。有了这个经验,后面的作业就很容易上手了哦。。。


workqueue

源码

#include <linux/kernel.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/workqueue.h>MODULE_LICENSE("GPL");struct workqueue_struct *queue;//定义workqueuestruct delayed_work *dwork;int count = 0;void function(struct work_struct *work){ printk(KERN_INFO "workqueue_function called/n"); if (count++ < 10) queue_delayed_work(queue, dwork, HZ );}//初始化模块时int init_module( void ) {//初始化workqueue queue = create_workqueue("queue"); dwork = (struct delayed_work*)kmalloc(sizeof(struct delayed_work), GFP_KERNEL); INIT_DELAYED_WORK((struct delayed_work*)dwork, function); queue_delayed_work(queue,dwork,HZ); return 0;}//卸载模块时void cleanup_module( void ) { if (dwork && delayed_work_pending(dwork)) cancel_delayed_work(dwork); flush_workqueue(queue); destroy_workqueue(queue); printk(KERN_EMERG "workqueue_module has been cleaned up!/n"); return;}

编译

同上

运行

同上


系列博客: 相信当你需要其中一个的时候,也一定需要剩下的两个 Linux OS内核 作业一:kthread和workqueue Linux OS内核 作业二:多线程访问 Linux OS内核 作业三:设备驱动与读写信号量


上一篇:如果爱可以重来

下一篇:子带编码

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表