特点:
1)有名管道可以使互不相关的两个进程互相通信
2)有名管道可以通过路径名来指出,并且在文件系统中可见
有名管道的文件名在文件系统可见,但是管道中的数据在内存上
文件系统:一种管理文件的机制,对文件进行管理,维护
不支持如lseek() 操作
3)进程通过文件IO来操作有名管道(先打开,再读写)
管道创建
命令行
mkfifo fifo 创建名为“fifo”的管道,后期权限不足通过chmod修改
unlink fifo 删除名为“fifo”的管道
函数创建
int mkfifo(const char *pathname, mode_t mode);
int unlink(const char *pathname);
具体参数用法建议使用前man一下
管道的操作 参考博客链接:https://blog.csdn.net/aLingYun/article/details/100085981
有名管道在操作上和普通文件一样进行,如:open()、write()、read()、close() 等。但是,和无名管道一样,操作命名管道肯定要考虑默认情况下其阻塞特性。
1.以只读和只写方式 open 管道,并且没有指定非阻塞标志 O_NONBLOCK 。则:
open() 以只读方式打开 FIFO 时,要阻塞到另一个进程为写而打开此 FIFO;
open() 以只写方式打开 FIFO 时,要阻塞到另一个进程为读而打开此 FIFO。
通信过程中若写进程先退出了,就算命名管道里没有数据,调用 read() 函数从 FIFO 里读数据时不阻塞;若写进程又重新运行,则调用 read() 函数从 FIFO 里读数据时又恢复阻塞。
2.以只读和只写方式 open 管道,并指定非阻塞标志 O_NONBLOCK 。则 open() 函数不会阻塞。
非阻塞标志(O_NONBLOCK)打开的命名管道有以下特点:
先以只读方式打开,如果没有进程已经为写而打开一个 FIFO, 只读 open() 成功,并且 open() 不阻塞。
先以只写方式打开,如果没有进程已经为读而打开一个 FIFO,只写 open() 将出错返回 -1 。
read()、write() 读写命名管道中读数据时不阻塞。
3.以可读可写方式 open 管道,则 open() 函数不会阻塞。
特点:
read() 仍会阻塞,缓冲区满时,write() 也会阻塞;
通信过程中,读进程退出后,写进程向命名管道内写数据时,写进程不会退出。
通信过程中若写进程先退出了,如果名管道里没有数据,调用 read() 函数从 FIFO 里读数据时会阻塞,与第一种情况不同。
示例代码 发送进程
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#define N 32
int main(int argc, const char *argv[])
{
int fd;
int ret;
ret = mkfifo("fifo", 0775); //创建有名管道fifo
if(ret < 0){
if(errno == EEXIST){ //错误编号为管道已存在(其他进程用户创建),执行打开管道操作
fd = open("fifo", O_RDWR);
printf("fd = %d\n", fd);
}
else{ //创建失败
perror("mkfifo error");
return -1;
}
}
else{ //创建成功并执行打开管道操作
fd = open("fifo", O_RDWR);
printf("fd = %d\n", fd);
}
char buf[N] = "";
while(1){
fgets(buf, N, stdin); //获取输入信息
buf[strlen(buf) - 1] = '\0';
write(fd, buf, strlen(buf)); //发送至管道
if(strncmp(buf, "quit", 4) == 0){
break;
}
}
return 0;
}
示例代码接收端
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#define N 32
int main(int argc, const char *argv[])
{
int fd;
int ret;
ret = mkfifo("fifo", 0775); //创建有名管道fifo
if(ret < 0){
if(errno == EEXIST){ //错误编号为管道已存在(其他进程用户创建),执行打开管道操作
fd = open("fifo", O_RDWR);
printf("fd = %d\n", fd);
}
else{
perror("mkfifo error");
return -1;
}
}
else{
fd = open("fifo", O_RDWR);
printf("fd = %d\n", fd);
}
char buf[N] = "";
while(1){
memset(buf, 0, N);
read(fd, buf, N); //读取管道数据
if(strncmp(buf, "quit", 4) == 0){
break;
}
printf("read:%s\n", buf);
}
return 0;
}
在这里插入代码片