linux进程延迟函数,linux内核延时操作

linux内核延时操作

系统为了实现中断的快速处理,将中断处理程序分为处理中断请求的上半部和延时处理逻辑和I/O的下半部(buttom halves)。下半部的主要实现机制有两种:tasklet和workqueue。

tasklets

tasklet是软件中断(softirq)机制的一部分,tasklet运行在软件中断上下文中,所以有软件中断服务函数的所有要求,比如不能休眠。tasklet相对于软件中断有一些针对驱动编写的好处:

通过软件中断实现,回调函数不能睡眠

tasklet的分配是动态的,可以在内核运行时添加和删除

同类型的tasklet总是串行执行的,因为它的主要数据结构是per-cpu的,所以不需要人为使用spinlock。但是不同的tasklet则可以并发地在不同cpu上运行。

tasklet的串行化使tasklet函数不必是可重入的。

不能访问用户态进程地址

softirq implementation

kernel/softirq.c

static __init int spawn_ksoftirqd(void); 创建softirq的内核线程,用于延迟处理过多的softirq,这是softirq处理速度和cpu公平性的一个折中处理。

kthread_create(run_ksoftirqd, hcpu, "ksoftirqd/%d", hotcpu); 设置内核线程的回调函数run_ksoftirqd

static int run_ksoftirqd(void * __bind_cpu); 内核线程回调,if (local_softirq_pending()) __do_softirq();如果本地cpu有待处理的softirq,则调用softirq的处理函数

asmlinkage void __do_softirq(void); 根据softirq_vec对应中对应的位来调用相应的action,循环处理所有待处理的softirq,处理过程中间如果有新来的softirq则会重新处理maxrestart这么多次。如果处理maxrestart次之后还有待处理的softirq则会重新调度ksoftirqd继续处理。

tasklet implementation

void __init softirq_init(void);初始化softirq, 调用open_softirq(TASKLET_SOFTIRQ, tasklet_action); 将tasklet的回调函数tasklet_action注册到softirq的处理函数中。这样在有tasklet对应的softirq处理时就会调用tasklet_action。

static void tasklet_action(struct softirq_action *a);这个函数主要有两个功能:

t->func(t->data);如果tasklet需要被调度,则运行它的回调函数

tasklet_trylock(t);测试tasklet是否在其他cpu上运行, test_and_set_bit(TASKLET_STATE_RUN, &(t)->state); 如果正在其他cpu上运行则重新发softirq请求延迟执行, __raise_softirq_irqoff(TASKLET_SOFTIRQ);

workqueue

kernel/workqueue.c

工作队列的具体实现比较复杂,但是它的原理很简单,就是创建内核线程来执行函数。

主要的实现函数

static void process_one_work(struct worker *worker, struct work_struct *work) 在worker线程上调用struct work_struct的回调函数。

主要的接口

请参考linux/workqueue.h

主要特点

用内核线程实现,运行在进程上下文,回调函数可以睡眠

在一个cpu上创建的work可能在其他cpu上运行

不能访问进程的用户态地址,因为这些内核线程没有相应的用户线程

可以指定延迟一段具体的时间执行

resources

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值