1. 程式人生 > >PIPE、SIGNAL(day11)

PIPE、SIGNAL(day11)

proc ctrl+c locked gad seconds 用戶自定義函數 丟失 參數 關系

一、管道
管道分為兩種:   無名管道    有名管道
無名管道用於具有親緣關系的進程間通訊。無名管道是單工的。
有內核管理的一塊內存空間。
使用管道,系統提供了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中 二、信號的基礎 什麽是信號? 信號就是軟中斷。 軟中斷就是軟件模擬的中斷機制。 中斷又是什麽? 正常的執行流程、中斷處理程序 正常的執行流程、信號處理程序是兩條執行路線,但是屬於同一個進程。 系統為我們提供了哪些信號呢? kill -l 信號有名字和編號。 信號的產生到消失的過程。 信號的產生、信號阻塞、信號遞達進程、信號處理 信號的未決狀態 就是信號產生了,但是信號還沒有被進程處理,這期間,信號的狀態為未決狀態。 進程可以設置對信號的阻塞。 三、改變信號的處理函數 進程對信號的處理有默認動作。默認處理是終止進程。 除此之外,還有兩種 忽略信號 用戶自定義 進程從父進程繼承信號處理函數。 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 四、信號的產生 信號產生的三種形式: 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 五、信號阻塞和未決信號 信號集類型 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 錯誤 10 不是 通過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 總結: 一 管道 (無名管道 有名管道) 二、信號基礎 三、信號的處理 signal(2) 四、信號的產生 五、信號阻塞和未決信號

PIPE、SIGNAL(day11)