在Linux内核中,创建线程函数为__kthread_create_on_node(),需要注意的是


内核创建一个内核线程是个异步过程。


函数__kthread_create_on_node对外提供两个函数


一,__kthread_create_worker


二,kthread_create_on_node


当然我们主要使用二这种形式。对于二这种形式,内核简单定义了宏:


#define kthread_create(threadfn, data, namefmt, arg...) \  kthread_create_on_node(threadfn, data, NUMA_NO_NODE, namefmt, ##arg)


这样方便通过kthread_create来创建内核线程。


 


需要注意,__kthread_create_on_node()函数并不执行真正的内核线程创建,而是创建一个对象,然后把对象递交一个


链表上面,唤醒创建内核线程的线程来执行创建。而原先的创建者则进行等待。


这里封装的数据结构为struct kthread_create_info。


存放在kthread_create_list链表上面。


创建线程的线程是kthreadd,其在内核启动的早期初始化。


static noinline void __ref rest_init(void)
{
 int pid;
 kernel_thread(kernel_init, NULL, CLONE_FS);
 numa_default_policy();
 pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);
 rcu_read_lock();
 kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);

}

 

int kthreadd(void *unused)
{
 struct task_struct *tsk = current;
 /* Setup a clean context for our children to inherit. */
 set_task_comm(tsk, "kthreadd");
 ignore_signals(tsk);
 set_cpus_allowed_ptr(tsk, cpu_all_mask);
 set_mems_allowed(node_states[N_MEMORY]);
 current->flags |= PF_NOFREEZE;
 for (;;) {
  set_current_state(TASK_INTERRUPTIBLE);
  if (list_empty(&kthread_create_list))如果为真,继续放弃CPU。
   schedule();
  __set_current_state(TASK_RUNNING);设置内核线程状态
  spin_lock(&kthread_create_lock);
  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);
   spin_unlock(&kthread_create_lock);
   create_kthread(create);//真正创建处理
   spin_lock(&kthread_create_lock);
  }
  spin_unlock(&kthread_create_lock);
 }
 return 0;
}

 
 
 
static void create_kthread(struct kthread_create_info *create)
{
 int pid;
#ifdef CONFIG_NUMA
 current->pref_node_fork = create->node;
#endif
 /* We want our own signal handler (we take no signals by default). */
 pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD);
需要注意这里给的是kthread,所以,所有的内核线程第一个函数都是kthread
 if (pid < 0) {
  /* If user was SIGKILLed, I release the structure. */
  struct completion *done = xchg(&create->done, NULL);
  if (!done) {
   kfree(create);
   return;
  }
  create->result = ERR_PTR(pid);
  complete(done);唤醒原先需要创建线程的线程
 }
}

 
pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
{
 return _do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn,
  (unsigned long)arg, NULL, NULL, 0);fork处理
}