Linux OS内核 作业一:kthread和workqueue
实验题目:http://gauss.ececs.uc.edu/Courses/c4029/labs/lab2.html题目是来自国外某知名大学的作业。具体翻译就不说了,大致就是用kthread和workqueue循环打印日志。因为是第一次编译内核模块,而且c语言的水平也是渣渣,所以中间遇到了不少的坑。写在这里,大家共勉。
·
实验题目:
题目是来自国外某知名大学的作业。具体翻译就不说了,大致就是用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.o
all :
make -C /lib/modules/$(shell uname -r)/build M=$(shell pwd) modules
clean:
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;
//定义workqueue
struct 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内核 作业三:设备驱动与读写信号量
更多推荐
已为社区贡献1条内容
所有评论(0)