内核线程,tasklet异步通知,工作队列,内核延时

原创: blog.chinaunix.net/uid/23795897.html
内核创建线程:struct task_struct * kthread_creat(int(*threadfn)(void *data),void *data,const char namefmt[],...)
结束线程:int kthread_stop(struct task_struct *k)//调用此要确保线程已经退出,否则会一直等待。

例如:static struct task_struct *simple_thread;
init_module()
{
    simple_thread=kthread_run(threadfunc,NULL,"simple_thread");// 创建内核线程
}
int threadfunc(void *data)
{
    while(1)
    {
            set_currrent_state(TASK_UNINTERRUPTIBLE);
            if(kthread_should_stop())break;
            printk("threadfunc\n");
            schedule_timeout(HZ);
    }
    return 0;
}


exit_module()
{
    if(simple_thread)
    {
            kthread_stop(simple_thread);
            simple_thread=NULL;
    }

}

二、tasklet:
利用软中断的一种下半部机制,执行异步任务
初始化:void tasklet_init(struct tasklet_struct *t,void(*func)(unsigned long),unsingned long data);//或者:#define   DECLART_TASKLET(name,func,data)
调度: tasklet_schedule(struct tasklet_struct *t); 或者优先级更高的; tasklet_hi_schedule(struct tasklet_struct *t);   
例如:
DECLART_TASKLET(tasklet,tasklet_callback,0); //绑定

static irqreturn_t  irq_handler(int irq,void * arg)
{
        tasklet_schedule(&tasklet); //开始callback
         return     IRQ_HANDLED;
}

static void tasklet_callback(unsinged long data)
{
        printk("hello!");
}

删除:void tasklet_kill(struct task_struct *t);//如果tasklet 正在运行,函数会一直等知道执行完毕。
tasklet使能和禁止:
禁止:
void tasklet_disable(struct tasklet_struct *t); //禁止给定的tasklet被tasklet_schedule调度,如果该tasklet当前正在执行,这个函数会等到它执行完毕再返回。
void tasklet_disable_nosync(struct tasklet_struct *t)//不等待就返回。
使能:
void tasklet_enable(struct tasklet_struct * t);


三、工作队列:
struct workqueque_stuct * create_workqueque(const char *name); //创建一个工作队列,名字由name定。,如果是单个线程用creat_singlethread_workqueque.

DECLARE_WORK(name,void(*function)(void *),void *date);  //在编译时初始化一个工作队列的任务。
INIT_WORK(struct work_struct *work,void(*function)(void *),void *date) //运行时初始化。
 
int fastcall queque_work(...); //将作业加入工作队列中。
int fastcall queque_delayed_work(...);//delay,至少保存delaty时间工作队列的任务才能真正执行。

int cancel_delayed_work(..)//取消工作队列中没有运行的作业,如果有任务正在运行,那么这个任务将继续执行但不加入到队列中。

void fastcall  flush_workqueque(...) //确保调度队列中的工作队列执行完毕。

void destroy_workqueque(...);//销毁工作队列。

int  fastcall schedule_work(...);//将工作置入全局工作队列。

int fastcall  schedule_delayed_work(..);//延时一段时间将作业置入全局工作队列。




例如:
static struct work_struct task;

static struct workqueque_stuct  * my_workqueque;
 my_workqueque=create_workqueque(“MYQUENU”);

INIT_WORK(&task,DemoTask);

queque_work(my_workqueque,&task);

static void DemoTask(void * p)
{
    printk("hello");
    memset(demobuffer,0x31,256);
    wake_up_interruptible(&DEMO_devices->wq);
    printk("me");
}


对比:
比较点                    softirq                                            tasklet                                            work queque
执行上下文            中断上下文                                    中断上下文                                            进程上下文
可重用                可以在不同cpu            不能不同cpu,但不用cpu可运行不同tasklet                       可以不同cpu
睡眠                    不能                                                    不能                                                 可以睡眠
抢占/调度                不能                                                不能                                                       能
易用性                    不容易                                               容易                                                     容易


四、内核中的延时:
1)时钟周期:晶振在1s厂商的时钟脉冲。
2)时钟滴答;一次时钟中断产生一次时钟滴答。系统每几个时钟周期产生一次时钟滴答。
3)HZ表示时钟滴答的频率。
4)全局变量: jiffies ,32为无符号整数,表示内核上一次启动以来的时钟滴答数。
5)xtime,记载系统开机以来的当前时间。
6)时钟:硬件时钟和系统时钟。
void do_gettimeofday  //获取系统时间。
int   do_settimeofday  //配置系统。



sleep_on_timeout;
interrupt_sleep_on_timeout;

毫秒级别延时:
ndelay(n);udelay(n);mdelay(n); //这三个是忙等待。

msleep();msleep_interruptible();//不忙等待的短延时。

内核定时器:在某个时间执行程序段或进程。
void add_timer(struct timer_list * timer); //增加定时器
int  del_timer(struct timer_list * timer);
//删除未到的定时器,到期的定时器会自动删除。
int  mod_timer(struct timer_list * timer,unsigned long expires);//修改定时器。

例如:
struct simple_dev  *simple_devices;

struct  timeval start stop;
static  struct timer_list  simple_timer;

init_timer(&simple_timer);
simple_timer.function=&simple_timer_handler;
simple_timer.expires=jiffies+SIMPLE_TIMER_DELAY;

add_timer(&simple_timer);
//do_gettimerofdey(&start);

static void spmple_timer_handler(unsigned long data)
{
   // do_gettimeofday(&stop);
//  比较时间start ,和stop
    printk(..);
}











<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(64) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~
评论热议
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值