一、我们在学习进程间通信的时候学习过匿名管道pipe,匿名管道的特点:
- 只能用于单向通信
- 只能用于有血缘关系的两个进程,通常是父子进程
- 生命周期随进程
- 面向字节流
- 具有同步机制
我们现在学习一种新的管道socketpair,可以用于双向通信,也是用于父子进程,代码实现与匿名管道类似
#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
int main(){
int fd[2];//fd[0]文件描述符读端 fd[1]文件描述符写端
//创建管道
if(socketpair(AF_LOCAL,SOCK_STREAM,0,fd)<0){
perror("socketpair");
return 1;
}
//创建子进程
pid_t id = fork();
if(id<0){
perror("fork");
exit(2);
}else if(id == 0){//child-->first write next read
close(fd[0]);
char buf[1024];
memset(buf,0,sizeof(buf));
//子进程先向文件写数据,再从文件读数据
while(1){
ssize_t s = read(0,buf,sizeof(buf)-1);
if(s<0){
perror("read");
exit(3);
}
write(fd[1],buf,strlen(buf));
sleep(1);
s = read(fd[1],buf,sizeof(buf)-1);
buf[s] = '\0';
printf("child: Father say:%s",buf);
}
//父进程从文件读数据,再写入数据
}else{//father-->first read next write
close(fd[1]);
char msg[1024];
memset(msg,0,sizeof(msg));
while(1){
ssize_t r = read(fd[0],msg,sizeof(msg)-1);
if(r<0){
perror("read");
exit(4);
}
msg[r] = '\0';
printf("Father:Child say: %s",msg);
read(0,msg,sizeof(msg)-1);
write(fd[0],msg,strlen(msg));
}
}
return 0;
}
结果图:
二、 dup对文件描述符重定向
1.我们之前学习新建文件的文件描述符是pcb中文件描述符表中未被使用的最小的一个文件描述符(默认打开0、1、2),方法如下:
先关闭我们想要使用的文件描述符0或1,在用open创建文件,此时fifo文件的fd即为0或1
2.如果我们首先创建文件,再想改变文件的fd ,这时就要用dup,文件描述符重定向;
先创建文件fifo,在关闭文件描述符,在dup
如果我们关闭的文件描述符是1(标准输出),且将fifo的文件描述符重定向为1,那么所有向标准输出上打印的东西全部输入到fifo文件中。