PIPE、SIGNAL(day11)

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  錯誤
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


總結:
一  管道 (無名管道   有名管道)
2、信號基礎
3、信號的處理
signal(2)
4、信號的產生
5、信號阻塞和未決信號
相關文章
相關標籤/搜索