菜鳥隨筆(3)---三種進程學習.孤兒進程.殭屍進程.守護進程

一隻菜鳥橫空出世,碼農世界闖一闖,天天進展多一丟丟。linux

  

                        三種進程學習.孤兒進程.殭屍進程.守護進程apache

轉自https://blog.csdn.net/believe_s/article/details/77040494markdown

 

一、孤兒進程ssh

 

若是父進程先退出,子進程還沒退出那麼子進程將被 託孤給init進程,這裏子進程的父進程就是init進程(1號進程).其實仍是很好理解的。函數

 

// 父進程先子進程退出 // 子進程會被祖父進程接手並在後臺運行,執行內部的代碼 int main() { pid_t pid = fork(); switch (pid) { case -1: perror ("fork"); break; case 0: // 子進程 close (1); // 建立一個文件用來保存輸出的文字 int fd = open ("child", O_RDWR|O_CREAT, 0777); printf ("我是子進程,個人ID是%d\n", getpid()); while (1) { printf ("找爸爸\n"); fflush (stdout); sleep (2); } break; default: // 父進程 printf ("我是父進程:ID = %d\n", getpid()); printf ("我走啦\n"); while (1); break; } return 0; }

 

這裏寫圖片描述

 

這裏寫圖片描述

 

這裏寫圖片描述 
在這裏咱們運行了程序,能夠在另外一終端看到有2個a.out在運行,咱們將父進程終止,子進程並無退出,而是在後臺繼續運行,並向child文件中輸出文字。post

 

二、殭屍進程 
這裏寫圖片描述 
若是咱們瞭解過Linux進程狀態及轉換關係,咱們應該知道進程這麼多狀態中有一種狀態是僵死狀態,就是進程終止後進入僵死狀態(zombie),等待告知父進程本身終止,後才能徹底消失.可是若是一個進程已經終止了,可是其父進程尚未獲取其狀態,那麼這個進程就稱之爲殭屍進程.殭屍進程還會消耗必定的系統資源,而且還保留一些概要信息供父進程查詢子進程的狀態能夠提供父進程想要的信息.一旦父進程獲得想要的信息,殭屍進程就會結束.學習

 

// 子進程比父進程先退出 int main() { int count = 5; while (count--) { //signal(SIGCHLD,SIG_IGN); pid_t pid = fork(); switch (pid) { case -1: perror ("fork"); break; case 0: // 子進程 printf ("我是子進程,個人ID是%d\n", getpid()); printf ("我走啦\n"); exit (0); default: // 父進程 printf ("我是父進程,個人ID是%d\n", getpid()); //while(1); break; } } while(1); return 0; }

 

這裏寫圖片描述

 

signal(SIGCHLD,SIG_IGN);加上這行代碼後殭屍進程都消失了。 
這裏寫圖片描述 
經過ps -ef | grep a.out 咱們能夠得知進程信息和進程pid,能夠看到子進程就是處於defunct狀態.這時咱們確定想要怎麼才能避免殭屍進程呢?看程序被我註釋的那句signal(SIGCHLD,SIG_IGN),加上就不會出現殭屍進程了.那咱們就加點篇幅講一下爲何就能夠避免殭屍進程呢? 
這是signal()函數的聲明sighandler_t signal(int signum, sighandler_t handler),咱們能夠得出,signal函數的第一個函數是linux支持的信號,第二個參數是對信號的操做 ,是系統默認仍是忽略或捕獲.咱們這是就能夠知道signal(SIGCHLD,SIG_IGN)是選擇對子程序終止信號選擇忽略,這是殭屍進程就是交個內核本身處理,並不會產生殭屍進程.ui

 

三、守護進程 
一樣咱們須要瞭解一下什麼是守護進程,守護進程就是在後臺運行,不與任何終端關聯的進程,一般狀況下守護進程在系統啓動時就在運行,它們以root用戶或者其餘特殊用戶(apache和postfix)運行,並能處理一些系統級的任務.習慣上守護進程的名字一般以d結尾(sshd),但這些不是必須的.spa

 

下面介紹一下建立守護進程的步驟:.net

 

· 調用fork(),建立新進程,它會是未來的守護進程. 
· 在父進程中調用exit,保證子進程不是進程組長 
· 調用setsid()建立新的會話區 
· 將當前目錄改爲跟目錄(若是把當前目錄做爲守護進程的目錄,當前 目錄不能被卸載他做爲守護進程的工做目錄) 

// 守護進程 int daemonize (int nochdir, int noclose) { // 建立子進程,關閉父進程 pid_t pid = fork(); if (pid > 0) // 父進程 { exit (0); } else if (pid < 0) { return -1; } // 二、設置文件的掩碼,mode & ~umask umask (0); // 三、設置新的會話:脫離當前會話和終端的控制 if (setsid() < 0) { return -1; } // 當nochdir爲0時,daemon將更改進程的根目錄爲root if (0 == nochdir) { // 改變當前的工做目錄 if (chdir ("/") < 0) { return -1; } } // 標準輸入、關閉標準輸出、標準錯誤 close (STDIN_FILENO); close (STDOUT_FILENO); close (STDERR_FILENO); if (0 == noclose) { // 重定向標準輸入、關閉標準輸出、標準錯誤 open ("dev/null", O_RDONLY); // 0 open ("dev/null", O_RDWR); // 1 open ("dev/null", O_RDWR); // 2 } return 0; } int main() { daemonize (0, 0); // daemon (0,0); // 系統自帶守護進程 while (1); return 0; }
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息