日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

【Linux系统编程】进程间通信--有名管道

發布時間:2024/4/21 linux 50 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Linux系统编程】进程间通信--有名管道 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

命名管道的概述

無名管道,由于沒有名字,只能用于親緣關系的進程間通信(更多詳情,請看《無名管道》)。為了克服這個缺點,提出了命名管道(FIFO),也叫有名管道、FIFO 文件。


命名管道(FIFO)不同于無名管道之處在于它提供了一個路徑名與之關聯,以 FIFO 的文件形式存在于文件系統中,這樣,即使與 FIFO 的創建進程不存在親緣關系的進程,只要可以訪問該路徑,就能夠彼此通過 FIFO 相互通信,因此,通過 FIFO 不相關的進程也能交換數據


命名管道(FIFO)和無名管道(pipe)有一些特點是相同的,不一樣的地方在于:

1、FIFO 在文件系統中作為一個特殊的文件而存在,但 FIFO 中的內容卻存放在內存中。

2、當使用 FIFO 的進程退出后,FIFO 文件將繼續保存在文件系統中以便以后使用。

3、FIFO 有名字,不相關的進程可以通過打開命名管道進行通信。


命名管道的創建

所需頭文件:

#include <sys/types.h>

#include <sys/stat.h>


int mkfifo( const char *pathname, mode_t mode);

功能:

命名管道的創建。

參數:

pathname:?普通的路徑名,也就是創建后 FIFO 的名字。

mode: 文件的權限,與打開普通文件的 open() 函數中的 mode 參數相同。

返回值:

成功:0
失敗:如果文件已經存在,則會出錯且返回 -1。


示例代碼如下:

#include <stdio.h> #include <sys/types.h> #include <sys/stat.h>int main(int argc, char *argv[]) {int ret;ret = mkfifo("my_fifo", 0666); // 創建命名管道if(ret != 0){ // 出錯perror("mkfifo");}return 0; }

運行結果如下:



命名管道的默認操作

后期的操作,把這個命名管道當做普通文件一樣進行操作:open()、write()、read()、close()。但是和無名管道一樣,操作命名管道肯定要考慮默認情況下其阻塞特性


下面驗證的是默認情況下的特點,即 open() 的時候沒有指定非阻塞標志( O_NONBLOCK )。

1)

open() 以只讀方式打開 FIFO 時,要阻塞到某個進程為寫而打開此 FIFO
open() 以只寫方式打開 FIFO 時,要阻塞到某個進程為讀而打開此 FIFO。

簡單一句話,只讀等著只寫,只寫等著只讀,只有兩個都執行到,才會往下執行。


只讀端代碼如下:

#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main(int argc, char *argv[]) {int fd;int ret;ret = mkfifo("my_fifo", 0666);if(ret != 0){perror("mkfifo");}printf("before open\n");fd = open("my_fifo", O_RDONLY);//等著只寫if(fd < 0){perror("open fifo");}printf("after open\n");return 0; }

只寫端代碼如下

#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main(int argc, char *argv[]) {int fd;int ret;ret = mkfifo("my_fifo", 0666);if(ret != 0){perror("mkfifo");}printf("before open\n");fd = open("my_fifo", O_WRONLY); //等著只讀if(fd < 0){perror("open fifo");}printf("after open\n");return 0; }

大家開啟兩個終端,分別編譯以上代碼,讀端程序和寫端程序各自運行,如下圖,大家自行驗證其特點,因為光看結果圖是沒有效果,大家需要分析其運行過程是如何變化。



如果大家不想在 open() 的時候阻塞,我們可以以可讀可寫方式打開 FIFO 文件,這樣 open() 函數就不會阻塞。

// 可讀可寫方式打開 int fd = open("my_fifo", O_RDWR);

2)假如 FIFO 里沒有數據,調用 read() 函數從 FIFO 里讀數據時 read() 也會阻塞。這個特點和無名管道是一樣的。


寫端代碼如下:

#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main(int argc, char *argv[]) {int fd;int ret;ret = mkfifo("my_fifo", 0666);//創建命名管道if(ret != 0){perror("mkfifo");}printf("before open\n");fd = open("my_fifo", O_WRONLY); //等著只讀if(fd < 0){perror("open fifo");}printf("after open\n");printf("before write\n");// 5s后才往命名管道寫數據,沒數據前,讀端read()阻塞sleep(5);char send[100] = "Hello Mike";write(fd, send, strlen(send));printf("write to my_fifo buf=%s\n", send);return 0; }

