kthread_create和kernel_thread的区别和总结
来源:互联网 发布:剪裁图片大小的软件 编辑:程序博客网 时间:2024/05/16 09:36
在看linux驱动代码的时候,经常惠会碰到kthread_create这个函数,google一下,发现很多人在讲二者的区别,但是都在讲源码的区别而已,总结不够,感觉没有说出二者之间的本质区别,自己总结下。
一. 源码分析(linux-2.6.39)
1. kthread_create源码分析
- #define kthread_create(threadfn, data, namefmt, arg...)/ kthread_create_on_node(threadfn, data,-1, namefmt, ##arg)
- 149 struct task_struct *kthread_create_on_node(int(*threadfn)(void*data),
- 150 void *data,
- 151 int node,
- 152 const char namefmt[],
- 153 ...)
- 154 {
- 155 struct kthread_create_info create;
- 156
- 157 create.threadfn = threadfn;
- 158 create.data = data;
- 159 create.node = node;
- /*kthread_create采用了完成量机制,不明白的同学可以先去查阅下等待量机制的原理*/
- 160 init_completion(&create.done);
- 161
- 162 spin_lock(&kthread_create_lock);
- /*注意这个全局链表kthread_create_list, 所用通过kthread_create创建的内核线程都会挂在这*/
- 163 list_add_tail(&create.list,&kthread_create_list);
- 164 spin_unlock(&kthread_create_lock);
- /*这是最重要的地方,从代码看是唤醒了kthreadd_task这个进程,如果对代码比较熟悉的话,就会想到这是内核中 的1号进程kthreadd*/
- 166 wake_up_process(kthreadd_task);
- /*当前进程在完成量上睡眠等待*/
- 167 wait_for_completion(&create.done);
- 168
- 169 if (!IS_ERR(create.result)){
- 170 static const struct sched_param param = { .sched_priority= 0};
- 171 va_list args;
- 172
- 173 va_start(args, namefmt);
- 174 vsnprintf(create.result->comm, sizeof(create.result->comm),
- 175 namefmt, args);
- 176 va_end(args);
- 177 /*
- 178 * root may have changed our (kthreadd's) priorityor CPU mask.
- 179 * The kernel thread should not inherit these properties.
- 180 */
- 181 sched_setscheduler_nocheck(create.result, SCHED_NORMAL,¶m);
- 182 set_cpus_allowed_ptr(create.result, cpu_all_mask);
- 183 }
- 184 return create.result;
- 185 }
具体讲解参见注释,上面代码的执行路径跳转到kthreadd这个内核线程,下面分析下kthreadd的代码:
- 249
- 250 int kthreadd(void*unused)
- 251 {
- 252 struct task_struct *tsk = current;
- 253
- 254 /* Setup a clean contextfor our childrento inherit.*/
- /*上面这段注释尤为重要,个人认为这就是kthread_create和kernel_thread的本质区别,对current做了一些 /*处理:设置当前进程的进程名,清空当前进程的信号等,都是为了保证一个干净的上下文环境*/
- 255 set_task_comm(tsk,"kthreadd");
- 256 ignore_signals(tsk);
- 257 set_cpus_allowed_ptr(tsk, cpu_all_mask);
- 258 set_mems_allowed(node_states[N_HIGH_MEMORY]);
- 259
- 260 current->flags|= PF_NOFREEZE| PF_FREEZER_NOSIG;
- 261
- 262 for (;;){
- 263 set_current_state(TASK_INTERRUPTIBLE);
- 264 if (list_empty(&kthread_create_list))
- 265 schedule(); /*如果没有内核线程需要创建,即不是通过kthread_create入口进来的,当前进程就应该调度*/
- 266 __set_current_state(TASK_RUNNING);
- 267
- 268 spin_lock(&kthread_create_lock);
- 269 while (!list_empty(&kthread_create_list)){ /*遍历全局链表kthread_create_list,创建内核线程*/
- 270 struct kthread_create_info *create;
- 271
- 272 create = list_entry(kthread_create_list.next,
- 273 struct kthread_create_info, list);
- 274 list_del_init(&create->list);
- 275 spin_unlock(&kthread_create_lock);
- 276
- 277 create_kthread(create);/代码执行路径转入create_kthread/
- 278
- 279 spin_lock(&kthread_create_lock);
代码执行路径转到create_kthread。
- 112 static void create_kthread(struct kthread_create_info*create)
- 113 {
- 114 int pid;
- 115
- 116 #ifdef CONFIG_NUMA
- 117 current->pref_node_fork= create->node;
- 118 #endif
- 119 /* We want our own signal handler(we take no signals by default).*/
- 120 pid = kernel_thread(kthread, create, CLONE_FS| CLONE_FILES| SIGCHLD);
- 121 if (pid< 0){
- 122 create->result= ERR_PTR(pid);
- 123 complete(&create->done);
- 124 }
- 125 }
- 126
这里我们看到了kernel_thread,而且通过kthread_create入口进来的内核线程创建路径都具有统一的线程函数kthread。
- 74 static int kthread(void*_create)
- 75 {
- 76 /* Copy data: it'son kthread's stack*/
- 77 struct kthread_create_info *create = _create;
- 78 int (*threadfn)(void*data)= create->threadfn;
- 79 void *data = create->data;
- 80 struct kthread self;
- 81 int ret;
- 82
- 83 self.should_stop = 0;
- 84 self.data = data;
- 85 init_completion(&self.exited);
- 86 current->vfork_done=&self.exited;
- 87
- 88 /* OK, tell user we're spawned, waitfor stop or wakeup*/
- /*这里需要注意:创建的新的内核线程被置为TASK_UNINTERRUPTIBLE,需要显示的被唤醒才能运行*/
- 89 __set_current_state(TASK_UNINTERRUPTIBLE);
- 90 create->result= current;
- 91 complete(&create->done); /*这里显示的唤醒在完成量上等待的进程,然后发生调度,唤醒的是调用kthread_create函数的进程*/
- 92 schedule();
- 93
- 94 ret = -EINTR;
- 95 if (!self.should_stop)
- 96 ret = threadfn(data);
- 97
- 98 /* we can't just return, we must preserve"self"on stack*/
- 99 do_exit(ret);
- 100 }
到此为止,一共出现了这么几个进程(线程):(本文中进程和线程不做区分)
(1)调用kthread_create的进程,假设为进程A
(2)kthreadd进程
(3)新创建的进程,假设为进程B
整个执行流程为:
A调用kthread_create, 然后在kthread_create中唤醒kthreadd进程,A进程自己在完成量上睡眠,等待kthreadd进程创建过程完成,当kthreadd最后创建完新进程B,即kthread函数中,再去唤醒睡眠的进程A,如果B进程想要运行,还要显示的对他唤醒。
二 区别总结
上面分析了kthread_create和kernel_thread的代码的不同部分,其中也提到了几点不同,现在总结一下:
(1)最重要的不同:kthread_create创建的内核线程有干净的上那上下文环境,适合于驱动模块或用户空间的程序创建内核线程使用,不会把某些内核信息暴露给用户程序
(2)二者创建的进程的父进程不同: kthread_create创建的进程的父进程被指定为kthreadd, 而kernel_thread创建的进程可以是init或其他内核线程。
- kthread_create和kernel_thread的区别和总结
- kthread_create和kernel_thread的区别和总结
- kthread_create和kernel_thread的区别和总结
- kthread_create和kernel_thread的区别和总结
- kthread_create和kernel_thread的区别和总结 (转)
- kthread_create函数和kernel_thread函数的区别
- kthread_create与kernel_thread的区别
- kthread_create与kernel_thread的区别
- kthread_create与kernel_thread的区别
- kthread_create与kernel_thread的区别
- kthread_create与kernel_thread的区别
- kthread_create与kernel_thread的区别
- kthread_create与kernel_thread的区别
- 说说内核线程(kthread_create 和 kernel_thread的区别就在于前者多加了个链表)
- kthread_run() 和 kthread_create() 关系
- 内核线程创建: kthread_create vs kernel_thread
- 内核sem、wait_queue_head_t、timer和kernel_thread使用驱动范例
- 内核sem、wait_queue_head_t、timer和kernel_thread使用驱动范例
- hdu1251
- web系统中使用js调用activex打印费用报销单
- 结合WireShark工具学习TCP协议
- Webservice_20_SOAP的基于契约优先头信息处理(隐式头信息)
- scanner
- kthread_create和kernel_thread的区别和总结
- linux_电源管理
- mac安装插件失败,提示“无法打开Plugins替身,因为找不到其原身”
- Android_LayoutInflater的作用与用法详解
- android学习笔记1 menu和actionBar学习笔记
- 抽象工厂模式-与-工厂方法模式区别
- 数据操作流
- OPENCV 滤波
- JavaSE基础之Java语言(JDK中的命令行工具)