原创: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(..);
}
阅读(1307) | 评论(0) | 转发(0) |