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

歡迎訪問 生活随笔!

生活随笔

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

linux

【Linux系统编程】进程间通信之命名管道

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

00. 目錄

文章目錄

    • 00. 目錄
    • 01. 命名管道概述
    • 02. 命名管道創建
    • 03. 命名管道特性
    • 04. 命名管道非阻塞
    • 05. 附錄

01. 命名管道概述

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

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

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

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

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

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

02. 命名管道創建

相關函數:

#include <sys/types.h> #include <sys/stat.h>int mkfifo(const char *pathname, mode_t mode); 功能:命名管道的創建。 參數:pathname : 普通的路徑名,也就是創建后 FIFO 的名字。mode : 文件的權限,與打開普通文件的 open() 函數中的 mode 參數相同。(0666) 返回值:成功:0 狀態碼失敗:如果文件已經存在,則會出錯且返回 -1

測試代碼:

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

測試結果:

deng@itcast:~$ gcc 1.c deng@itcast:~$ ./a.out deng@itcast:~$ ls fifo fifo deng@itcast:~$

03. 命名管道特性

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

3.1 打開管道阻塞特性

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

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);

3.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; }

通信過程中若寫進程先退出了,就算命名管道里沒有數據,調用 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; }

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

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

這兩個特點和無名管道是一樣的,這里不再驗證。

04. 命名管道非阻塞

命名管道可以以非阻塞標志(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; }

05. 附錄

總結

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

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