进程间通信(二)
進程間通信(二)
文章目錄
- 進程間通信(二)
- 一、管道的讀寫規則
- 二、命名管道
- 三、命名管道的寫入規則
- 四、舉例
一、管道的讀寫規則
-
1.當管道沒有數據可以讀取時:
-
O_NONBLOCK disable :read調用阻塞,即進程暫停執行,一直等到有數據到來位置
-
O_NONBLOCK enable :read調用返回-1,error為EAGIN
-
2.當管道滿的時候,往管道中寫數據:
-
O_NONBLOCK disable :write調用會阻塞,直到有進程讀取數據
-
O_NONBLOCK enable : write調用返回-1, error為EAGIN
-
3.如果所有管道寫端對應的文件描述符被關閉,則read返回0;
-
4.如果所有管道的讀端對應的文件描述符都被關閉,則write操作會產生信號SIGPIPE,進而可能導致write進程退出
-
5.當要寫入的數據量不大于PIPE_BUF時,linux保證寫入的原子性
-
6.當要寫入的數據量大于PIPE_BUF時,Linux將不再保證寫入的原子性。
-
7.管道的特點:
-
只能用于具有共同祖先的進程(具有親緣關系的進程)之間的通信,通常一個管道有一個進程創建,然后該進程調用fork函數,這樣父子進程都可以使用該管道,就可以完成父子進程間的通信
-
管道提供流式的服務
-
一般而言,進程退出,管道釋放,所以管道的生命周期隨進程。
-
注意,所有引用管道的進程都退出,管道才能釋放
-
一般而言,內核會對管道操作進行同步與互斥
-
管道是半雙工的,數據只能單方向流動;需要雙向流動時,需要建立兩個管道
二、命名管道
-
1.命名管道的引入
-
根據上面可以得知管道的一個限制條件是只能用于具有親緣關系的進程之間進行通信。
-
如果我們想在不相關的進程間進行通信,進行數據交換,可以使用FIFO文件完成,即命名管道。
-
命名管道是一種特殊的管道文件(P)。
-
2.創建命名管道
-
a.程序內部創建:
- b.命令行創建:
- 3.命名管道與匿名管道的區別
| 可以有命令行和mkfifo函數創建,打開用open | 由pipe函數創建 |
| 適用于同主機上的任意兩個進程間的通信 | 只適用于具有親緣關系的進程之間進行通信 |
命名管道和匿名管道的主要區別還是在于它們的創建和打開方式不同,一旦這些工作完成,那么它們之間具有相同的語義。
三、命名管道的寫入規則
-
1.如果當前打開操作是為讀而打開FIFO時
-
O_NONBLOCK disable : 阻塞到有相應進程為寫而打開FIFO
-
O_NONBLOCK enable : 立即返回成功
-
2.如果當前打開操作是為寫而打開FIFO時
-
O_NONBLOCK disable :阻塞到有相應進程為讀而打開FIFO
-
O_NONBLOCK enable : 立即返回失敗,錯誤碼為ENXIO
四、舉例
- 1.用命名管道實現文件的拷貝:
把文件的內容寫入到管道
把管道的內容寫到文件
#include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <errno.h> #include <string.h>#define ERR_EXIT(m)\do\ {\perror(m);\exit(EXIT_FAILURE);\ }while(0)int main() {//讀取管道,寫入目標文件int outfd = open("abc.back",O_WRONLY | O_TRUNC,0664);if(outfd == -1){perror("open is error");exit(1);}int infd = open("tp",O_RDONLY);if(infd == -1){perror("open is error");exit(1);}char buf[10];int n = read(infd,buf,10);if(n >0){write(outfd,buf,n);}close(infd);close(outfd);unlink("tp");return 0; }- 2.用命名管道實現server&client通信
server端:
client端:
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <sys/stat.h> #include <sys/types.h> #include <string.h> #include <fcntl.h>int main() {int wfd = open("mypipe",O_WRONLY);if(wfd < 0){perror("open pipe is error");exit(1);}char buf[1024];while(1){buf[0] = 0;printf("Please Enter!\n");fflush(stdout);ssize_t s = read(0,buf,sizeof(buf)-1);if(s <= 0){perror("read is error");continue;}else if(s > 0){buf[s] = 0;write(wfd,buf,sizeof(buf));}}close(wfd);return 0; }總結
- 上一篇: 进程间通信(一)
- 下一篇: 区分多种类型的输入输出