Linux学习笔记24——进程管道
一 管道的作用
通常把一個(gè)進(jìn)程的輸出通過(guò)管道連接到另一個(gè)進(jìn)程的輸入。
二 popen和pclose函數(shù)
#include <stdio.h>FILE *popen(const char *command, //是要運(yùn)行的程序名和相應(yīng)的參數(shù)const char *open_mode //必須是“r”或者“w”,如果是其它值,errno將返回EINVAL
); int pclose(FILE *stream_to_close);
popen() 函數(shù)通過(guò)創(chuàng)建一個(gè)管道,調(diào)用 fork 產(chǎn)生一個(gè)子進(jìn)程,執(zhí)行一個(gè) shell 以運(yùn)行命令來(lái)開(kāi)啟一個(gè)進(jìn)程。
pclose()調(diào)用只在popen啟動(dòng)的進(jìn)程結(jié)束后才返回,如果調(diào)用pclose函數(shù)時(shí)它仍在運(yùn)行,pclose調(diào)用將等待該進(jìn)程的結(jié)束。
例:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h>int main(){FILE *read_fp; //要讀取的文件描述符char buffer[BUFSIZ+1]; //用來(lái)存儲(chǔ)讀到的文件信息int chars_read; //實(shí)際讀取的元素個(gè)數(shù)memset(buffer,'\0',sizeof(buffer)); //將數(shù)組清零初始化read_fp=popen("cat test*.c | wc -l","r"); //創(chuàng)建管道,用于顯示所有test*.c文件的字?jǐn)?shù)if(read_fp!=NULL){chars_read=fread(buffer,sizeof(char),BUFSIZ,read_fp);//從一個(gè)文件流中讀數(shù)據(jù),最多讀取count個(gè)元素,每個(gè)元素size字節(jié),如果調(diào)用成功返回實(shí)際讀取到的元素個(gè)數(shù),如果不成功返回 0while(chars_read>0){buffer[chars_read-1]='\0'; //清除回車(chē)符printf("Reading:-\n %s\n",buffer);chars_read=fread(buffer,sizeof(char),BUFSIZ,read_fp);}pclose(read_fp); //關(guān)閉管道exit(EXIT_SUCCESS);}exit(EXIT_FAILURE); }使用shell的一個(gè)不太好的影響:針對(duì)每個(gè)popen調(diào)用,不僅要啟動(dòng)一個(gè)被請(qǐng)求的程序,還要啟動(dòng)一個(gè)shell,即每個(gè)popen調(diào)用將多啟動(dòng)兩個(gè)進(jìn)程。從節(jié)省系統(tǒng)資源的角度來(lái)看,popen函數(shù)的調(diào)用成本略高,而且對(duì)目標(biāo)命令的調(diào)用比正常方式要慢一些。
三 pipe函數(shù)
#include <unistd.h> int pipe(int fd[2]);pipe函數(shù)的參數(shù)是一個(gè)由兩個(gè)整數(shù)類(lèi)型的文件描述符組成的數(shù)組的指針,兩個(gè)返回的文件描述符以一種特殊的方式連接起來(lái),寫(xiě)到fd[1]的所有數(shù)據(jù)都可以從fd[0]讀回來(lái),數(shù)據(jù)基于先進(jìn)先出的原則(FIFO)進(jìn)程處理。
對(duì)一個(gè)已關(guān)閉寫(xiě)數(shù)據(jù)的管道做read調(diào)用將返回0而不是阻塞,讀取無(wú)效的文件描述符將看作是一個(gè)錯(cuò)誤并返回-1
?
如果跨越fork調(diào)用使用管道,就會(huì)有兩個(gè)不同的文件描述符可以用于向管道寫(xiě)數(shù)據(jù),一個(gè)在父進(jìn)程中,一個(gè)在子進(jìn)程中。只有把父子進(jìn)程中的針對(duì)管道的寫(xiě)文件描述符都關(guān)閉,管道才會(huì)被認(rèn)為是關(guān)閉了,對(duì)管道的read調(diào)用才會(huì)失敗。
管道的讀寫(xiě)規(guī)則:
1 從管道中讀取數(shù)據(jù)
- 如果管道的寫(xiě)端不存在,則認(rèn)為已經(jīng)讀到了數(shù)據(jù)的末尾,讀函數(shù)返回的讀出字節(jié)數(shù)為0;
- 當(dāng)管道的寫(xiě)端存在時(shí),如果請(qǐng)求的字節(jié)數(shù)目大于PIPE_BUF,則返回管道中現(xiàn)有的數(shù)據(jù)字節(jié)數(shù),如果請(qǐng)求的字節(jié)數(shù)目不大于 PIPE_BUF,則返回管道中現(xiàn)有數(shù)據(jù)字節(jié)數(shù)(此時(shí),管道中數(shù)據(jù)量小于請(qǐng)求的數(shù)據(jù)量);或者返回請(qǐng)求的字節(jié)數(shù)(此時(shí),管道中數(shù)據(jù)量不小于請(qǐng)求的數(shù)據(jù) 量)。注:(PIPE_BUF在include/linux/limits.h中定義,不同的內(nèi)核版本可能會(huì)有所不同。Posix.1要求 PIPE_BUF至少為512字節(jié),red hat 7.2中為4096)。
2 從管道中寫(xiě)入數(shù)據(jù)
向管道中寫(xiě)入數(shù)據(jù)時(shí),linux將不保證寫(xiě)入的原子性,管道緩沖區(qū)一有空閑區(qū)域,寫(xiě)進(jìn)程就會(huì)試圖向管道寫(xiě)入數(shù)據(jù)。如果讀進(jìn)程不讀走管道緩沖區(qū)中的數(shù)據(jù),那么寫(xiě)操作將一直阻塞。
注:只有在管道的讀端存在時(shí),向管道中寫(xiě)入數(shù)據(jù)才有意義。否則,向管道中寫(xiě)入數(shù)據(jù)的進(jìn)程將收到內(nèi)核傳來(lái)的SIFPIPE信號(hào),應(yīng)用程序可以處理該信號(hào),也可以忽略(默認(rèn)動(dòng)作則是應(yīng)用程序終止)。
?
例子:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h>int main(){const char some_data[]="123";int file_pipes[2];int data_processed;pid_t fork_result;if(pipe(file_pipes)==0){fork_result=fork();if(fork_result==(pid_t)-1){fprintf(stderr,"Fork failure");exit(EXIT_FAILURE);}if(fork_result==0){ //子進(jìn)程close(0); //關(guān)閉標(biāo)準(zhǔn)輸入,即鍵盤(pán)輸入dup(file_pipes[0]); //復(fù)制一個(gè)文件描述符close(file_pipes[0]); ?//關(guān)閉讀操作close(file_pipes[1]); //關(guān)閉寫(xiě)操作execlp("od","od","-c",(char*)0); //利用od查看特殊格式的文件內(nèi)容,-c表示ASCII字符或反斜杠序列,(char*)0參數(shù)作用是終止被調(diào)用程序的參數(shù)列表exit(EXIT_FAILURE);}else{ //主進(jìn)程close(file_pipes[0]); data_processed=write(file_pipes[1],some_data,strlen(some_data)); //寫(xiě)入數(shù)據(jù)close(file_pipes[1]);printf("%d - wrote %d bytes\n",getpid(),data_processed);}}exit(EXIT_SUCCESS); }?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/zjzsky/p/3518604.html
總結(jié)
以上是生活随笔為你收集整理的Linux学习笔记24——进程管道的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 女人何苦为难女人剧情介绍
- 下一篇: Linux中强大的输入输出重定向和管道