一、无名管道
1.无名管道函数图
2. 管道文件是一个特殊文件,它由队列实现的。
在文件IO中,创建、打开一个文件是由open函数实现,但是无名管道不能用open创建,对应的函数是pipe。
创建:pipe(fd) //fd[0]是读端口,fd[1]是写端口
读:read(f[0], readbuf, 128 ) //在管道读取128byte到readbuf内存中,实际读取字节数<=128字节
写:write(f[0], writebuf, sizeof(writebuf) ) //将writebuf内存中的数据写入到管道中,大小为sizeof(writebuf)个字节
关闭:
close(fd[0]) //close read
close(fd[1]) //close write
无名管道的无名是指在它在文件系统中无文件名。
3.无名管道的特性
3.1 没有名字,因此不能使用open函数,只能在进程中创建,然后通过继承方式将无名管道文件描述符传递给子进程
3.2 只能用于亲缘进程间(父子、兄弟、祖孙进程)通讯
3.3 半双工,读写分开
3.4 写入不具备原子性,因此只能一对一的简单通讯
3.5 跟FIFO和socket一样,不能使用lseek()来定位,他们不像普通文件一样存放在磁盘、flash等设备上。
3.6 具有读写堵塞性,当管道写满或者管道无数据的时候去读取管道,将会堵塞
4.例子:
#include "unistd.h"
#include "stdio.h"
#include "sys/types.h"
#include "stdlib.h"
int main()
{
pid_t pid;
int fd[2];
int ret;
char process_inter=0;
ret=pipe(fd); //必须先创建管道,然后再创建子进程。如此才能继承父进程的PIPE文件描述符
if(ret < 0)
{
printf("creat pipe failure\n");
return -1;
}
printf("creat pipe sucess\n");
pid = fork();
if(pid ==0)//child process code second
{
int i=0;
read(fd[0],&process_inter,1);//如果管道没有数据则堵塞
while(process_inter ==0);
for(i=0;i<2;i++)
{
printf("this is child process i=%d\n",i);
usleep(100);
}
}
if(pid >0)//parent process code first
{
int i=0;
for(i=0;i<2;i++)
{
printf("this is parent process i=%d\n",i);
usleep(100);
}
process_inter=1;
sleep(5);
write(fd[1],&process_inter,1); //如果管道数据填满管道内存则堵塞
}
while(1);
return 0;
}
效果如下:
c@c:$ ./a.out
creat pipe sucess
this is parent process i=0
this is parent process i=1
this is parent process i=2
this is child process i=0
this is child process i=1
this is child process i=2
二、有名管道
1.有名管道函数图
2. mkfifo使用方法与open类似,有名管道创建完后,在指定目录中生成文件。
mkfifo调用内核,内核在文件系统中生成文件名,并没有在内核中生成管道。只有在调用open代开有名管道时,才会在内核中创建管道。这个文件不占用磁盘空间,只有innode号,和套接字、字符设备文件、块设备文件一样。普通文件,符号链接文件及目录文件不仅有inode号,还占用磁盘空间。
创建有名管道mkfifo。跟普通文件一样使用,打开open,读read,写write,关闭close。
3.有名管道的特性
3.1 两个进程操作有名管道时,一个读,一个写。当读端RD,写端WR都打开时,程序才会运行,不然会阻塞。(就是管道读写都开打时,open函数才能打开管道)
3.2 有名字,存储于普通文件系统之中
3.3 任何具有相应权限的进程都可以使用open()来获取FIFO的文件描述符
3.4 跟普通文件一样:使用统一的read、write来读写
3.5 具有原子性,支持多写者同时进行写操作而数据不会相互践踏
3.6 First In First Out, 最先被写入FIFO的数据。最先被读写出来
3.7 跟普通文件不同,不能使用lseek()来定位
写者:持有文件可写权限的描述符的进程
读者:持有文件可读权限的描述符的进程
4.例子:
第一个进程:
#include "unistd.h"
#include "stdio.h"
#include "sys/types.h"
#include "stdlib.h"
#include "fcntl.h"
#define MYFIFO "/home/c/process/myfifo"
int main()
{
int fd;
int i;
char process_inter=0;
if(access(MYFIFO, F_OK)) //只判断是否存在,不存在返回非0
{
mkfifo(MYFIFO, 0644);
}
fd=open("./myfifo",O_WRONLY);
if(fd <0)
{
printf("open myfifo failure\n");
return -1;
}
printf("open myfifo sucess\n");
for(i=0;i<5;i++)
{
printf("this is first process i=%d\n",i);
usleep(100);
}
process_inter=1;
sleep(5);
write(fd,&process_inter,1);
while(1);
return 0;
}
第二个进程:
#include "unistd.h"
#include "stdio.h"
#include "sys/types.h"
#include "stdlib.h"
#include "fcntl.h"
#define MYFIFO "/home/c/process/myfifo"
int main()
{
int fd;
int i;
int process_inter=0;
if(access(MYFIFO, F_OK)) //只判断是否存在,不存在返回非0
{
mkfifo(MYFIFO, 0644);
}
fd=open("./myfifo",O_RDONLY);
if(fd <0)
{
printf("open myfifo failure\n");
return -1;
}
printf("open myfifo sucess\n");
read(fd,&process_inter,1);
while(process_inter == 0);
for(i=0;i<5;i++)
{
printf("this is second process i=%d\n",i);
usleep(100);
}
while(1);
return 0;
}
参考:https://blog.csdn.net/wenwen111111/article/details/54645682