Linux進程管理知識整理(1)

來源:互聯網
上載者:User

1、進程有哪些狀態?什麼是進程的可中斷等待狀態?進程退出後為什麼要等待調度器刪除其task_struct結構?進程的退出狀態有哪些?

TASK_RUNNING可運行狀態)

TASK_INTERRUPTIBLE可中斷等待狀態)

TASK_UNINTERRUPTIBLE不可中斷等待狀態)

TASK_STOPPED進程被其它進程設定為暫停狀態)

TASK_TRACED進程被調試器設定為暫停狀態)

TASK_DEAD退出狀態)

進程由於所需資源得不到滿足,從而進入等待隊列,但是該狀態能夠被訊號中斷。比如當一個正在啟動並執行進程因進行磁碟I/O操作而進入可中斷等待狀態時,在I/O操作完成之前,使用者可以向該進程發送SIGKILL,從而使該進程提前結束等待狀態,進入可運行態,以便響應SIGKILL,執行進程結束代碼,從而結束該進程。

當進程退出時例如調用exit或者從main函數返回),需要向父進程發送訊號,父進程進行訊號處理時,需要擷取子進程的資訊,因此這時不能刪除子進程的task_struct。另外每個進程都有一個核心態的堆棧,當進程調用exit()時,在切換到另外一個進程前,總是要使用核心態堆棧,因此當進程調用exit()時,完成必要的處理後,就把state設定為TASK_DEAD,並切換到其他進程。當順利地切換到其他進程後,由於該進程的狀態設定為TASK_DEAD,因此這個進程不會被調度,之後當調度器檢查到狀態為TASK_DEAD的進程時,就會刪除這個進程的task_struct結構,這樣這個進程就徹底的消失了。

EXIT_ZOMBIE僵死進程):父進程等待子進程結束時發送的SIGCHLD訊號預設情況下,建立進程都會設定在進程退出的時候向父進程發送訊號的標誌,除非建立的是輕權進程),此時子進程已退出,並且SIGCHLD訊號已經發送,但是父進程還沒有被調度運行;EXIT_DEAD僵死撤銷狀態):父進程對子進程的退出訊號“沒興趣”,或者在子進程退出時,父進程通過waitpid()調用等待子進程的SIGCHLD訊號。

2、殭屍進程

1) 怎麼產生殭屍進程

一個進程在調用exit命令結束自己的時候,其實它並沒有真正的被銷毀,只是進程不能被調度並處於EXIT_ZOMBIE狀態,它佔用的所有記憶體就是核心棧、thread_info結構和task_struct結構。此時進程存在的唯一目的就是向它的父進程提供資訊,如果它的父進程沒有調用wait或waitpid等待子進程結束,又沒有顯示地忽略該訊號,那麼它就一直保持EXIT_ZOMBIE狀態。

2) 怎麼查看殭屍進程

利用命令ps,看到有標記為Z的進程就是殭屍進程。

3) 怎麼清理殭屍進程

  • 父進程可以調用waitpid、wait函數來等待子進程結束
  • 把父進程殺掉,父進程死後,殭屍進程成為“孤兒進程”,過繼給init進程,init進程始終負責清理殭屍進程,它產生的所有殭屍進程也跟著消失。

3、PID管理

在Linux系統中用pid結構體來標識一個進程,通過pidmap位元影像來管理所有的進程號(即pid:與前面的pid結構體不是同一個意思),目的就是要更快的找到目標進程。用pid結構體來表示進程的優點:比直接用數字pid_t更容易管理(進程退出時pid回收再分配效率高),比直接用task_struct標識進程佔用空間小。

pid結構體如下所示:

 
  1. struct pid 
  2. atomic_t count; 
  3. int nr;                          /*存放pid數值*/ 
  4. struct hlist_node pid_chain;        /*把該pid鏈到雜湊表中*/ 
  5. struct hlist_head tasks[PIDTYPE_MAX]; 
  6. struct rcu_head rcu; 
  7. }; 

因為對於32位系統來說,預設最大的pid為32768,由於pidmap位元影像中每一位表示這個pid是否可用,共需要32768位,正好一個物理頁的大小(4*1024*8)。

pidmap結構體如下所示:

 
  1. struct pidmap { 
  2.        /* 
  3.         *這個變數用來統計這個結構體對應的一頁實體記憶體中有多少個位 
  4.             *是0的,即空閑pid的數量 
  5.         */ 
  6.        atomic_t nr_free;  
  7.        void *page;      /*這個就是指向存放這個位元影像的記憶體頁的指標*/ 
  8. }; 

下面首先來看Linux核心啟動之初在start_kernel函數中對pidmap位元影像的初始化函數pidmap_init如下所示:

 
  1. void __init pidmap_init(void) 
  2.    /*申請一頁實體記憶體,並初始化為0*/ 
  3. init_pid_ns.pidmap[0].page = kzalloc(PAGE_SIZE, GFP_KERNEL); 
  4.   /*將第0位設定為1,表示當前進程使用pid為0,即現在就是0號進程*/ 
  5. set_bit(0, init_pid_ns.pidmap[0].page); 
  6.    /*同時更新nr_free統計空閑pid的值*/ 
  7. atomic_dec(&init_pid_ns.pidmap[0].nr_free); 
  8. pid_cachep = KMEM_CACHE(pid, SLAB_PANIC); 

再來看Linux核心啟動之初在start_kernel函數中對pid hash表的初始化函數pidhash_init如下所示:

 
  1. void __init pidhash_init(void) 
  2. int i, pidhash_size; 
  3.    /* 
  4.     *nr_kernel_pages表示核心記憶體總頁數,就是系統DMA和NORMAL內 
  5.         *存頁區的實際實體記憶體總頁數 
  6.     *megabytes:統計的是核心記憶體有多少MB 
  7.     */ 
  8. unsigned long megabytes = nr_kernel_pages >> (20 - PAGE_SHIFT); 
  9.   /*從下面兩行代碼可以看出pidhash_shift是在4~12之間的*/ 
  10. pidhash_shift = max(4, fls(megabytes * 4)); 
  11. pidhash_shift = min(12, pidhash_shift); 
  12. pidhash_size = 1 << pidhash_shift; 
  13. printk("PID hash table entries: %d (order: %d, %Zd bytes)\n", 
  14. pidhash_size, pidhash_shift, 
  15. pidhash_size * sizeof(struct hlist_head)); 
  16.    /* 
  17.    *由alloc_bootmem可知pid_hash是在低端實體記憶體申請的,由於 
  18.        *pidhash_init函數是在mem_init函數執行之前被調用的,所以這裡申請  
  19.        *的記憶體是不會被回收的 
  20.    */ 
  21. pid_hash = alloc_bootmem(pidhash_size * sizeof(*(pid_hash))); 
  22. if (!pid_hash) 
  23. panic("Could not alloc pidhash!\n"); 
  24. for (i = 0; i < pidhash_size; i++) 
  25.        /*初始化每個表的每個表項的鏈表*/ 
  26. INIT_HLIST_HEAD(&pid_hash[i]); 

總結:核心維護兩個資料結構來維護進程號pid,一個是雜湊表pid_hash,還有一個位元影像pidmap。在do_fork()中每調用一次alloc_pid(),首先會通過調用alloc_pidmap()修改相應的位元影像,該函數的主要思想是:last記錄上次分配的pid,此次分配的pid為last+1,如果pid超出最大值,那麼就迴圈回到最初值(RESERVED_PIDS),然後測試pidmap上該pid所對應的bit是否為0,直到找到為止。其次通過hlist_add_head_rcu函數在pid_hash表中增加一項。


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.