先看完成量
usb重要的内核线程
睡眠与唤醒
/**
看,完成量是由 等待队列 + 原子变量 来实现的。
那么,问题是 :
他们是怎么样来实现完成量的呢?
他的初始化函数会将done 设置为0
再complete()加1,wait_for_completion(以及他衍生出来的函数)减 1
再初始化函数中会初始化等待队列,
这里简单的说一下,具体的请往下看。有实验验证。
*/
struct completion {
unsigned int done;
wait_queue_head_t wait;
};
/**
这个函数 不会 timeout,哈哈。不像wait_for_completion_timeout()函数。
他们两个再内核中都会调用 schedule_timeout(timeout);只是传入的参数不同罢了。
那么wait_for_completion()传入的就是这个第二个参数 MAX_SCHEDULE_TIMEOUT。
而wait_for_completion_timeout()需要你传入一个时间,具体的欣赏再下面。
看他第三个参数,TASK_UNINTERRUPTIBLE,
这两个函数底层都会调用__set_current_state(state)函数,
都会将进程状态设置为 TASK_UNINTERRUPTIBLE。
*/
void __sched wait_for_completion(struct completion *x)
{
wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE);
}
static long __sched wait_for_common(struct completion *x, long timeout, int state)
{
might_sleep();
/**
这里有一个疑问。
再自旋锁保护的临界区 不能 调用有可能会睡眠的函数的。
但是 do_wait_for_common() 这个函数 最终可能会调用到 schedule();
这个又怎么解释?
*/
spin_lock_irq(&x->wait.lock);
/**
真正干活的是这个函数
*/
timeout = do_wait_for_common(x, timeout, state);
spin_unlock_irq(&x->wait.lock);
return timeout;
}
下面这幅图是我改动了内核源码打印出来的log
看内核线程

本文深入解析Linux内核中完成量的概念,包括其通过等待队列和原子变量实现的方式,并详细介绍了与之相关的函数和状态管理过程。通过实验验证,清晰展示了这些核心组件在系统级任务协调中的作用。

被折叠的 条评论
为什么被折叠?



