管道是什麼:
1. 管道只能用於具備親緣關係的進程之間通訊。
2.管道是一種單工或者說半雙工的通訊方式,傳遞信息的方向是固定的,只能由一端傳遞到另外一端。
頭文件及函數原型:
#include <unistd.h>
int pipe(int fd[2]);
當用pipe 建立管道後,兩個文件描述符fd[0],fd[1]就能夠使用了,其中fd[0]用於讀取,fd[1]用於寫入。調用管道pipe返回值0表示成功,返回值-1表示失敗。
pipe函數建立管道後,接着fork出子進程,子進程繼承父進程管道。
代碼舉例來看:函數
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <unistd.h>
- #define MAX_DATA_LEN 256
- #define DELAY_TIME 1
- int main() {
- pid_t pid;
- char buf[MAX_DATA_LEN];
- const char *data="Pipe Test";
- int real_read,real_write;
- int pipe_fd[2];
- memset((void*)buf,0,sizeof(buf));
- if(pipe(pipe_fd)<0){
- perror("Pipe create error!\n");
- exit(1);
- }
-
- if ((pid=fork())<0) {
- perror("Fork error!\n");
- exit(1);
- } else if (pid==0) {
- close(pipe_fd[1]);
- sleep(DELAY_TIME*3);
- if ((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) {
- printf("Child receive %d bytes from pipe: '%s'.\n",real_read,buf);
- }
- close(pipe_fd[0]);
- exit(0);
- } else {
- close(pipe_fd[0]);
- sleep(DELAY_TIME);
- if ((real_write=write(pipe_fd[1],data,strlen(data)))>0) {
- printf("Parent write %d bytes into pipe: '%s'.\n",real_write,data);
- }
- close(pipe_fd[1]);
- waitpid(pid,NULL,0);
- exit(0);
- }
- }
複製代碼
運行輸出:
Parent write 9 bytes into pipe: 'Pipe Test'.
Child receive 9 bytes from pipe: 'Pipe Test'.spa
上述代碼只能從父進程向子進程傳遞,如何從子進程向父進程傳遞呢?咱們看到父進程關閉了管道讀取端「close(pipe_fd[0]);」,子進程關閉了管道寫入端「close(pipe_fd[1]);」,若是取消關閉這兩個端,是否可以實現子進程向父進程傳遞呢。
父進程先發送,子進程接收,而後子進程再發送,父進程再接收,實現全雙工互相通訊,指望運行結果以下:
Parent write 9 bytes into pipe: 'Pipe Test'.
Child receive 9 bytes from pipe: 'Pipe Test'.
Child write 9 bytes from pipe: 'Pipe Test'.
Parent receive 9 bytes from pipe: 'Pipe Test'.
修改代碼以下:
code
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <unistd.h>
- #define MAX_DATA_LEN 256
- #define DELAY_TIME 1
- int main() {
- pid_t pid;
- char buf[MAX_DATA_LEN];
- const char *data="Pipe Test";
- int real_read,real_write;
- int pipe_fd[2];
- memset((void*)buf,0,sizeof(buf));
- if(pipe(pipe_fd)<0){
- perror("Pipe create error!\n");
- exit(1);
- }
-
- if ((pid=fork())<0) {
- perror("Fork error!\n");
- exit(1);
- } else if (pid==0) {
- //close(pipe_fd[1]);
- sleep(DELAY_TIME*3);
- if ((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) {
- printf("Child receive %d bytes from pipe: '%s'.\n",real_read,buf);
- }
-
- if ((real_write=write(pipe_fd[1],data,strlen(data)))>0) {
- printf("Child write %d bytes into pipe: '%s'.\n",real_write,data);
- }
- close(pipe_fd[0]);
- exit(0);
- } else {
- //close(pipe_fd[0]);
- sleep(DELAY_TIME);
- if ((real_write=write(pipe_fd[1],data,strlen(data)))>0) {
- printf("Parent write %d bytes into pipe: '%s'.\n",real_write,data);
- }
-
- if ((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) {
- printf("Parent receive %d bytes from pipe: '%s'.\n",real_read,buf);
- }
- close(pipe_fd[1]);
- waitpid(pid,NULL,0);
- exit(0);
- }
- }
複製代碼
可是實際運行以下:
Parent write 9 bytes into pipe: 'Pipe Test'.
Parent receive 9 bytes from pipe: 'Pipe Test'.
能夠看到,父進程發送的數據被父進程本身接收了,子進程讀不到數據被阻塞了。顯然這種方法不行。繼承
由於管道是單工的,只能固定從一個方向傳遞到另外一個方向。
要實現互相通訊,一個管道是不行的,能夠建立兩個管道,一個管道是父寫子讀,另外一個是子寫父讀。
代碼以下:進程
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/types.h>
- #include <unistd.h>
- #define MAX_DATA_LEN 256
- #define DELAY_TIME 1
- int main() {
- pid_t pid;
- char buf[MAX_DATA_LEN];
- const char *data="Pipe Test";
- int real_read,real_write;
- int pipe_fd[2],pipe_fd2[2];
- memset((void*)buf,0,sizeof(buf));
- if(pipe(pipe_fd)<0){
- perror("Pipe create error!\n");
- exit(1);
- }
-
- if(pipe(pipe_fd2)<0){
- perror("Pipe create error!\n");
- exit(1);
- }
- if ((pid=fork())<0) {
- perror("Fork error!\n");
- exit(1);
- } else if (pid==0) {
- close(pipe_fd[1]);
- close(pipe_fd2[0]);
- sleep(DELAY_TIME*3);
- if ((real_read=read(pipe_fd[0],buf,MAX_DATA_LEN))>0) {
- printf("Child receive %d bytes from pipe: '%s'.\n",real_read,buf);
- }
- if ((real_write=write(pipe_fd2[1],data,strlen(data)))>0) {
- printf("Child write %d bytes into pipe: '%s'.\n",real_write,data);
- }
- close(pipe_fd[0]);
- close(pipe_fd2[1]);
- exit(0);
- } else {
- close(pipe_fd[0]);
- close(pipe_fd2[1]);
- sleep(DELAY_TIME);
- if ((real_write=write(pipe_fd[1],data,strlen(data)))>0) {
- printf("Parent write %d bytes into pipe: '%s'.\n",real_write,data);
- }
- if ((real_read=read(pipe_fd2[0],buf,MAX_DATA_LEN))>0) {
- printf("Parent receive %d bytes from pipe: '%s'.\n",real_read,buf);
- }
- close(pipe_fd[1]);
- close(pipe_fd2[0]);
- waitpid(pid,NULL,0);
- exit(0);
- }
- }
複製代碼
運行結果:
Parent write 9 bytes into pipe: 'Pipe Test'.
Child receive 9 bytes from pipe: 'Pipe Test'.
Child write 9 bytes into pipe: 'Pipe Test'.
Parent receive 9 bytes from pipe: 'Pipe Test'.
能夠看到,建立了兩個管道 「int pipe_fd[2],pipe_fd2[2];」,
pipe_fd 是父寫子讀,pipe_fd2是子寫父讀,經過兩個管道,實現了進程的全雙工互相通訊。ip