1、管道 管道分爲兩種: 無名管道 有名管道 無名管道用於具備親緣關係的進程間通信。無名管道是單工的。 有內核管理的一塊內存空間。 使用管道,系統提供了pipe(2) #include <unistd.h> int pipe(int pipefd[2]); 功能:建立管道 參數: pipefd[2]:用於返回管道的兩端。pipefd[0]指向管道的讀端。 pipefd[1]指向管道的寫端。 返回值: 0 成功。 -1 錯誤 errno被設置 使用管道實現兩個進程間的通信。 步驟: (一)、父進程建立管道 (二)、父進程建立子進程(子進程繼承了父進程的文件描述符) (三)、父進程負責的工做 1、關閉讀端 2、經過管道的寫端文件描述符,寫數據到管道空間。 3、阻塞等待子進程的結束。子進程結束的時候,收屍 (四)、子進程負責的工做 1、關閉寫端 2、從管道中讀取數據 3、將讀取到的數據,輸出到顯示器 4、結束進程。 代碼的實現 pipe.c 有名管道 有名管道實際上是一個文件,這個文件只能用於兩個進程間通信的橋樑。不存儲任何數據內容。 如何建立一個有名管道的文件。使用mkfifo(3) #include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *pathname, mode_t mode); 功能:建立一個有名管道文件 參數: pathname:指定了有名管道文件的名字 mode:指定了管道文件的權限 mode & ~umask 返回值: 0 成功 -1 錯誤 errno被設置 編碼實現管道文件的建立。 文件名字由命令行第一個參數傳入,權限爲0664. 代碼參見 mkfifo.c 編寫代碼向有名管道寫數據。代碼參見PA.c 編寫代碼實現從有名管道讀取數據 代碼參見PB.c 進程結束了。 嘗試將管道添加到psh中 2、信號的基礎 什麼是信號? 信號就是軟中斷。 軟中斷就是軟件模擬的中斷機制。 中斷又是什麼? 正常的執行流程、中斷處理程序 正常的執行流程、信號處理程序是兩條執行路線,可是屬於同一個進程。 系統爲咱們提供了哪些信號呢? kill -l 信號有名字和編號。 信號的產生到消失的過程。 信號的產生、信號阻塞、信號遞達進程、信號處理 信號的未決狀態 就是信號產生了,可是信號尚未被進程處理,這期間,信號的狀態爲未決狀態。 進程能夠設置對信號的阻塞。 3、改變信號的處理函數 進程對信號的處理有默認動做。默認處理是終止進程。 除此以外,還有兩種 忽略信號 用戶自定義 進程從父進程繼承信號處理函數。 SIG_DFL 默認 SIG_IGN 忽略 doit 用戶自定義的信號處理函數 系統提供了signal(2) 用來改變信號的處理函數 #include <signal.h> typedef void (*sighandler_t)(int); sighandler_t signal(int signum, sighandler_t handler); 功能: 參數: signum:指定了信號的編號 handler:指定了signum信號的處理函數 SIG_IGN, SIG_DFL, 用戶自定義函數 返回值: SIG_ERR 錯誤 返回的是舊的信號處理函數的地址 typedef void (*sighandler_t)(int); 舉例說明 編碼實現進程忽略2號信號 代碼參見signal2.c 編碼實現進程對2號信號的處理採用用戶自定義的函數。 代碼參見 signal_2u.c 4、信號的產生 信號產生的三種形式: 1、硬件產生信號 ctrl+c ctrl+\ 2、使用命令爲進程發送信號 kill -信號編號 pid 3、使用庫函數或者系統調用爲進程發送信號 kill(2) #include <sys/types.h> #include <signal.h> int kill(pid_t pid, int sig); 功能:給一個進程發送信號 參數: pid:指定了接收信號的進程的pid sig:指定了具體的信號 返回值: 0 成功 -1 錯誤 errno被設置 舉例說明 編寫代碼實現kill命令的功能。代碼參見pkill.c raise(3) #include <signal.h> int raise(int sig); 功能:發送信號給當前進程 參數: sig:指定信號的編號 返回值: 0 成功 非0 錯誤 舉例說明,使用raise給當前進程發送信號 代碼參見 raise.c alarm(2) 產生SIGALRM信號 #include <unistd.h> unsigned int alarm(unsigned int seconds); 功能:產生SIGALRM信號,將這個信號發送給當前進程 參數: seconds:指定了鬧鐘的時間。若是這個參數爲0.取消鬧鐘。 返回值: 返回剩餘的沒執行的時間值。 舉例說明 編寫代碼實現每一秒鐘輸出的數字。代碼參見 count.c 5、信號阻塞和未決信號 信號集類型 sigset_t 系統對sigset_t 類型進行了封裝 #include <signal.h> int sigemptyset(sigset_t *set); 功能:初始化信號集爲空,不包含任何信號 參數: set:指定要初始化的信號集 返回值: 0 成功 -1 錯誤 int sigfillset(sigset_t *set); 功能:初始化信號集爲滿,包含全部的信號 參數: set:指定要初始化的信號集 返回值: 0 成功 -1 錯誤 int sigaddset(sigset_t *set,int signum); 功能:添加指定的信號到信號集 參數: set:指定信號集 signum:指定信號 返回值: 0 成功 -1 錯誤 int sigdelset(sigset_t *set,int signum); 功能:從指定信號集刪除指定的信號 參數: set:指定信號集 signum:指定信號 返回值: 0 成功 -1 錯誤 int sigismember(const sigset_t *set, int signum); 功能:測試信號是不是集合的一員 參數: set:指定信號集 signum:指定信號 返回值: -1 錯誤 1 是 0 不是 經過sigprocmask(2)設置信號集爲進程的屏蔽字。 #include <signal.h> int sigprocmask(int how,const sigset_t *set,\ sigset_t *oldset); 功能:檢查或者改變阻塞信號 參數: how: SIG_BLOCK:原來的set和set的並集 SIG_UNBLOCK:將set集合中的信號從當前進程的set中移除。 SIG_SETMASK:將set設置爲當前進程的信號屏蔽字 set:新的信號屏蔽字。 oldset:保存進程原來的信號屏蔽字。若是爲NULL,不保存。 返回值: 成功 0 -1 錯誤 舉例說明 編寫代碼實現對2號信號的阻塞。 代碼參見 blocked2.c 屢次發送2號信號,進程對2號信號阻塞,在解除阻塞的時候,信號處理函數只執行一次,形成了信號的丟失。這樣的信號叫不可靠信號。 1~31 34~64 稱爲可靠信號,不會有信號丟失。 檢測進程的未決信號 sigpending(2) #include <signal.h> int sigpending(sigset_t *set); 功能:檢測未決信號 參數: set:未決信號掩碼被存放在這個集合中 返回值: 成功 0 錯誤 -1 舉例說明 檢測進程的未決信號集 代碼參見 pending.c 總結: 一 管道 (無名管道 有名管道) 2、信號基礎 3、信號的處理 signal(2) 4、信號的產生 5、信號阻塞和未決信號