tasklet+kthread+workqueue使用记录

tasklet+kthread+workqueue使用记录


linux的任务调度机制太高深了,目前只能做到会用这三种结构。但具体什么情况哪种性能更高却没法详细的总结下来,还需多做项目多积累啊。。。。linux是个坑。。。本篇仅记录下

tasklet

  • 结构体定义
struct my_bus {
  ... ...
  struct tasklet_struct run_tasklet;  
};
  • tasklet待执行的函数
void exec_tasklet(void *data){ 
    struct my_bus *bus_if = (struct my_bus *)data;
    do{
        ... ...
        if(退出条件)
            break;
    }while(1);
}
  • 初始化tasklet
struct my_bus *bus_if;
... ...
tasklet_init(&bus_if->run_tasklet,
         (void(*)(unsigned long))exec_tasklet,
         (unsigned long)bus_if);
  • 停止tasklet
struct my_bus *bus_if;
... ...
tasklet_kill(&bus_if->run_tasklet);
  • 调度tasklet
struct my_bus *bus_if;
... ...
tasklet_schedule(&bus_if->run_tasklet);

tasklet特点:

  • 可响应中断
  • 不可睡眠或阻塞
  • 在软中断上实现的
  • 同一个tasklet不可在多个CPU上运行
  • 执行的操作是原子的
  • 同一个tasklet只能在最初被提交的CPU上运行

kthread

  • 结构体定义
struct my_bus {
  ... ...
  struct completion run_trgg;//这里用了completion机制
  struct task_struct *run_thread;
};

如果线程不需要频繁调用的话,或是会有线程休眠的情况,则用schedule_timeout等函数令线程进入休眠状态后,若需要调用时再wake_up_process唤醒该线程。

若是频繁用到该线程,则可用completion机制来实现调用。即线程状态一直处于running,内部函数用while(1)保证一直循环运行,但是真正对处理函数的调用要等待complete信号被触发以后才执行。

  • kthread待执行的函数
void exec_thread(void *data){ 
    struct my_bus *bus_if = (struct my_bus *)data;
    struct sched_param param = { .sched_priority = 1 };
    param.sched_priority = ...;//值越高优先级越高
    sched_setscheduler(current, SCHED_FIFO, &param);//优先级有SCHED_OTHER、SCHED_RR、SCHED_FIFO
    while (1) {
        if(kthread_should_stop()) {
            printk("run_thread stop\n");
            break;
        }
        if (!wait_for_completion_interruptible(&bus_if->run_trgg)) {
            if(bus_if->state == BUS_DOWN_ST)
                break;
            ... ...//一些要运行的操作
        }
    }
}

RR-时间片轮转调度算法 FIFO-先来先服务调度算法

  • 初始化thread和completion
struct my_bus *bus_if;
... ...
init_completion(&bus_if->run_trgg);
bus_if->run_thread= kthread_run(exec_thread, (void *)bus_if, "my_thread");
  • 停止thread
struct my_bus *bus_if;
... ...
if (bus_if->run_thread) {
        complete(&bus_if->run_trgg);
        kthread_stop(bus_if->run_thread);
        bus_if->run_thread= NULL;
}
  • 调度thread
struct my_bus *bus_if;
... ...
complete(&bus_if->run_trgg);

kthread特点:

  • 是内核调度基本单位
  • 只运行在内核态
  • 可选择调度算法及线程优先级

workqueue

  • 结构体定义
struct my_bus {
  ... ...
  struct work_struct work;
  struct workqueue_struct *wq;
};
  • workqueue待执行的函数
void work_queue_task(struct work_struct *mywork){   
    ... ...
    while (1) {
       if(退出条件)
           break;
    }
}
  • 初始化work和workqueue
struct my_bus *bus_if;
... ...
INIT_WORK(&bus_if->work, work_queue_task);
bus_if->wq= create_singlethread_workqueue("my_wq");
  • workqueue释放
struct my_bus *bus_if;
... ...
memset(bus_if, 0, sizeof(*bus_if));
  • 调度workqueue
struct my_bus *bus_if;
... ...
queue_work(bus_if->wq, &bus_if->work); 

workqueue特点:

  • 允许休眠
  • 系统负载大时,worker_thread(为处理工作队列调度的线程)会自己降低优先级,会延迟工作队列执行的操作
  • 可将任务推后,交给一个内核线程执行
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值