Linux(高階程式設計)6————程序間通訊2(命名管道)
阿新 • • 發佈:2019-02-03
通過匿名管道學習,我們對管道有了一些瞭解,下面我們將進行下一步學習管道,這次來學習一下匿名管道,關於管道這裡就不在贅言了,直接上命名管道。
- 命名管道:
1.檔案系統可見。
2.命名管道是一類特殊型別檔案(管道型別檔案) 。
3.命名管道可以應用於同一主機上所有的程序之間的通訊(命名管道於匿名管道區別)。 - 命名管道的建立:
函式原型:
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
pathname:建立管道檔案的名字
mode:檔案許可權
成功返回:返回0;失敗返回:-1。
當管道建立好後,即可開啟像操作檔案那樣操作管道了。
- 命名管道的開啟特性(只有命名管道有這個特性):
1.如果以只讀的方式開啟命名管道 ,那麼open函式將阻塞,直到其它程序以寫的方式開啟這個命名管道。
2.如果以只寫的方式開啟命名管道 ,那麼open函式將阻塞,直到其它程序以讀的方式開啟這個命名管道。
3.如果以讀寫的方式開啟命名管道,則不會阻塞(但這樣會與管道特性半雙工向違背,以讀寫的方式開啟會出現問題的)。
4讀的特性:
read特性:if(ret>0)讀到資料;if(ret == 0)寫端關閉。
瞭解了命名管道的這些特性後就可以來做一個小案例練練手了:
案例1:通過命名管道實現檔案拷貝
read_file.c:讀取將要複製的檔案並寫入管道
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<fcntl.h> #include<sys/stat.h> #include<sys/types.h> #include<string.h> #include<errno.h> #define OUT "out" int main(void) { //1.建立管道 if(mkfifo("F_PIPE",0664)<0) { if(errno != EEXIST) { perror("mkfifo"); exit(-1); } } //2.開啟管道檔案,開啟要寫入的檔案 int fd = open(OUT,O_TRUNC|O_WRONLY|0664); int rfd = open("F_PIPE",O_RDONLY); if(rfd<0 || fd<0) { perror("open"); exit(-1); } //3.將管道中的檔案寫入要複製的目標檔案中 ssize_t size = 0; char buf[1024]; while((size = read(rfd,buf,sizeof(buf)-1))>0) { write(fd,buf,size); } printf("write FILE over!\n"); close(rfd); close(fd); return 0; }
write_file.c:讀取管道中的檔案並寫入目標檔案
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
#define OUT "out"
int main(void)
{
//1.建立管道
if(mkfifo("F_PIPE",0664)<0)
{
if(errno != EEXIST)
{
perror("mkfifo");
exit(-1);
}
}
//2.開啟管道檔案,開啟要寫入的檔案
int fd = open(OUT,O_TRUNC|O_WRONLY|0664);
int rfd = open("F_PIPE",O_RDONLY);
if(rfd<0 || fd<0)
{
perror("open");
exit(-1);
}
//3.將管道中的檔案寫入要複製的目標檔案中
ssize_t size = 0;
char buf[1024];
while((size = read(rfd,buf,sizeof(buf)-1))>0)
{
write(fd,buf,size);
}
printf("write FILE over!\n");
close(rfd);
close(fd);
return 0;
}
執行效果展示:
當管道以只讀或只寫的方式開啟時,會在open函式處阻塞(命名管道的開啟規則)。
當我們在執行write_file時,管道的讀寫都被開啟,阻塞就被解除。
接下來在執行write_file:
當write_file執行管道讀端被開啟,read_file被解除阻塞!!!,檔案複製完成!!!
案例2:通過命名管道實現server&client通訊
server.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
int main(void)
{
//建立命名管道
int rfd = -1;
if((mkfifo("FIFO",0664))<0)
{
if(errno != EEXIST)
{
perror("mkfifo!");
exit(-1);
}
}
//開啟管道
rfd = open("FIFO",O_RDONLY);
if(rfd<0)
{
perror("open");
exit(-1);
}
//迴圈的從命名管道中讀取資料
char buf[1024];
while(1)
{
printf("please wait client enter....\n");
int ret = read(rfd,buf,sizeof(buf)-1);
buf[ret] = 0;
if(ret>0)
printf("client say:%s",buf);
//當ret == 0時,說明寫端關閉
else if(ret == 0)
{
printf("client has quit,exit now!\n");
exit(1);
}
else
{
perror("read!");
exit(-1);
}
}
close(rfd);
return 0;
}
client.c:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<string.h>
#include<errno.h>
int main(void)
{
//建立命名管道
int wfd = -1;
if((mkfifo("FIFO",0664))<0)
{
if(errno != EEXIST)
{
perror("mkfifo!");
exit(-1);
}
}
//開啟管道
wfd = open("FIFO",O_WRONLY);
if(wfd<0)
{
perror("open");
exit(-1);
}
//迴圈的向命名管道中寫入資料
char buf[1024];
while(1)
{
buf[0] = 0;
printf("client enter# ");
fflush(stdout);
int ret = read(0,buf,sizeof(buf)-1);
if(ret>0)
{
int size = write(wfd,buf,ret);
if(size<0)
{
perror("write!");
exit(-1);
}
}
}
close(wfd);
return 0;
}
執行效果展示:
總結(命名管道與匿名管道的區別):
1.匿名管道由pipe建立並開啟;命名管道由mkfifo建立,通過open開啟。
2.匿名管道只能用於具有親緣關係的程序間通訊;命名管道可以應用於同一主機上的所有程序間通訊。
3.命名管道檔案系統可見。
4.命名管道是一個特殊型別(管道型別)檔案。