管道(Pipe)是兩個進程之間進行單向通信的機制,因為它的單向性,所以又稱為半雙工管道。它主要用於進程間的一些簡單通信。
- 數據只能由一個進程流向另一個進程(一個寫管道,一個讀管道);如果要進行全雙工通信,需要建立兩個管道。
- 管道只能用於父子進程或者兄弟進程之間的通信。
- 管道沒有名字,且其緩沖區大小有限。
- 一個進程向管道寫數據,數據每次都添加在管道緩沖區的末尾;另一個進程從管道另一端讀數據,從緩沖區頭部讀出數據。
創建管道的命令:
#include <unistd.h> int pipe(int fd[2])
管道兩端分別用描述符fd[0]和fd[1]來描述。其中fd[0]只能用於讀,稱為管道讀端;fd[1]只能用於寫,稱為管道寫端。
管道的一般用法:先創建一個管道,之后用fork創建一個子進程,之后父進程關閉管道的讀端(或寫端),子進程關閉管道的寫端(或讀端),父進程向管道寫輸入,子進程就能從管道讀數據了。
例子:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <unistd.h> /*讀管道*/ void read_from_pipe (int fd) { char message[100]; read (fd,message,100); printf("read from pipe:%s",message); } /*寫管道*/ void write_to_pipe (int fd) { char *message = "Hello, pipe!\n"; write (fd, message,strlen(message)+1); } int main(void) { int fd[2]; pid_t pid; int stat_val; if (pipe (fd)) { printf ("create pipe failed!\n"); exit (1); } pid = fork(); switch (pid) { case -1: printf ("fork error!\n"); exit (1); case 0: /*子進程關閉fd1*/ close (fd[1]); read_from_pipe (fd[0]); exit (0); default: /*父進程關閉fd0*/ close (fd[0]); write_to_pipe (fd[1]); wait (&stat_val); exit (0); } return 0; }
有名管道
管道的一個不足之處是沒有名字,因此只能在具有親緣關系的進程之間通信。而“有名管道”與此不同,它提供了一個路徑名與之關聯,作為一個設備文件存在,即使無親緣關系的進程之間,只要能訪問該路徑,也可以通過FIFO進行通信。FIFO總是按照先進先出的原則工作,第一個被寫入的數據將首先從管道中讀出。
函數原型:
#include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *path,mode_t mode);
path為創建有名管道的路徑名;mode為創建有名管道的模式,指明其存取權限。函數調用成功返回0,失敗返回-1。
使用一個存在的有名管道之前,需要用open()將其打開。因為有名管道是一個存在於硬盤上的文件,而管道是存在於內存中的特殊文件。
以下程序演示有名管道在無親緣關系的進程之間如何通信。
寫端:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #define FIFO_NAME "myfifo" #define BUF_SIZE 1024 int main(void) { int fd; char buf[BUF_SIZE] = "Hello procwrite, I come from process named procread!"; umask(0); //指明創建一個有名管道且存取權限為0666,即創建者、與創建者同組的用戶、其他用戶對該有名管道的訪問權限都是可讀可寫 if (mkfifo (FIFO_NAME, S_IFIFO | 0666) == -1) { perror ("mkfifo error!"); exit (1); } if((fd = open (FIFO_NAME, O_WRONLY) ) == -1)/*以寫方式打開FIFO*/ { perror ("fopen error!"); exit (1); } write (fd, buf, strlen(buf)+1); /*向FIFO寫數據*/ close (fd); exit (0); }
讀端:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/stat.h> #include <fcntl.h> #include <sys/types.h> #define FIFO_NAME "myfifo" #define BUF_SIZE 1024 int main(void) { int fd; char buf[BUF_SIZE]; umask (0); fd = open(FIFO_NAME, O_RDONLY); read (fd, buf, BUF_SIZE); printf ("Read content: %s\n", buf); close (fd); exit (0); }
以上就是管道和有名管道的基本用法了。