5.09有名管道的概述
pipe指的是无名管道
fifo指的是有名管道
FIFO会在文件系统中直接创建一个可见的文件
linux系统中的文件类型分为7大类 :bcd-lsp
fifo和pipe区别:
1、fifo属于半双工,数据在同一时刻只能在同一个方向上流动
2、写入fifo中的数据遵守先入先出
3、fifo所传送的数据是无格式的,要求读写格式统一
4、fifo在文件系统中作为一个特殊的文件存在,但是fifo 中的内容却在内存中存在
5、管道在内存中对应一个缓冲区
6、从fifo中读取数据是一次性操作
7、当使用fifo的进程退出时,fifo文件将继续保存在文件系统中,释放空间以便写入更加多的数据
8、fifo有名字,不相关的进程可以实现通信
5.10有名管道的创建
有两种方式创建:
1、在shell命令中
mkfifo 文件名
2、使用函数mkfifo
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode)
功能:创建一个有名管道,产生一个本地文件系统的文件pathname
参数:文件名和权限;成功返回0
如果文件存在,会报错,我们可以通过查看errno.h中的错误码
#include<errno.h>
{
if(mkfifo("fifo_file", 0664) == -1)
{
if(error != EEXIST)
{
这样就可以把文件存在所报的错误给忽略掉
perror("fail to mkfifo");
exit(1);
}
perror("");
}
return 0;
}
5.11有名管道的基本读写操作
系统调用的IO都可以操作FIFO:open,close,read,write等,打开fifo时,非阻塞标志(O_NONBLOCK)产生下列影响;
特点:1、不指定O_NONBLOCK(即open没有位或O_NONBLOCK)
2、open以只读方式打开fifo时,要阻塞多少某个进程为写而打开此fifo
3、open以只写方式打开fifo时,要阻塞多少某个进程为读而打开此fifo
由于有名管道在本地创建了一个管道文件,所以系统调用的IO函数基本都可以对有名管道进行操作,但是不能使用lseek修改管道文件的偏移量
注意:有名管道创建的本地的文件只是起到标识作用,真正有名管道实现进程通信还是在内核空间开辟内存,所以本地产生的文件只是一个标识,没有其他作用。对本地管道文件的操作实质就是对内核空间的操作
#define FIFONAME "fifo_file"
main()
{
if(mkfifo("fifo_file", 0664) == -1)
{
if(error != EEXIST)
{
这样就可以把文件存在所报的错误给忽略掉
perror("fail to mkfifo");
exit(1);
}
perror("");
}
接下来就是对有名管道进行操作
int fd
fd = open(FIFONAME, O_RDWR);
if(...)
然后就是写数据,读数据
int fd
}
5.11有名管道如何实现进程间通信
由于有名管道创建了一个管道文件,所以不相关的进程之间可以实现通信,
创建2个有名管道
需要一个send.c文件和recv.c
send.c
#include<stdio.h>
#include<stdlib.h>
#include<unstd.h>
...
int main(int argc, char **argv)
{
//创建管道-----if判断出错省略了
mkfifo("myfifo1", 0664);
mkfifo("myfifo2", 0664);
int fd_w, fd_r;
fd_w = open("myfifo1", O_WRONLY);
fd_r = open("myfifo2", O_RDONLY);
char buf[128] = "";
ssize_t bytes;
while(1)
{
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf) -1] = '\0';
bytes = write(fd_w, buf, sizeof(buf));
bytes = read(fd_r, buf, sizeof(buf));
printf("from recv:%s\n", buf);
}
return 0;
}
recv.c
#include<stdio.h>
#include<stdlib.h>
#include<unstd.h>
...
int main(int argc, char **argv)
{
创建管道-----if判断出错
mkfifo("myfifo1", 0664);
mkfifo("myfifo2", 0664);
int fd_w, fd_r; //这个地方刚刚好相反
fd_r = open("myfifo1", O_WDONLY);
fd_w = open("myfifo2", O_RDONLY);
char buf[128] = "";
ssize_t bytes;
while(1)
{
bytes = read(fd_r, buf, sizeof(buf));
printf("from send:%s\n", buf);
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf) -1] = '\0';
bytes = write(fd_w, buf, sizeof(buf));
}
return 0;
}
5.13有名管道的基本读写操作
1、读写端都存在,只读不写
会发生阻塞
2、读写端都存在,只写不读
会发生阻塞
3、在一个进程中,只有读端,没有写端
会在open函数的位置阻塞
4、在一个进程中,只有写端,没有读端
会在open函数的位置阻塞