管道linux
管道是unix ipc的最古老形式,是一種在內存中的特殊文件,只能在具備公共祖先的進程之間使用(即父子進程,兄弟進程)。ios
管道由pipe函數建立函數
#include <unistd.h> int pipe(int fd[2])
fd[1]寫,fd[0]讀。spa
單個進程的管道幾乎沒有任何用處,一般,調用pipe的進程接着調用fork,這樣就建立了父子進程間的管道。unix
#include <unistd.h> #include<stdio.h> #include<sys/types.h> #include<sys/wait.h> int main() { int fd[2]; char buf[80]; pid_t pid; pipe(fd); pid = fork(); if(pid>0) {//父進程 printf("Father thread\n"); char s[]="Hello\n"; write(fd[1],s,sizeof(s)); close(fd[0]); close(fd[1]); } else if(pid==0) { printf("Child Thread\n"); read(fd[0],buf,sizeof(buf)); printf("%s\n",buf); close(fd[0]); close(fd[1]); } waitpid(pid,NULL,0);//等待子進程結束 return 0; }
輸出結果:code
Father thread
Child Thread
Helloblog
當管道的一端關閉時:進程
當讀一個寫端關閉的管道時,則認爲已經讀到了數據的末尾,讀函數返回的讀出字節數爲0;ip
當寫一個讀端關閉的管道時,向管道中寫入數據的進程將收到內核傳來的SIFPIPE信號,應用程序能夠處理該信號,也能夠忽略(默認動做則 是應用程序終止)。內存
從管道中讀取數據:
當管道的寫端存在時,若是請求的字節數目大於PIPE_BUF,則返回管道中現有的數據字節數,若是請求的字節數目不大於PIPE_BUF,則返回管道中現有數據字節數(此時,管道中數據量小於請求的數據量);或者返回請求的字節數(此時,管道中數據量不小於請求的數據量)。注:PIPE_BUF在include/linux/limits.h中定義。
向管道中寫入數據:
向管道中寫入數據時,linux將不保證寫入的原子性,管道緩衝區一有空閒區域,寫進程就會試圖向管道寫入數據。若是讀進程不讀走管道緩衝區中的數據,那麼寫操做將一直阻塞。
管道由於沒有名字因此只能用於具備親緣關係的進程,而有名管道(FIFO)則克服了這個限制。
FIFO
建立函數以下
#include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *pathname, mode_t mode);
第一個參數是一個普通的路徑名,即爲FIFO的名字。第二個參數設置權限,跟建立普通文件同樣。
FIFO的讀寫也像普通文件同樣,不過須要讀寫端都打開,具體規則以下:
當打開(open)時:
若沒有設置O_NONBLOCK,只讀open要阻塞到其它進程爲寫而打開FIFO。相似地,只寫open要阻塞到其它進程爲讀而打開FIFO。
若是設置了O_NONBLOCK,則只讀open當即返回,若沒有其它進程爲寫而打開FIFO,則返回-1。
用FIFO模擬生產者消費者問題:
fifo2.cpp:
#include<iostream> #include<unistd.h> #include <sys/types.h> #include <sys/stat.h> #include<limits.h> #include<stdio.h> #include<stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define FIFO "/tmp/myfifo" #define BUF_SIZE PIPE_BUF #define SEND_MAX (1024*1024*10) using namespace std; int main() { int pid,fifo_fd; int send_num; char *buf[BUF_SIZE+1]; if(-1 == access(FIFO,F_OK)) { int res = mkfifo(FIFO,0777); if(res != 0) { fprintf(stderr,"can't create fifo in %s",FIFO); exit(EXIT_FAILURE); } } fifo_fd = open(FIFO,O_WRONLY); printf("process %d open fifo %d\r\n",getpid(),fifo_fd); if(fifo_fd == -1) exit(EXIT_FAILURE); int res; while(send_num<SEND_MAX) { res = write(fifo_fd,buf,BUF_SIZE); if(res == -1) { cout<<"write fifo error"<<endl; exit(EXIT_FAILURE); } send_num += res; } return 0; }
fifo3.cpp
#include<iostream> #include<unistd.h> #include <sys/types.h> #include <sys/stat.h> #include<limits.h> #include<stdio.h> #include<stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define FIFO "/tmp/myfifo" #define BUF_SIZE PIPE_BUF #define SEND_MAX (1024*1024*10) using namespace std; int main() { int fifo_fd; int res; char buffer[BUF_SIZE+1]; int read_num = 0; fifo_fd = open(FIFO,O_RDONLY); printf("process %d open FIFO %d\r\n",getpid(),fifo_fd); if(fifo_fd == -1) exit(EXIT_FAILURE); do{ res = read(fifo_fd,buffer,BUF_SIZE); read_num += res; }while(res>0); close(fifo_fd); return 0; }
結果以下:
可見讀進程運行0.013s就讀取了10m的數據,FIFO的效率仍是很高的。