IPC(InterProcess Communication,進程間通訊)是進程中的重要概念。Linux 進程之間經常使用的通訊方式有:mysql
經過管道,能夠把一個進程的輸出做爲另外一個進程的輸入。管道分爲兩種:web
一般用的管道,都是匿名管道。管道其實是一塊內核緩衝區,不佔用磁盤空間,但操做方式跟文件是同樣的。sql
在 Linux 的命令行終端中,管道是再經常使用不過的命令技巧了。經過管道能夠把前一個命令的輸出做爲後一個命令的輸入。在 Linux 命令中一般經過符號 |
來使用管道。數組
例如,查看全部的進程,而後按關鍵字過濾:緩存
ps aux | grep mysql
匿名管道是不能在文件系統中以任何方式看到的半雙工管道,不佔磁盤空間。管道的特色有:bash
匿名管道沒法判斷消息是否被讀完,一般僅用於父進程向子進程傳遞數據,或子進程向父進程傳遞數據。此時能夠在父子進程中關閉不用的讀或寫端。數據結構
管道是基於環形隊列這個數據結構實現的,數據先進先出。默認的緩衝區大小是 4 KB,大小會自動調整。socket
- 單工:數據單向流動,例如遙控器
- 雙工:數據能夠同時雙向流動,例如手機
- 半雙工:數據能夠雙向流動,但不可同時雙向流動,例如對講機
pipe() 函數用於建立匿名管道。.svg
函數原型:函數
#include <unistd.h> int pipe(int pipefd[2]);
參數:返回文件描述符數組,對應管道的兩端,往寫端寫的數據會被內核緩存起來,直到讀端將數據讀完。其中:
返回值:成功返回 0,不然返回-1。
示例:
#include <unistd.h> #include <stdio.h> #include <stdlib.h> int main() { int fd[2]; int ret, pid; char buf; ret = pipe(fd); if (ret == -1) { perror("pipe error"); exit(1); } pid = fork(); if (pid == 0) { close(fd[1]); while(read(fd[0], &buf, 1) > 0) { // 兩種方式均可以實現輸出 printf("%c\n", buf); write(STDOUT_FILENO, &buf, 1); } close(fd[0]); } else if (pid > 0) { close(fd[0]); write(fd[1], "hello world", 12); close(fd[1]); wait(NULL); } else { perror("fork error"); exit(1); } close(fd[0]); close(fd[1]); return 0; }
命名管道也叫 FIFO 文件,在文件系統中以文件名的形式存在,大小爲0。匿名管道沒法在無關進程之間通訊,但 FIFO 能夠藉助文件系統中的文件,使得同一主機內的全部的進程均可以通訊。
進程經過 FIFO 通訊時,首先要打開管道文件,而後使用 read 、write 函數通訊。
函數原型:
#include <sys/types.h> #include <sys/stat.h> int mkfifo(const char *pathname, mode_t mode);
參數:
返回值:
函數成功返回 0,不然返回-1 並設置 errno,常見 errno 有:
示例:
建立兩個進程,一個將文件內容讀到 FIFO,另外一個從 FIFO 讀內容寫到另外一個文件。
寫 FIFO 的文件示例:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #define BUFSIZE 1024 int main(int argc, char *argv[]){ int ret; int datafd, fifofd; int bytes; char buffer[BUFSIZE]; const char *fifoname = "/tmp/fifo"; if (argc != 2) { printf("please input filename\n"); exit(EXIT_FAILURE); } if (access(fifoname, F_OK) < 0) { ret = mkfifo(fifoname, 0777); if (ret < 0) { perror("mkfifo error"); exit(EXIT_FAILURE); } } fifofd = open(fifoname, O_WRONLY); datafd = open(argv[1], O_RDONLY); if (fifofd < 0) { perror("open fifo error"); exit(EXIT_FAILURE); } if (datafd < 0) { perror("open file error"); exit(EXIT_FAILURE); } bytes = read(datafd, buffer, BUFSIZE); while (bytes > 0) { ret = write(fifofd, buffer, bytes); if (ret < 0) { perror("write fifo error"); exit(EXIT_FAILURE); } bytes = read(datafd, buffer, BUFSIZE); } close(fifofd); close(datafd); return 0; }
讀 FIFO 的文件示例:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <fcntl.h> #include <sys/stat.h> #include <sys/types.h> #define BUFSIZE 1024 int main(int argc, char *argv[]) { char *fifoname = "/tmp/fifo"; int fifofd, datafd; int bytes, ret; char buffer[BUFSIZE]; if (argc != 2) { printf("please input a filename"); exit(EXIT_FAILURE); } fifofd = open(fifoname, O_RDONLY); datafd = open(argv[1], O_WRONLY); if (fifofd < 0) { perror("open fifo error"); exit(EXIT_FAILURE); } if (datafd < 0) { perror("open file error"); exit(EXIT_FAILURE); } bytes = read(fifofd, buffer, BUFSIZE); while(bytes > 0) { ret = write(datafd, buffer, bytes); if (ret < 0) { perror("write file error"); exit(EXIT_FAILURE); } bytes = read(fifofd, buffer, BUFSIZE); } close(datafd); close(fifofd); return 0; }