linux
# | 數據流 |
0 | 鍵盤 |
1 | 屏幕 |
2 | 屏幕 |
描述符表的第一列是文件描述符號,另外一列是它們對應的數據流,描述符表前三項恆古不變,0號標準輸入,1號標準輸出,2號標準錯誤輸出,其餘項要麼爲空,要麼爲連接進程打開的數據流。數組
怎樣返回描述符函數
FILE * my_file = fopen("xxxx.txt", "r"); int p = fileno(my_file);
複製數據流spa
dup2(4,3);
將4號描述符的數據流鏈接到3號描述符操作系統
waitpid()函數在sys/wait.h頭文件中,做用是等子進程結束後在繼續運行父進程指針
waitpid(進程的pid, 這個變量用來保存進程信息(int指針變量),選項(通常設置爲0,設置爲0表示等待進程結束))
在第二個參數中會保存一個值,它會記錄進程完成狀況,能夠用WEXITSTATUS()來查看。調試
二.c語言中的錯誤處理代碼code
每次系統調用時都須要寫錯誤處理代碼,即出現錯誤中止程序,並報錯。blog
exit()函數在stdlib.h頭文件中,它可讓進程退出並設置退出狀態值進程
錯誤處理函數的例子:
void error (char * msg) { fprintf(stderr, "%s : %s\n", msg, strerror(errno)); exit(1); }
調用方法
pid_t pid = fork(); if(pid == -1) { error("沒法克隆進程!"); }
二.在代碼中建立管道
pipe()函數建立兩條相連的數據流,與linux命令中的管道符號|效果相同
首先建立一個存儲兩個字符的數組,pipe()函數會建立一條管道並返回兩個描述符,一個描述符讀數據,一個描述符寫數據
int fd[2]; pipe(fd);
子進程把管道寫入端連到標準輸出
close(fd[0]) close()關閉管道的數據流 dup2(fd[1], 1); fd[1]向管道寫數據
父進程把讀取端連到標準輸入
dup2(fd[0], 0); close(fd[1]);
其中fd[0]從管道讀數據
一條管道只能單向通訊,能夠建立兩條管道進行雙向通訊
能夠反向鏈接管道從父進程到子進程
三.操做系統能夠向程序發送信號
1.信號表以下:
信號名 | 做用 |
SIGINT | 進程被中斷 |
SIGQUIT | 有人要求中止進程,而且要求把存儲器中的內容保存到核心轉儲文件 |
SIGFPE | 浮點錯誤 |
SIGTRAP | 調試人員詢問進程執行到了哪裏 |
SIGSEGV | 進程企圖訪問非法存儲器地址 |
SIGWINCH | 終端窗口的大小發生改變 |
SIGTERM | 有人要求內核終止進程 |
SIGPIPE | 進程在向一個沒有人讀的管道寫數據 |
2.在使用ctrl+c使用至關於操做系統向程序發送SIGINT信號,默認的信號處理器會調用exit()函數
3.sigaction是一個函數包裝器,它有一個函數指針,sigaction告訴操做系統進程收到某個信號時應該調用哪一個函數。
sigaction的建立方法
struct sigaction xxxx; xxxx.sa_handler = 函數名字; sigemptyset(&action.sa_mask); 用掩碼過濾要處理的信號 xxxx.sa_flags = 0;一些附加標誌位將它置0; return sigaction(信號編號, &xxxx, NULL);最後一個選項可使用&變量名用來保存被替換的信號處理器
使用sigaction所包裝的函數叫作信號處理器,信號是一個整型值,若是你建立一個自定義的處理器它的形參須要接收一個整型值。
例如:
void diediedie(int sig) { puts("Goodbye cruel world......\n"); exit(1); }
4.使用kill殺死進程
kill 進程id 向程序發送SIGTERN
kill -INT 進程id 向程序發送SIGINT信號
kill -SEGV 進程id 向程序發送SIGSEGV
kill -KILL 進程id向程序發送SIGKILL信號
5.可使用raise(信號名)函數讓程序向本身發送信號,能夠在程序接收到低級別信號時引起更高級別的信號,這叫作信號升級。
6.使用定時器函數
alarm(時間數值以秒爲單位)
一個進程最好只設置一個定時器
在n秒後發出SIGALRM信號
7.還原與忽略信號處理器
SIG_DFL以默認方式處理信號
SIG_IGN讓進程忽略某個信號
使用方法:
調用前面的使用sigaction註冊的處理器函數
函數名(信號,SIG_DEL)以默認方式處理信號
函數名(信號,SIG_IGN)忽略某個信號