讀端代碼如下:

#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main(int argc, char *argv[]) {int fd;int ret;ret = mkfifo("my_fifo", 0666); //創建命名管道if(ret != 0){perror("mkfifo");}printf("before open\n");fd = open("my_fifo", O_RDONLY);//等著只寫if(fd < 0){perror("open fifo");}printf("after open\n");printf("before read\n");char recv[100] = {0};//讀數據,命名管道沒數據時會阻塞,有數據時就取出來read(fd, recv, sizeof(recv)); printf("read from my_fifo buf=[%s]\n", recv);return 0; }

請根據下圖自行編譯運行驗證:



3)通信過程中若寫進程先退出了,就算命名管道里沒有數據,調用 read() 函數從 FIFO 里讀數據時不阻塞;若寫進程又重新運行,則調用 read() 函數從 FIFO 里讀數據時又恢復阻塞。


寫端代碼如下:

#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main(int argc, char *argv[]) {int fd;int ret;ret = mkfifo("my_fifo", 0666); // 創建命名管道if(ret != 0){perror("mkfifo");}fd = open("my_fifo", O_WRONLY); // 等著只讀if(fd < 0){perror("open fifo");}char send[100] = "Hello Mike";write(fd, send, strlen(send)); //寫數據printf("write to my_fifo buf=%s\n",send);while(1); // 阻塞,保證讀寫進程保持著通信過程return 0; }

讀端代碼如下:

#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main(int argc, char *argv[]) {int fd;int ret;ret = mkfifo("my_fifo", 0666);// 創建命名管道if(ret != 0){perror("mkfifo");}fd = open("my_fifo", O_RDONLY);// 等著只寫if(fd < 0){perror("open fifo");}while(1){char recv[100] = {0};read(fd, recv, sizeof(recv)); // 讀數據printf("read from my_fifo buf=[%s]\n",recv);sleep(1);}return 0; }

請根據下圖自行編譯運行驗證:



5)通信過程中,讀進程退出后,寫進程向命名管道內寫數據時,寫進程也會(收到 SIGPIPE 信號)退出。


6)調用 write() 函數向 FIFO 里寫數據,當緩沖區已滿時 write() 也會阻塞。


5)?6)這兩個特點和無名管道是一樣的,這里不再驗證,詳情請看《無名管道》。


命名管道非阻塞標志操作

命名管道可以以非阻塞標志(O_NONBLOCK)方式打開:RDONLY|O_NONBLOCK); ?

fd = open("my_fifo", O_WRONLY|O_NONBLOCK); fd = open("my_fifo", O_RDONLY|O_NONBLOCK);


非阻塞標志(O_NONBLOCK)打開的命名管道有以下特點:
1、先以只讀方式打開,如果沒有進程已經為寫而打開一個 FIFO, 只讀 open() 成功,并且 open() 不阻塞。


2、先以只寫方式打開,如果沒有進程已經為讀而打開一個 FIFO,只寫 open() 將出錯返回 -1。


3、read()、write() 讀寫命名管道中讀數據時不阻塞。


請根據以下代碼自行編譯運行驗證。


寫端代碼如下:

#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main(int argc, char *argv[]) {int fd;int ret;ret = mkfifo("my_fifo", 0666); // 創建命名管道if(ret != 0){perror("mkfifo");}// 只寫并指定非阻塞方式打開fd = open("my_fifo", O_WRONLY|O_NONBLOCK);if(fd<0){perror("open fifo");}char send[100] = "Hello Mike";write(fd, send, strlen(send));printf("write to my_fifo buf=%s\n",send);while(1);return 0; }

讀端代碼如下:

#include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h>int main(int argc, char *argv[]) {int fd;int ret;ret = mkfifo("my_fifo", 0666); // 創建命名管道if(ret != 0){perror("mkfifo");}// 只讀并指定非阻塞方式打開fd = open("my_fifo", O_RDONLY|O_NONBLOCK);if(fd < 0){perror("open fifo");}while(1){char recv[100] = {0};read(fd, recv, sizeof(recv));printf("read from my_fifo buf=[%s]\n",recv);sleep(1);}return 0; }

總結

以上是生活随笔為你收集整理的【Linux系统编程】进程间通信--有名管道的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。