1、无名管道
1)、特点:
只能用于具有亲缘关系的进程之间的通信
半双工的通信模式,具有固定的读端和写端
管道可以看成是一种特殊的文件,对于它的读写可以使用文件IO如read、write函数。
#include <unistd.h>
int pipe(int pipefd[2]); //创建管道,得到管道的读端fd[0]和写端fd[1]
参数:
pipefd ---- 存放读写文件描述符的数组首地址
返回值:
成功: 0
失败: -1, 并设置errno
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
pid_t pid;
char buf[100];
int ret;
int fd[2];
if (0 > pipe(fd))
{
perror("pipe");
return -1;
}
printf("fd: %d %d\n", fd[0], fd[1]);
if (0 > (pid = fork()))
{
perror("fork");
return -1;
}
else if (0 == pid) //child:write
{
close(fd[0]);
while (1)
{
printf("Child input: ");
fgets(buf, sizeof(buf), stdin);
if (0 > write(fd[1], buf, sizeof(buf)))
{
perror("write");
break;
}
if (strncmp(buf, "quit", 4) == 0)
break;
}
close(fd[1]);
}
else //parent: read
{
close(fd[1]);
while (1)
{
ret = read(fd[0], buf, sizeof(buf));
if (ret < 0)
{
perror("read");
break;
}
else if (0 == ret)
{
printf("read end!\n");
break;
}
else
printf("Parent recv: %s", buf);
}
close(fd[0]);
}
return 0;
}
2、有名管道FIFO
无名管道只能用于具有亲缘关系的进程之间,这就限制了无名管道的使用范围
有名管道可以使互不相关的两个进程互相通信。有名管道可以通过路径名来指出,并且在文件系统中可见
进程通过文件IO来操作有名管道
有名管道遵循先进先出规则
不支持如lseek() 操作
有名管道的内容保存在内存中
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *pathname, mode_t mode);
参数:
pathname --- 路径 + 名字
mode --- 权限,一般0664
返回值:
成功: 0
失败: -1, 并设置errno
使用: open close read write
有名管道的创建(mkfifo):
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
int main(int argc, char *argv[])
{
if (0 > mkfifo("myfifo", 0664))
{
perror("mkfifo");
return -1;
}
return 0;
}
有名管道的读(read):
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int fd = open("myfifo", O_RDONLY);
if (fd < 0)
{
perror("open");
return -1;
}
char buf[100];
int ret;
while (1)
{
ret = read(fd, buf, sizeof(buf));
if (ret < 0)
{
perror("read");
break;
}
else if (0 == ret)
{
printf("read end!\n");
break;
}
printf("recv: %s\n", buf);
}
close(fd);
return 0;
}
有名管道的写(write):
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
int main(int argc, char *argv[])
{
int fd = open("myfifo", O_WRONLY);
if (fd < 0)
{
perror("open");
return -1;
}
char buf[100];
int ret;
while (1)
{
printf("Input: ");
fgets(buf, sizeof(buf), stdin);
ret = write(fd, buf, sizeof(buf));
if (ret < 0)
{
perror("write");
break;
}
if (strncmp(buf, "quit", 4) == 0)
break;
}
close(fd);
return 0;
}
==总结==:
* 管道只有在读写端存在时才有意义
* 写端存在时,当管道中有数据时,读端可以读到数据,没有数据时,读端阻塞。但是写端关闭时,读端会把管道中的数据都读走后返回0
* 当读端存在时但不读取数据,写端把管道缓冲区写满后会阻塞,直到读端读走数据就可以继续写入
* 当读端关闭时,写端再向管道中写入,会出现管道破裂的信号(SIGPIPE)导致进程结束