1: linux 内核态下的多线程开发

方法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 start\n");
    while(!kthread_should_stop()){
        wait_event_interruptible_timeout(thread_wq, thread_flag == 1, 1),

        printk("#### thread running\n");
    }
    printk("#### the system is exit\n");
    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 = %d\n",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 schedule\n");
            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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值