管道
#include <unistd.h>
int pipe(int fds[2]);
fd返回兩個文件描述符,fd[0]讀,fd[1]寫!
管道是單雙工的,只能一端寫,另一端讀,不能兩邊同時讀寫
管道實際上是在,內核中開闢了一個循環隊列,
當隊列寫滿(隊空)時,繼續寫(讀)管道會阻塞當前進程!
當寫端關閉,繼續讀時返回EOF
當讀端關閉,繼續寫時候發送SIGPIPE信號,默認關閉進程
可能多個進程往管道寫,若指定寫的字節數< 管道空間大小PIP_BUF,則寫數據不會交叉(獨佔寫,寫是院子操作)
若指定寫的字節數> 管道空間大小PIP_BUF,則寫數據可能會交叉(寫滿管道,阻塞,管道有空間,大家一起競爭寫?)
pipe創建的管道只能用於有親緣關係的進程間通信,父進程創建管道,fork子進程繼承文件描述符,則可以父進程用fd[0]讀,子進程從fd[0]寫!
爲確保,讀寫單向,讀端應該關閉寫fd[1],寫端關閉讀fd[0]
popen& pclose
#include <stiod.h>
FILE *popen(const char *cmdstr, const char *type);
int pclose(FILE *fp);
open 開一個管道,然後調用fork,使用exec執行cmdstr 命令
返回一個標準I/O流,type 爲“r”返回標準讀,“w”返回標準寫即fd綁定爲fd[1]
注意,因爲管道作爲標準輸入/出,所以默認使用全緩衝,可能造成讀不到,或者寫不到數據
在讀寫之前追號設置俄爲行緩衝!
管道可在程序設計時候,作爲中間處理代碼,插入某一個流程,作爲中間處理!
FIFO
管道只能用於親緣關係的進程之間通信
FIFO可以用於無關係的進程間通信
可在磁盤中中創建一個文件,管道的inode會指向內核空間的,管道內存(循環隊列)
文件的實際大小是0
通過文件所有的進程就都能索引到管道的實際內容!
#include <sys/stat.h>
int mkfifo(const char *path, mode_t mode);
int mkfifoat(int fd, const char *path, mode_t mode );
創建一個FIFO文件,通過S_ISFIFO可以判斷是否文FIFO文件
open未指定O_NOBLIOCK(默認),讀(寫)打開,無進程以寫(讀)打開時,阻塞,知道有進程以寫(讀)打開
FIFO可以用來實現服務進程/客戶進程的模型
客戶以公用管道寫,大小應小於PIPE_BUF 以保證寫操作的原子性
服務以私有管道寫,客戶從此管道讀(注意處理SIGPIPE,客戶進程可能以外終止)
shell 用來將數據從一條管道送到另一條管道,無須臨時文件???