Linux進程間的通信
一.進程與線程
- 進程是程序在某個數據集合上的一次運行活動,線程是進程中一個執行路徑。進程有自己獨立的地址空間,而線程沒有,線程必須依賴進程而存在。
- 進程是系統資源分配的單位,線程是系統調度的單位
- 操作系統以進程為單位分配資源,進程中的每個線程共享進程的資源,每個線程有自己的程序計數器、棧。
二.進程啟動的三種方式
- system("ps -ef"),使用shell啟動一個新的進程
- exec族函數會用新進程代替原有的進程,系統會從新的進程運行,新的進程的PID值會與原來的進程的PID值相同。
- fork函數復制進程映像,創建一個新的進程,新進程的許多屬性與當前進程是相同的,執行代碼也完全相同,但新進程有自己的數據空間、環境、文件描述符。
三.孤兒進程和僵死進程
在linux中,子進程總是由父進程產生的,子進程和父進程是同時運行著的,父進程無法預知子進程什麽時候結束,當一個進程完成它的工作後,父進程需要調用waitpid系統調用獲取子進程的終止狀態。孤兒進程指的是父進程已經運行結束了,而它的子進程還在運行,那麽那些子進程將稱為孤兒進程。孤兒進程將被init進程(進程號為1)所收養,並由init進程對它們完成狀態收集工作。僵屍進程指的是一個進程使用fork創建子進程,如果子進程退出,而父進程並沒有調用wait或waitpid獲取子進程的狀態信息,那麽子進程的進程描述符仍然保存在系統中。這種進程稱之為僵死進程,進程處於僵死狀態。
四.進程與信號
信號提供了一種處理異步事件的方法。每個信號都有一個名字。這些名字都以三個字符SIG開頭。在頭文件<signal.h>中,這些信號都被定義為正整數(信號編號)。不存在編號為0的信號。(kill函數對信號編號0有特殊的應用)。信號是異步事件的經典實例。產生信號的事件對進程而言是隨機出現的。進程不能簡單地測試一個變量(例如errno)來判別是否出現了一個信號,而是必須告訴內核“在此信號出現時,請執行下列操作”。下面的實例是通過信號機制處理僵死進程,子進程退出時向父進程發送SIGCHILD信號,父進程處理SIGCHILD信號。在信號處理函數中調用wait進行處理僵屍進程。
產生信號的方式:
- 當用戶按某些終端鍵時,引發終端產生的信號。
- 硬件異常產生信號。
- 進程調用kill(2)函數可將信號發送給另一個進程或進程組。(接收信號進程和發送信號進程的所有者必須相同,或者發送信號進程的所有者必須是超級用戶。)
- 用戶可用kill(1)命令將信號發送給其他進程。
可以要求內核在某個信號出現時按照下列三種方式之一進行處理,我們稱之為信號的處理或者與信號相關的動作。
- 忽略此信號。大多數信號都可使用這種方法進行處理,但是有兩種信號決不能被忽略:SIGKILL和SIGSTOP。這兩種信號不能被忽略的原因是:它們向超級用戶提供了使進程終止或停止的可靠方法。另外,如果忽略某些由硬件異常產生的信號(例如除以0),則進程的運行行為是未定義的。
- 捕捉信號。為了做到這一點,要通知內核在某種信號發生時調用一個用戶函數。在用戶函數中,可執行用戶希望對這種事件進行的處理。註意,不能捕捉SIGKILL和SIGSTOP信號。
- 執行系統默認動作。註意,針對大多數信號的系統默認動作是終止
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <errno.h> 4 #include <stdlib.h> 5 #include <signal.h> 6 7 static void sig_child(int signo); 8 9 int main() 10 { 11 pid_t pid; 12 //創建捕捉子進程退出信號 13 signal(SIGCHLD,sig_child); 14 pid = fork(); 15 if (pid < 0) 16 { 17 perror("fork error:"); 18 exit(1); 19 } 20 else if (pid == 0) 21 { 22 printf("I am child process,pid id %d.I am exiting.\n",getpid()); 23 exit(0); 24 } 25 printf("I am father process.I will sleep two seconds\n"); 26 //等待子進程先退出 27 sleep(2); 28 //輸出進程信息 29 system("ps -o pid,ppid,state,tty,command"); 30 printf("father process is exiting.\n"); 31 return 0; 32 } 33 34 static void sig_child(int signo) 35 { 36 pid_t pid; 37 int stat; 38 //處理僵屍進程 39 while ((pid = waitpid(-1, &stat, WNOHANG)) >0) 40 printf("child %d terminated.\n", pid); 41 }View Code
五.進程與管道
參考:
-
孤兒進程與僵屍進程[總結]
-
進程與信號
Linux進程間的通信