進程是一個獨立的資源分配單位,不同進程之間的資源是相互獨立的,沒有關聯,不能在一個進程中直接訪問另一個進程中的資源。但是,進程不是孤立的,不同的進程之間需要信息的交換以及狀態的傳遞,因此需要進程間數據傳遞、同步與異步的機制。
此篇博文記錄管道。
● 命名管道命名管道是為了解決無名管道只能用於近親進程之間通信的缺陷而設計的。命名管道是建立在實際的磁盤介質或文件系統(而不是只存在於內存中)上有自己名字的文件,任何進程可以在任何時間通過文件名或路徑名與該文件建立聯系。為了實現命名管道,引入了一種新的文件類型——FIFO文件(遵循先進先出的原則)。實現一個命名管道實際上就是實現一個FIFO文件。命名管道一旦建立,之後它的讀、寫以及關閉操作都與普通管道完全相同。雖然FIFO文件的inode節點在磁盤上,但是僅是一個節點而已,文件的數據還是存在於內存緩沖頁面中,和普通管道相同。
如果管道的讀端口關閉,那麼在該管道上的發出寫操作調用的進程將接收到一個SIGPIPE信號。關閉寫端口是給讀端口一個文件結束符的唯一方法。對於寫端口關閉後,在該管道上的read調用將返回0。
/* 管道 */ #include <unistd.h> /* 建立管道 */ int pipe(int filedes[2]); /* filedes[0]為管道裡的讀取端 filedes[1]為管道裡的寫入端 返回值: 成功返回-1,錯誤返回-1,錯誤存於errno中 錯誤代碼: EMFILE 進程已用完文件描述詞最大量 ENFILE 系統已無文件描述符可用 EFAULT 參數filedes數組地址不合法 */ /* 阻塞設置 */ fcntl(filedes[0], F_SETFL, O_NONBLOCK); fcntl(filedes[1], F_SETFL, O_NONBLOCK); /* 讀寫 */ read(fd, buf, sizeof(buf)); write(fd, buf, sizeof(buf));
#include <unistd.h> #include <stdio.h> int main() { int p[2]; char buf[20]; char buf0[20]; pid_t pid; strcpy(buf,"Hello World!"); pipe(p); if((pid = fork()) > 0){ printf("This is father process.\n\n"); write(p[1], buf, strlen(buf)); close(p[1]); close(p[2]); } else{ printf("This is child process.\n"); read(p[0], buf0, sizeof(buf0)); printf("%s\n", buf0); close(p[0]); close(p[1]); } return 0; }
/* 命名管道 */ #include <sys/types.h> #include <sys/stat.h> /* 建立管道 */ int mkfifo(const char * pathname, mode_t mode); /* pathname 路徑,創建管道的位置 mode 打開函數open中的Mode */ /* 打開管道 */ int open(const char *pathname,int oflag,... /* mode_t mode */); /* mode 可選:O_RDONLY | O_WRONLY | O_NONBLOC */ /* 讀寫 */ int read(int fd, void *buf, int nbyte) int write(int fd, void *buf, int nbyte) /* 關閉 */ close(int handle)
/* fifo_write.c */ #include <sys/types.h> #include <sys/stat.h> #include <string.h> #include <stdio.h> #include <unistd.h> #include <fcntl.h> int main() { const char* pathname = "m_fifo"; int pipe_fd = -1; int bytes; char buf[20]; strcpy(buf, "hello world!"); mkfifo(pathname, 0777); pipe_fd = open(pathname, O_WRONLY); printf("Process %d result %d\n", getpid(), pipe_fd); write(pipe_fd, buf, strlen(buf)); printf("Process %d finished!\n", getpid()); return 0; }
#include <unistd.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main() { const char* pathname = "m_fifo"; char buf[20]; int pipe_fd; pipe_fd = open(pathname, O_RDONLY); printf("Process %d result %d\n", getpid(), pipe_fd); read(pipe_fd, buf, sizeof(buf)); close(pipe_fd); printf("Process %d finished,\n read content: %s \n", getpid(), buf); return 0; }