在上一篇介紹了程序間通信方式之管道,連結如下:
http://blog.csdn.net/zhuyunfei/article/details/51087802
今天再來介紹下程序間通信方式之有名管道
1.有名管道
看名字就和明顯了,它和匿名管道的差別就是,這個管道是有“名字”,這個名字是什麼呢?就是FIFO檔案路徑,從檔案操作我們可以大膽推理,既然有檔案路徑,那麼這個檔案就可以被不同的程序所通路,這樣就實作了通過有名管道來實作不同程序間的通信,此時,有名管道就不再像匿名管道那樣受限制,之前的匿名管道隻能在具有親緣關系的程序中通信,匿名管道不适用不具有親緣關系的不同程序間通信。
有名管道也稱為命名管道(named pipe),或者FIFO。
建立有名管道的函數是mkfifo,函數原型是:
int mkfifo (const char *__path, __mode_t __mode)
功能:建立新的帶命名路徑的FIFO
參數:path — 命名管道路徑
mode — 模式權限
傳回值:成功傳回0,失敗傳回-1;
包含mkfifo定義的頭檔案路徑是:/usr/include/x86_64-linux-gnu/sys/stat.h
2.有名管道的特點
a)使不同程序之間完成通信。
通過mkfifo建立FIFO檔案建立有名管道,
使得不同程序可以通過像通路檔案的方式一樣來通路有名管道,
fifo檔案特點:
先進先出:即寫檔案從有名管道資料尾端寫入,資料讀取從有名管道的開始處讀取
b)有名管道内資料不支援如lseek()檔案定位操作
3.阻塞打開與非阻塞打開
對于讀程序
•若該管道是阻塞打開,且目前FIFO内沒有資料,則對讀程序而言将一直阻塞到有資料寫入
•若該管道是非阻塞打開,則不論FIFO内是否有資料,讀程序都會立即執行讀操作。即如果FIFO内沒有資料,則讀函數将立刻傳回0
對于寫程序
•若該管道是阻塞打開,則寫操作将一直阻塞到資料可以被寫入
•若該管道是非阻塞打開而不能寫入全部資料,則讀操作進行部分寫入或者調用失敗
4.例子
writepipe.c
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#define P_FIFO "/tmp/name_pipe"
int main(int argc, char* argv[])
{
int fd;
//指令要帶寫入有名管道的資料
if(argc < 2){
printf("please input the write data.\n");
}
//打開有名管道
//第一個參數指定有名管道路徑
//第二個參數指定以寫以及非阻塞方式打開有名管道
//O_WRONLY寫入方式
//O_NONBLOCK阻塞模式
fd = open(P_FIFO,O_WRONLY|O_NONBLOCK);
//打開有名管道失敗
if(fd < 0){
printf("open failed.\n");
}
//寫入資料到有名管道
//第一個參數為有名管道檔案描述符
//第二個參數為寫入有名管道的資料
//第三個參數為寫入有名管道的資料長度
write(fd,argv[1],100);
//關閉有名管道
close(fd);
return 0;
}
readpipe.c
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#define P_FIFO "/tmp/name_pipe"
int main()
{
int ret = -1;
int fd;
char buffer[100];
//如果有名管道存在,則先删除它
if(access(P_FIFO,F_OK)){
execlp("rm","-f",P_FIFO,NULL);
printf("access.\n");
}
//建立有名管道,并賦予通路有名管道的權限
ret = mkfifo(P_FIFO,0777);
//建立失敗
if(ret < 0){
printf("create named pipe failed.\n");
return 0;
}
//打開有名管道
//第一個參數為有名管道檔案路徑
//第二個參數表明是以讀取方式并以非阻塞方式打開有名管道
//O_RDONLY讀取模式
//O_NONBLOCK非阻塞方式
fd = open(P_FIFO,O_RDONLY | O_NONBLOCK);
//循環讀取有名管道
while(1){
memset(buffer,0,sizeof(buffer));
if(read(fd,buffer,100) == 0){
printf("nodata.\n");
}else{
printf("getdata:%s\n",buffer);
sleep(1);
}
}
close(fd);
return 0;
}
編譯這兩個程式
sudo gcc readpipe.c -o readpipe
sudo gcc writepipe.c -o writepipe
如果需要權重限,
sudo chmod 777 readpipe
sudo chmod 777 writepipe
這時我們先運作readpipe程序,然後運作writepipe程序,并帶一個資料參數hellonamedpipe,這時我們在readpipe程序視窗會看見它讀出了writepipe程序寫入到有名管道中的資料,結果如圖:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISO0ATNzMDN5EzNxQDM2EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)