8.14 管道
进程间通信(IPC):管道 信号量 共享内存 消息队列 套接字
管道:
有名管道:可以用在任意两个进程之间
mkfifo fifo pipe()
无名管道:只能用在父子进程之间(方便)
管道特点:
1 打开管道后 在内存中分配空间(大小永远为零 不在磁盘上写入 永远在内存中)
2 向管道中写入数据 实际是写入在内存中
3 读取 也是从内存中读取数据
!4 写端关闭,读端read()返回值为0 (作为循环判断的退出条件)
如果读端关闭 写端写入数据就会产生异常 (收到信号SIGPIPE)
半双工 单工 全双工
(管道)
!面试常问:
1 有名无名区别:无名在父子进程间 有名在任意进程间
2 写入管道的数据:内存
3 通讯方式:半双工
有名管道:
a:写入 b:读取
(a.c)
#include <stdio.h>
#include <stdlib.h>
#include <unsited.h>
#include <string.h>
#include <fcntl.h>
int main()
{
int fd = open("fifo",O_RDONLY); //可能阻塞
if(fd == -1)
{
exit(0);
}
printf("fd = %d\n",fd);
while(1)
{
char buff[128] = {0};
printf("input:\n");
fgets(buff,128,stdin); //可能阻塞
if(strncmp(buff,"end",3) == 0)
{
break;
}
write(fd,buff,strlen(buff));
}
close(fd);
exit(0);
}
(b.c)
#include <stdio.h>
#include <stdlib.h>
#include <unsited.h>
#include <string.h>
#include <fcntl.h>
int main()
{
int fd = open("fifo",O_RDONLY);
if(fd == -1)
{
exit(0);
}
printf("fd = %d\n",fd);
while(1)
{
char buff[128] = {0};
int n = read(fd,buff,127); //可能阻塞
if(n == 0)
{
break;
}
printf("buff(%d)=%s\n",n,buff);
}
close(fd);
exit(0);
}
无名管道:
int pipe(int fd[2])
fd[0] 读端
fd[1] 写端
在父子进程之间形成单向数据流(eg:先关闭父进程读端 后关闭子进程写端) 父子进程间形成通讯
#include <stdio.h>
#include <stdlib.h>
#include <unsited.h>
#include <string.h>
//(1)在单个进程中打开关闭读端写端
int main()
{
int fd[2]; //fd[0] 读 fd[1] 写
if(pipe(fd) == -1)
{
printf("create pipe err\n");
exit(0);
}
write(fd[1],"hello",5);
sleep(3);
char buff[128] = {0};
int n = read(fd[0],buff,127);
printf("read(%d)=%s\n",n,buff);
close(fd[0]);
close(fd[1]);
exit(0);
}
!//(2)在父子进程间创建管道形成通讯
int main()
{
int fd[2]; //f创建管道
if(pipe(fd) == -1)
{
printf("create pipe err\n");
exit(0);
}
//创建子进程
pid_t pid fork();
if(pid == -1)
{
close(fd[0]);
close(fd[1]);
exit(0);
}
if(pid == 0)
{
//读
close(fd[1]); //关闭写端
char buff[128]={0};
read(fd[0],buff,127); //读取
printf("child:%s\n",buff); //打印
close(fd[0]);
}
else
{
//写
close(fd[0]); //关闭读端
write(fd[1],"hello",127); //写入
close(fd[1]);
}
exit(0);
}