1. 程式人生 > >Linux學習筆記之內核線程

Linux學習筆記之內核線程

出了 freeze rest eas time 進程 來看 inf span

本文旨在簡單介紹一下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學習筆記之內核線程