进程间通信方式----管道通信
C语言中的管道通信是通过在内核中开辟一块空间,用户通过文件io接口来访问这块空空间实现通信目的。管道的优点是直接访问内存,通信速度较快。缺点是一方面管道属于半双工的通信,即同一进程只能读或者写,无法同时读写同一管道。另一方面管道中的数据只能读一次,无法重复读取。进程通过文件IO来操作管道,但是不能使用lseek()操作。管道分为有名管道(fifo)和无名管道(pipe)
- 无名管道(pipe)
无名管道在内核中没有自己的文件名。这决定了它只能用于父子进程间的通信。
头文件:
#include <unistd.h>
函数原型:
int pipe(int pipefd[2]);
int pipe2(int pipefd[2], int flags);
@pipefd:存储创建后管道两端的两个文件描述符pipefd[0]为读端,pipefd[1]为写端。
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
int main()
{
//创建无名管道
int fd[2];
if (-1 == pipe(fd))
{
perror("pipe error");
return 0;
}
//创建进程
int pid = fork();
if (-1 == pid)
{
perror("pid error");
return 0;
}
else if (0 == pid)
{
//子进程
close(fd[0]);//关闭读端
char buf[10] = "hello!";
write(fd[1], buf, 10);
}
else
{
//父进程
sleep(1);//确保管道信息已写入
close(fd[1]);//关闭写端
char buf[10] = {0};
read(fd[0], buf, 10);
printf("%s\n", buf);
}
//等待程序结果输出完毕退出程序
sleep(2);
return 0;
}
管道在默认情况(没有设置O_NONBLOCK)下属于阻塞读写
注意:
1)所有写端都关闭,仅有读端描述符时,读端读取数据,read返回0
2)所有读端都关闭,写端写入数据,进程将收到SIGPIPE信号,程序崩溃
3)写端不再写入数据,读端将管道数据读取完毕后再读取会阻塞
4)读端不再读取数据,写端还在写入数据到管道,管道空间满后,继续写入数据会阻塞
- 有名管道
有名管道可以通过路径名来指出,并且在文件系统中可见,但内容存放在内存中。所以有名管道可以在非父子管道之接进行通信。
头文件:
#include <sys/types.h>
#include <sys/stat.h>
函数原型:
int mkfifo(const char *pathname, mode_t mode);
@pathname:带路径的文件名,表示要创建的管道
@mode:权限(可以使用0666(读写权限)这种写法)
fifowrite.c
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define FIFO_PATH "/home/abing/test.fifo"
int main()
{
//创建管道
if (-1 == mkfifo(FIFO_PATH, 0666) && errno != EEXIST)
{
perror("mkfifo error");
return 0;
}
//打开管道
int fd = open(FIFO_PATH, O_WRONLY);
if (-1 == fd)
{
perror("open error");
return -1;
}
//写入数据
write(fd, "hello!", 7);
close(fd);
return 0;
}
fiforead.c
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#define FIFO_PATH "/home/abing/test.fifo"
int main()
{
//打开管道
int fd = open(FIFO_PATH, O_RDONLY);
if (-1 == fd)
{
perror("open error");
return -1;
}
//读取数据
char buf[10] = {0};
read(fd, buf, 7);
printf("%s\n", buf);
close(fd);
return 0;
}