Linux学习笔记之内核线程

Posted 学习笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux学习笔记之内核线程相关的知识,希望对你有一定的参考价值。

本文旨在简单介绍一下Linux内核线程:

先举个例子:

不插U盘,在Linux命令行中输入:ps -el;然后插上U盘,再次输入:ps -el

会发现多出了下面一行(当然还会有其他的,比如scsi相关的):

1 F S   UID   PID  PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
2 1 S     0  2749   2 0  80   0 -     0 -      ?        00:00:00 usb-storage

usb-storage 就是U盘驱动程序(驱动程序是动态加载的)起来之后,由内核创建的内核线程。下面我们就来看一下它是如何被创建的。有关usb-storage的完整内容,以后学习USB驱动时再详解,今天只讨论内核是如何管理内核线程的创建的。

 

在启动过程中,Linux2.6.22.6/init/main.c::rest_init()会创建另外2个进程(1号进程kernel_init和2号进程kthreadd),今天我们要讨论的就是2号进程kthreadd,它是所有内核线程(比如上面的usb-storage)的父进程。

 1 static void noinline __init_refok rest_init(void)
 2     __releases(kernel_lock)
 3 {
 4     int pid;
 5 
 6     kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); // 创建1号进程
 7     numa_default_policy();
 8     pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);  // 创建2号进程 kthreadd
 9     kthreadd_task = find_task_by_pid(pid);
10     unlock_kernel();
11     ....
12 }

 

kthreadd()位于Linux2.6.22.6/kernel/kthread.c,今天我们主要就是分析这支文件。

kthreadd进程被创建之后就开始运行,我们看到他有一个死循环(for),他会一直去判断链表kthread_create_list中是否有内容,如果有,就根据链表的元素去创建一个内核线程。而函数kthread_create()会向链表kthread_create_list中插入元素(代码这里就不贴了)。

 1 int kthreadd(void *unused)
 2 {
 3     /* Setup a clean context for our children to inherit. */
 4     kthreadd_setup();
 5 
 6     current->flags |= PF_NOFREEZE;
 7 
 8     for (;;) {
 9         set_current_state(TASK_INTERRUPTIBLE);  // 设置进程状态: 可中断的等待状态
10         if (list_empty(&kthread_create_list))  // 如果链表为空
11             schedule();
12     
13         __set_current_state(TASK_RUNNING);
14 
15         spin_lock(&kthread_create_lock);
16         while (!list_empty(&kthread_create_list)) {
17             struct kthread_create_info *create;
18 
19             create = list_entry(kthread_create_list.next,
20                         struct kthread_create_info, list);
21             list_del_init(&create->list);
22             spin_unlock(&kthread_create_lock);
23 
24             create_kthread(create);   // 他会调用kernel_thread完成真正的内核线程创建
25 
26             spin_lock(&kthread_create_lock);
27         }
28         spin_unlock(&kthread_create_lock);
29     }
30 
31     return 0;
32 }

 

U盘驱动程序的内核线程是如何被创建的呢? 就是通过下面这段代码(位于Linux2.6.22.6/driver/usb/storage/usb.c):

1 /* Start up our control thread */
2     th = kthread_create(usb_stor_control_thread, us, "usb-storage"); // 
3     if (IS_ERR(th)) {
4         printk(KERN_WARNING USB_STORAGE 
5                "Unable to start control thread\\n");
6         return PTR_ERR(th);
7     }

 

下面通过一张图来总结一下:

 

以上是关于Linux学习笔记之内核线程的主要内容,如果未能解决你的问题,请参考以下文章

学习笔记

20179223《Linux内核原理与分析》第十一周学习笔记

(笔记)Linux内核学习之内核介绍

(笔记)Linux内核学习之内核内存管理方式

(笔记)Linux内核学习之内核同步机制和实现方式

学习笔记 深入理解Linux内核第三版 —— 第三章 进程