1、管道數組
管道:管道是一種半雙工的通訊方式,數據只能單方向流動,並且只能在具備親緣關係的進程間使用,由於管道服務器
傳遞數據的單向性,管道又稱爲半雙工管道。進程的親緣關係一般是指父子進程關係。函數
管道的特色決定了其使用的侷限性:ui
- 數據只能由一個進程流向另外一個進程(其中一個爲寫管道,另外一個爲讀管道);若是要進行全雙工通訊,須要
創建兩個管道。spa
- 管道只能用於父子進程或者兄弟進程間的通訊,也就是說管道只能用於具備親緣關係的進程間的通訊,無親緣
關係的進程不能使用管道。code
管道的建立:orm
Linux下建立管道能夠經過函數pipe來完成。該函數若是調用成功則返回0,而且數組中將包含兩個新的文件描述符;blog
若是有錯誤發生,返回-1,該函數返回兩個文件描述符:pipefd[0]和pipefd[1]。前者打開來讀,後者打開來寫。該函進程
數的原型爲:ip
#include <fcntl.h>
#include <unistd.h>
int pipe(int pipefd[2]);
1. 下面是經過創建管道和建立父子進程間的通訊:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> #include <sys/wait.h> int main() { int fd[2]; pid_t pid; int ret; ret= pipe(fd); if(ret== -1) { perror("pipe.\n"); exit(1); } pid= fork(); if(pid== -1) { perror("fork.\n"); exit(1); } else if(pid== 0) { char buff[256]; close(fd[1]); read(fd[0],buff,256); printf("Form parent say: %s\n",buff); close(fd[0]); } else { char *say= "Hello Linux."; close(fd[0]); write(fd[1],say,strlen(say)+ 1); close(fd[1]); int status; wait(&status); } return 0; }
這是父子進程間利用管道進行通訊的一個例子。
2. 下面是經過創建兩個管道來實現父子進程間全雙工通訊:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <sys/wait.h> int main() { char *parent_talk[]= {"Hello","Can you tell me what time is it?","Ok,I must go,Bye",NULL}; char *child_talk[]= {"Hi","No problem","See you,Bye",NULL}; int fd1[2],fd2[2]; pid_t pid; int ret; ret= pipe(fd1); if(ret== -1) { perror("pipe1.\n"); exit(1); } ret= pipe(fd2); if(ret== -1) { perror("pipe2.\n"); exit(1); } pid= fork(); if(pid== -1) { perror("fork.\n"); exit(1); } else if(pid== 0) { char buff[256]; close(fd1[1]); close(fd2[0]); int i= 0; char *talk= child_talk[i]; while(talk!= NULL) { read(fd1[0],buff,256); printf("Parent say: %s\n",buff); write(fd2[1],talk,strlen(talk)+ 1); talk= child_talk[++i]; } close(fd1[0]); close(fd2[1]); } else { char buff[256]; close(fd1[0]); close(fd2[1]); int i= 0; char *talk= parent_talk[i]; while(talk!= NULL) { write(fd1[1],talk,strlen(talk)+ 1); read(fd2[0],buff,256); printf("Child say: %s\n",buff); talk= parent_talk[++i]; } close(fd1[1]); close(fd2[0]); int status; wait(&status); } return 0; }
這是經過創建兩個管道來實現父子進程間全雙工通訊的例子。
2、有名管道
管道的有一個不足之處是沒有名字,所以,只能用於具備親緣關係的進程間通訊,在有名管道(FIFO)提出後,該
限制獲得了克服。FIFO不一樣於管道之處在於它提供一個路徑名與之關聯,以FIFO的文件形式存儲於文件系統中。有名
管道是一個設備文件,所以,即便進程與建立FIFO的進程不存在親緣關係,只要能夠訪問該路徑,就可以經過FIFO相
互通訊。須要注意的是,FIFO老是按照先進先出的原則工做,第一個被寫入的數據將首先從管道中讀出。
有名管道的建立:
Linux下有兩種方式建立有名管道。一是在Shell下交互地創建一個有名管道,二是在程序中使用系統函數創建有
名管道。Shell方式下可以使用mkfifo或mknod命令。建立有名管道的系統函數有兩個:mkfifo和mknod。兩個函數均定義
在頭文件sys/stat.h中,函數的原型爲:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname,mode_t mode);
int mknod(const char *pathname,mode_t mode,dev_t dev);
函數mkfifo參數中pathname爲建立的有名管道的全路徑名;mode爲建立的有名管道的模式,指明其存取權限;函
數mknod參數中pathname爲建立的有名管道的全路徑名;mode爲建立的有名管道的模式,指明其存取權限;dev爲設
備值,該值取決於文件建立的種類,它只在建立設備文件時纔會用到。這兩個函數調用成功都返回0,失敗都返回-1。
下面是使用有名管道創建一個客戶端/服務器的例子:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/wait.h> #define BUFFER_SIZE 256 const char *write_fifo= "write_fifo"; const char *read_fifo= "read_fifo"; int main() { if(access(write_fifo,F_OK)) { int ret= mkfifo(write_fifo,0755); if(ret== -1) { perror("mkfifo"); exit(1); } } int write_fd= open(write_fifo,O_WRONLY); if(write_fd== -1) { perror("open write_fifo."); exit(1); } int read_fd; while(1) { read_fd= open(read_fifo,O_RDONLY); if(read_fd== -1) { sleep(1); continue; } break; } char sendbuf[BUFFER_SIZE]; char recvbuf[BUFFER_SIZE]; while(1) { printf("Ser:"); scanf("%s",sendbuf); if(strcmp(sendbuf,"quit")== 0) { unlink(write_fifo); break; } write(write_fd,sendbuf,strlen(sendbuf)+ 1); read(read_fd,recvbuf,BUFFER_SIZE); printf("Cli:%s\n",recvbuf); } close(write_fd); close(read_fd); return 0; }
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/wait.h> #define BUFFER_SIZE 256 const char *write_fifo= "write_fifo"; const char *read_fifo= "read_fifo"; int main() { int read_fd= open(write_fifo,O_RDONLY); if(read_fd== -1) { perror("open write_fifio."); exit(1); } if(access(read_fifo,F_OK)) { int ret= mkfifo(read_fifo,0755); if(ret== -1) { perror("mkfifo"); exit(1); } } int write_fd= open(read_fifo,O_WRONLY); if(write_fd== -1) { perror("open read_fifo."); exit(1); } char sendbuf[BUFFER_SIZE]; char recvbuf[BUFFER_SIZE]; while(1) { read(read_fd,recvbuf,BUFFER_SIZE); printf("Ser:%s\n",recvbuf); printf("Cli:"); scanf("%s",sendbuf); if(strcmp(sendbuf,"quit")== 0) { unlink(read_fifo); break; } write(write_fd,sendbuf,strlen(sendbuf)+ 1); } close(write_fd); close(read_fd); return 0; }