linux进程间通信:命名管道FIFO
生活随笔
收集整理的這篇文章主要介紹了
linux进程间通信:命名管道FIFO
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- FIFO 通信特點
- 系統調用接口
- 應用
- 擁有親緣關系之間的進程通信
- 非親緣關系進程之間的通信
- 總結
FIFO 通信特點
- FIFO文件有文件名
- 可以像普通文件一樣存儲在文件系統之中
- 可以像普通文件一樣使用open/write讀寫
- 和pipe文件一樣屬于流式文件,不能使用lseek系統調用重定位文件偏移地址
- 具有寫入原子性,支持多個進程同時對FIFO進行寫操作,如日志系統
/var/log - First in First out,先入先出。最先被寫入的數據最先被讀出來
- 默認阻塞讀,阻塞寫的特性??梢栽趏pen的時候進行設置
- 如果一個進程打開fifo的一端時,令一端沒有打開,該進程會被阻塞。
fifo與pipe最大的區別就是pipe只能用于親緣進程之間的通信(fork方式創建的父子進程),但是fifo可以支持任意兩個進程之間的通信,并包括擁有親緣關系的進程
系統調用接口
- shell命令:
mkfifo pathname,可以通過man mkfifo查看命令用法 - 函數接口:
int mkfifo(const char *pathname,mode_t mode) - 函數功能:創建fifo的有名管道
- 函數參數:
-pathnameFIFO管道文件名
-mode讀寫權限
應用
擁有親緣關系之間的進程通信
通信過程類似于pipe的fd[0]讀出,fd[1]寫入
#include <sys/types.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <stdio.h>#define FIFO "testfifo"
int main()
{int a=mkfifo(FIFO,0644);if (0 != a)printf("mkfifo failed %d\n",a);int ret,fifo_fd;ret = fork();if (ret == -1) {perror("fork");_exit(-1);}//子進程負責寫入管道else if (ret == 0) {fifo_fd = open("testfifo",O_RDWR);char buf[100];memset(buf,0,100);printf("child process(%d) input msg:",getpid());//scanf("%s",buf);fgets(buf,10,stdin);int write_len = write(fifo_fd,buf,strlen(buf));printf("%d bytes has been sent\n",write_len);_exit(1);}//父進程進行從管道進行讀取else {sleep(5);fifo_fd = open("testfifo",O_RDWR);char buf[100];memset(buf,0,100);printf("father process befor read\n");int read_len = read(fifo_fd,buf,100);if (read_len == -1)printf("read error %d\n",read_len);printf("father process(%d) read message from fifo :%s\n",getpid(),buf);_exit(1);}return 0;
}
非親緣關系進程之間的通信
寫端:
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>#define FIFO_NAME "testfifo"int main(int argc, char* argv[])
{int fd;char buf[100];mkfifo(FIFO_NAME, S_IFIFO|0666);//循環向testinfo中寫入數據while (1){printf("please input the string : \n");fd = open(FIFO_NAME, O_WRONLY);fgets(buf,100,stdin);write(fd, buf, strlen(buf)+1);close(fd);}unlink(FIFO_NAME); //刪除命名管道文件sleep(1);return 0;
}
讀端:
#include <stdio.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>#define FIFO_NAME "testfifo"
#define BUF_SIZE 1024int main(int argc, char* argv[])
{int fd;char buf[BUF_SIZE];//循環從testinfo中讀取數據while (1) {fd = open(FIFO_NAME, O_RDONLY);//read系統調用會從打開的文件當前文件偏移地址開始讀,即上次寫入的數據read(fd, buf, BUF_SIZE);printf("%s\n", buf);close(fd);}return 0;
}
總結
為什么無名管道只能用于父子進程之間的通信呢?無名管道是一個文件,但是只能存在與內存之中,且該文件的讀寫方式是固定的,我們只能從一端寫入,一端讀出。使用無名管道通信,他得文件句柄需要在同一個進程內共享。即在同一個進程內只有fork的方式,能夠將當前進程所有文件描述符以及進程狀態信息拷貝給另一個進程;只有在這樣的進程關系之下,無名管道的數據傳輸才能實現一端寫入,一端讀出。
命名管道fifo可以像普通文件一樣存在與操作系統磁盤之中,同樣支持read/write的數據讀寫,因此它能夠被多個進程共同訪問。雖然fifo相比于pipe使用范圍擴大了,但是總體的阻塞式通信依然存在。
pipe的內核實現fs/pipe.c中pipe_read和pipe_write函數處理過程中都是通過加鎖mutex來實現,并沒有相關的異步操作,而fifo的fifo_open函數同樣是阻塞式處理函數體。
總結
以上是生活随笔為你收集整理的linux进程间通信:命名管道FIFO的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 陌陌个性签名超拽霸气
- 下一篇: 少了我的陪伴是哪首歌啊?