Linux内核实现透视---kthread_work - Little_Village - 博客园
kthreadd-linux下2号进程 - yuxi_o - 博客园
kthread_create_worker函数创建worker:
struct kthread_worker *
kthread_create_worker(unsigned int flags, const char namefmt[], ...)
{
struct kthread_worker *worker;
va_list args;
va_start(args, namefmt);
worker = __kthread_create_worker(-1, flags, namefmt, args);
va_end(args);
return worker;
}
__kthread_create_worker函数创建线程并绑定worker,即一个worker对应一个线程:
static struct kthread_worker *
__kthread_create_worker(int cpu, unsigned int flags,
const char namefmt[], va_list args)
{
struct kthread_worker *worker;
struct task_struct *task;
int node = -1;
worker = kzalloc(sizeof(*worker), GFP_KERNEL);
kthread_init_worker(worker);
if (cpu >= 0)
node = cpu_to_node(cpu);
//创建线程
task = __kthread_create_on_node(kthread_worker_fn, worker,
node, namefmt, args);
if (cpu >= 0)
kthread_bind(task, cpu);
worker->flags = flags;
//一个worker对应一个线程
worker->task = task;
wake_up_process(task);
return worker;
}
线程对应的处理函数,从该处理函数中可以看出:该线程在不断调用worker链表里的work->func(work),直到worker链表为空。
int kthread_worker_fn(void *worker_ptr)
{
struct kthread_worker *worker = worker_ptr;
struct kthread_work *work;
worker->task = current;
if (worker->flags & KTW_FREEZABLE)
set_freezable();
repeat:
set_current_state(TASK_INTERRUPTIBLE); /* mb paired w/ kthread_stop */
if (kthread_should_stop()) {
__set_current_state(TASK_RUNNING);
worker->task = NULL;
return 0;
}
work = NULL;
if (!list_empty(&worker->work_list)) {
//worker链表中取出work,并将它从worker链表中删除
work = list_first_entry(&worker->work_list,struct kthread_work, node);
list_del_init(&work->node);
}
worker->current_work = work;
if (work) {
__set_current_state(TASK_RUNNING);
//work->func(work)都是在一个线程内被执行
work->func(work);
} else if (!freezing(current))
schedule();
try_to_freeze();
cond_resched();
//进入循环遍历
goto repeat;
}
__kthread_create_on_node创建内核线程 ,创建内核线程又与kthreadd线程相关。
static struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
void *data, int node,
const char namefmt[],
va_list args)
{
DECLARE_COMPLETION_ONSTACK(done);
struct task_struct *task;
struct kthread_create_info *create = kmalloc(sizeof(*create), GFP_KERNEL);
//所创线程的threadfn线程处理函数是在kthreadd线程里的一个kthread线程内被调用。
create->threadfn = threadfn;
create->data = data;
create->node = node;
create->done = &done;
//该线程链表被kthreadd线程维护的
list_add_tail(&create->list, &kthread_create_list);
//唤醒kthreadd线程
wake_up_process(kthreadd_task);
if (unlikely(wait_for_completion_killable(&done))) {
if (xchg(&create->done, NULL))
return ERR_PTR(-EINTR);
wait_for_completion(&done);
}
task = create->result;
kfree(create);
return task;
}
kthreadd:管理和调度其他内核线程kernel_thread, 会循环执行一个kthreadd的函数,该函数的作用就是运行kthread_create_list全局链表中维护的kthread, 当我们调用kthread_create创建的内核线程会被加入到此链表中,因此所有的内核线程都是直接或者间接的以kthreadd为父进程。所有的内核线程的PPID都是2。
在linux启动的C阶段start_kernel()的最后,rest_init()会开启两个进程:kernel_init,kthreadd,之后主线程变成idle线程。
static noinline void __ref rest_init(void)
{
struct task_struct *tsk;
int pid;
pid = kernel_thread(kernel_init, NULL, CLONE_FS);
......
pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
......
}
相关数据结构定义:
static DEFINE_SPINLOCK(kthread_create_lock);
static LIST_HEAD(kthread_create_list);
struct task_struct *kthreadd_task;
struct kthread_create_info
{
/* Information passed to kthread() from kthreadd. */
int (*threadfn)(void *data);
void *data;
int node;
/* Result passed back to kthread_create() from kthreadd. */
struct task_struct *result;
struct completion done;
struct list_head list;
};
struct kthread {
int should_stop;
void *data;
struct completion exited;
};
kthreadd线程处理函数:
int kthreadd(void *unused)
{
struct task_struct *tsk = current;
......
for (;;) {
set_current_state(TASK_INTERRUPTIBLE);
//kthread_create_list链表为空,挂起
if (list_empty(&kthread_create_list))
schedule();
__set_current_state(TASK_RUNNING);
//为kthread_create_list链表中的每个kthread_create_info成员创建对应的线程
while (!list_empty(&kthread_create_list)) {
struct kthread_create_info *create;
create = list_entry(kthread_create_list.next,
struct kthread_create_info, list);
list_del_init(&create->list);
//创建kthread线程,该线程就是为每个kthread_create_info变量创建的对应的线程
create_kthread(create);
}
}
return 0;
}
static void create_kthread(struct kthread_create_info *create)
{
int pid;
//create对应的线程就是ktread线程
pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
if (pid < 0) {
create->result = ERR_PTR(pid);
complete(&create->done);
}
}
kthread线程处理函数:
static int kthread(void *_create)
{
struct kthread_create_info *create = _create;
int (*threadfn)(void *data) = create->threadfn;
void *data = create->data;
struct kthread self;
int ret;
self.should_stop = 0;
self.data = data;
init_completion(&self.exited);
current->vfork_done = &self.exited;
__set_current_state(TASK_UNINTERRUPTIBLE);
//create对应的线程就是ktreadd线程创建的kthead线程
create->result = current;
complete(&create->done);
//线程创建完成,挂起,等待唤醒
schedule();
ret = -EINTR;
if (!self.should_stop)
//执行上面传下来的新创建的线程的处理函数
ret = threadfn(data);
/* we can't just return, we must preserve "self" on stack */
do_exit(ret);
}