概述
方法1:通过信号量条件唤醒线程,首先可以在driver的probe函数中先创建并启动线程
1. wait_queue_head_t thread_wq;
init_waitqueue_head(&thread_wq); 通常先要在init函数中初始化一个thread_wq,该thread_wq 用作到时候线程唤醒的信号量队列
2. 通常在probe或者在init等接口中就通过kthread_run接口去创建好线程并run,kthread_run函数不能再中断函数中调用,因为会有阻塞导致报错中断中 BUG: scheduling while atomic: swapper/0/0/0x00000102。
struct task_struct *kthread;
kthread= kthread_run(thread_func, arg, "thread_func");
if(IS_ERR(kthread)){
printk("error: Unable to start kernel thread.n");
}
3. 这个时候线程就开始run了,打印"the system is start" 但是阻塞到wait_event_interruptible_timeout中,等待 thread_flag == 1 且 wake_up_interruptible_all(&thread_wq), 才能打印thread running,通常在while循环中会考虑将thread_flag 清0。重新进入阻塞态,待重新唤醒。其中kthread_should_stop 接口是判定该进程是否退出,当进程退出时,本线程就会kthread_should_stop 会置上(在driver unregister时候),此处不用while(1) 是为了避免线程二次退出导致kernel crash的现象(在driver unregister前被kill了一次,driver unregister时候再stop一次)。
int thread_flag = 0;
int thread_func(void *arg){
printk("#### the system is startn");
while(!kthread_should_stop()){
wait_event_interruptible_timeout(thread_wq, thread_flag == 1, 1),
printk("#### thread runningn");
}
printk("#### the system is exitn");
return 0;
}
4. ISR(中断服务程序)中,或者其它需要唤醒线程的地方,通过信号量。
copy_frame_run_flag = 1; 将thread_func中等待条件置上
wake_up_interruptible_all(&thread_wq) ;
5. 正常kthread_stop函数会在driver unregister时候去将线程stop掉,会保证进程退出时候 kthread_should_stop通常会置1
kthread_stop(kthread);
thread_flag = 0;
方法2:直接用调度的方法去让线程运行
1. struct task_struct *thread_task_p; 创建线程句柄
2. 通常在probe或者在init等接口中就通过kthread_create 接口去创建,但是不运行。
thread_flag = 1;
thread_task_p = kthread_create(thread_func, iav, "thread_func");
printk("############## thread_flag = %dn",thread_flag );
3. 线程调度函数此时为就绪态了
int thread_func(void *arg){
while(1){
set_current_state(TASK_UNINTERRUPTIBLE); //线程处于等待状态,不可中断,等待wake_up_process 就可以起来。
if (??){
thread_flag = 0;
} else {
thread_flag = 1;
}
if(thread_flag ){
printk("############## thread running n");
} else {
printk("####thread schedulen");
schedule(); //将线程cpu调度出去
set_current_state(TASK_RUNNING); //将线程设置为就绪态,等待cpu时间片调度。
ssleep(5);
}
}
return 0;
}
4. ISR(中断服务程序)中,或者其它需要唤醒线程的地方,去将线程唤醒。
thread_flag = 1;
wake_up_process(thread_task_p);
}
5. 正常kthread_stop函数会在driver unregister时候去将线程stop掉
kthread_stop(thread_task_p);
thread_flag = 0;
备注:如想对进程理解比较深入,可以参考这个文章
https://blog.csdn.net/weixin_34293911/article/details/86356832?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase
最后
以上就是眼睛大银耳汤为你收集整理的1: linux 内核态下的多线程开发的全部内容,希望文章能够帮你解决1: linux 内核态下的多线程开发所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复