管道基礎
##管道基礎
#通信分類:只寫單工管道、只讀單工管道、半雙工管道(單向讀寫)、全雙工管道(兩個半雙工管道拼接)
類型 創建/打開 關閉 讀 寫
單工 popen() pclose() read() write()
半雙工 pipe()/open() close() read() write()
FIFO半雙工 mkfifo()/open() close()/unlink() read() write()
全雙工 socketpair() close() read() write()
管道通常用於進程間通信,可以用KFC買東西來比喻,通過man 7 pipe來查看管道在redhat中的官方解釋。
#管道的分類
@匿名管道
特點:必須是親緣進程之間
案例:
ps_self \\打印自身的父子進程信息
ps_other \\執行參數中的命令,並且打印參數中的命令相關的父子進程
分類:
*單工管道
操作: 管道 文件
打開 popen() fopen()
關閉 pclose() pclose()
打開管道:FILE* popen(const char* command,const char* open_mode);
command:命令行字符串
open_mode:只讀"r";只寫"w"
返回值:文件描述符 NULL(打開失敗)
讀寫:
size_t fread(void* buffer,size_t size,size_t count,FILE* stream)
buffer:用於接收數據的內存地址
size:讀取每個數據項的字節數
count:數據項個數
stream:輸入流
返回值:出錯(>count)、整數(實際讀取的數據項個數)
size_t fwrite(const void* buffer,size_t size,size_t count,FILE* stream)
buffer:寫入數據的內存地址
size:寫入數據項的字節數
count:寫入數據項的個數
stream:目標文件指針
返回值:出錯(>count)、正數(實際寫入的數據項個數)
關閉管道:int pclose(FILE* stream);
stream:文件描述符
返回值:失敗(-1)、成功(0)
本質:
a.啓動shell和命令兩個進程,從命令進程中讀/寫文件流
b.解決exec和system無法返回輸出數據問題
特點:
a.方便使用系統自帶功能,並且可以執行比較複雜shell
b.默認啓動兩個進程,效率較低
*半雙工管道
操作:
創建管道:int pipe(int filedes[2])
filedes[0] 讀
filedes[1] 寫
返回值:失敗(-1)、成功(0)
讀寫
ssize_t write(int fd,const void* buf,size_t nbyte)
fd:文件描述符
buf:寫入數據的內存單元
nbyte:寫入文件指定的字節數
返回值:出錯(-1)、正數(寫入的字節數)
ssize_t read(int fd,void* buf,size_t count)
fd:文件描述符
buf:讀入數據的內存單元
返回值:出錯(-1)、0(無數據)、正數(讀取的字節數)
控制:如果管道是空的,read()默認是阻塞
int fcntl(int fd,int cmd,long arg)
fd:文件描述符
cmd:F_GETFL(獲取文件描述符狀態)、F_SETFL(設置文件描述符狀態)、……
arg:O_NONBLOCK(非阻塞)、O_BLOCK(阻塞)、……
fcnt(filedes,F_SETFL,O_NONBLOCK); \\把文件描述符改爲非阻塞的。
關閉管道:close(filedes)
本質:文件描述符[文件流是文件描述符之上的封裝。文件流通過增加緩衝區減少讀寫系統調用次數來提高讀寫效率。在進程的用戶空間封裝的FILE結構,以提高可移植性和效率]
*複製管道
定義:Linux內核使用三個關聯的數據結構,表示打開的文件。【描述符表,文件表,v-node表】內核爲每個進程創建的文件文件描述符。
分類 文件描述符 文件號
標準輸入 STDIN_FILENO 0
標準輸出 STDOUT_FILENO 1
標準出錯信息 STDERR_FILENO 2
int dup(oldfd) \\返回值:-1(失敗)、其他(新的文件描述符)
int dup2(int oldfd,int newfd) \\返回值:-1(失敗)、其他(最小及尚未使用的文件描述符)
@【半雙工】FIFO管道/命名管道
特點:可以是非親緣進程之間;讀寫必須同時執行,否則阻塞。
案例:FIFO工具箱
操作:
創建命名管道:int mkfifo(pathname,mode)【古老方式:int mknod(const char *filename,mode_t mode | S_IFIFO,(dev_t)0);】
pathname:文件路徑【文件必須不存在】
mode:模式
返回值:0(成功)、非零(失敗)
打開FIFO文件:int open(const char* path,int mode)
pathname:文件路徑
mode:模式【O_RDONLY(阻塞只讀)、O_RDONLY|O_NONBLOCK(非阻塞只讀)、O_WRONLY(阻塞只寫)、O_WRONLY|O_NONBLOCK(非阻塞只寫)】
返回值:-1(失敗)、其他(文件描述符)
#通信分類:只寫單工管道、只讀單工管道、半雙工管道(單向讀寫)、全雙工管道(兩個半雙工管道拼接)
類型 創建/打開 關閉 讀 寫
單工 popen() pclose() read() write()
半雙工 pipe()/open() close() read() write()
FIFO半雙工 mkfifo()/open() close()/unlink() read() write()
全雙工 socketpair() close() read() write()
管道通常用於進程間通信,可以用KFC買東西來比喻,通過man 7 pipe來查看管道在redhat中的官方解釋。
#管道的分類
@匿名管道
特點:必須是親緣進程之間
案例:
ps_self \\打印自身的父子進程信息
ps_other \\執行參數中的命令,並且打印參數中的命令相關的父子進程
分類:
*單工管道
操作: 管道 文件
打開 popen() fopen()
關閉 pclose() pclose()
打開管道:FILE* popen(const char* command,const char* open_mode);
command:命令行字符串
open_mode:只讀"r";只寫"w"
返回值:文件描述符 NULL(打開失敗)
讀寫:
size_t fread(void* buffer,size_t size,size_t count,FILE* stream)
buffer:用於接收數據的內存地址
size:讀取每個數據項的字節數
count:數據項個數
stream:輸入流
返回值:出錯(>count)、整數(實際讀取的數據項個數)
size_t fwrite(const void* buffer,size_t size,size_t count,FILE* stream)
buffer:寫入數據的內存地址
size:寫入數據項的字節數
count:寫入數據項的個數
stream:目標文件指針
返回值:出錯(>count)、正數(實際寫入的數據項個數)
關閉管道:int pclose(FILE* stream);
stream:文件描述符
返回值:失敗(-1)、成功(0)
本質:
a.啓動shell和命令兩個進程,從命令進程中讀/寫文件流
b.解決exec和system無法返回輸出數據問題
特點:
a.方便使用系統自帶功能,並且可以執行比較複雜shell
b.默認啓動兩個進程,效率較低
*半雙工管道
操作:
創建管道:int pipe(int filedes[2])
filedes[0] 讀
filedes[1] 寫
返回值:失敗(-1)、成功(0)
讀寫
ssize_t write(int fd,const void* buf,size_t nbyte)
fd:文件描述符
buf:寫入數據的內存單元
nbyte:寫入文件指定的字節數
返回值:出錯(-1)、正數(寫入的字節數)
ssize_t read(int fd,void* buf,size_t count)
fd:文件描述符
buf:讀入數據的內存單元
返回值:出錯(-1)、0(無數據)、正數(讀取的字節數)
控制:如果管道是空的,read()默認是阻塞
int fcntl(int fd,int cmd,long arg)
fd:文件描述符
cmd:F_GETFL(獲取文件描述符狀態)、F_SETFL(設置文件描述符狀態)、……
arg:O_NONBLOCK(非阻塞)、O_BLOCK(阻塞)、……
fcnt(filedes,F_SETFL,O_NONBLOCK); \\把文件描述符改爲非阻塞的。
關閉管道:close(filedes)
本質:文件描述符[文件流是文件描述符之上的封裝。文件流通過增加緩衝區減少讀寫系統調用次數來提高讀寫效率。在進程的用戶空間封裝的FILE結構,以提高可移植性和效率]
*複製管道
定義:Linux內核使用三個關聯的數據結構,表示打開的文件。【描述符表,文件表,v-node表】內核爲每個進程創建的文件文件描述符。
分類 文件描述符 文件號
標準輸入 STDIN_FILENO 0
標準輸出 STDOUT_FILENO 1
標準出錯信息 STDERR_FILENO 2
int dup(oldfd) \\返回值:-1(失敗)、其他(新的文件描述符)
int dup2(int oldfd,int newfd) \\返回值:-1(失敗)、其他(最小及尚未使用的文件描述符)
@【半雙工】FIFO管道/命名管道
特點:可以是非親緣進程之間;讀寫必須同時執行,否則阻塞。
案例:FIFO工具箱
操作:
創建命名管道:int mkfifo(pathname,mode)【古老方式:int mknod(const char *filename,mode_t mode | S_IFIFO,(dev_t)0);】
pathname:文件路徑【文件必須不存在】
mode:模式
返回值:0(成功)、非零(失敗)
打開FIFO文件:int open(const char* path,int mode)
pathname:文件路徑
mode:模式【O_RDONLY(阻塞只讀)、O_RDONLY|O_NONBLOCK(非阻塞只讀)、O_WRONLY(阻塞只寫)、O_WRONLY|O_NONBLOCK(非阻塞只寫)】
返回值:-1(失敗)、其他(文件描述符)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.