一、无名管道通信
无名管道只能在有亲缘关系的进程间通信,即父子进程间通信或者兄弟间通信,创建无名管道会创建两个文件描述符,一个用来执行写操作,一个用来执行读操作。
#include<unistd.h>
#include<sys/types.h>
#include<errno.h>
#include<stdio.h>
#include<stdlib.h>
int main()
{
int pipe_fd[2];
pid_t pid;
char buf_r[100];
char* p_wbuf;
int r_num;
memset(buf_r,0,sizeof(buf_r));
/*创建管道*/
if(pipe(pipe_fd)<0) {
printf("pipe create error\n");
return -1;
}
/*创建子进程*/
if((pid=fork())==0) //子进程 OR 父进程?
{
printf("\n");
close(pipe_fd[1]);
sleep(2); /*为什么要睡眠*/
if((r_num=read(pipe_fd[0],buf_r,100))>0)
{
printf("%d numbers read from the pipe is %s\n",r_num,buf_r);
}
close(pipe_fd[0]);
exit(0);
}
else if(pid>0)
{
close(pipe_fd[0]);
if(write(pipe_fd[1],"Hello",5)!=-1)
printf("parent write1 is Hello!\n");
if(write(pipe_fd[1],"Pipe",5)!=-1)
printf("parent write2 is Pipe!\n");
close(pipe_fd[1]);
sleep(3);
waitpid(pid,NULL,0); /*等待子进程结束*/
exit(0);
}
return 0;
}
二、有名管道通信
有名管道的优点在于它可以支持任何进程间的通信,即通过open函数来打开管道控制读写。只需一方进程使用open函数执行只读操作,一方进程通过open函数执行只写操作,实现进程间的通信。
/* fifo_read.c 读端代码 */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main()
{
int ret;
ret = mkfifo("./FIFO", 0666);
if(ret != 0)
{
perror("mkfifo");
}
int fd_r;
printf("open之前\n");
/* 1. 以只写方式打开有名管道 */
//fd_r = open("./FIFO",O_RDONLY);
/* 2. 以只写方式打开有名管道,非阻塞 |O_NONBLOCK*/
fd_r = open("./FIFO",O_RDONLY);
/* 3. 以可读可写方式打开有名管道 */
printf("open之后\n");
if(fd_r < 0)
{
perror("open");
_exit(-1);
}
char str[64];
int i = 0;
while (i<10)
{
i++;
memset(str,0,sizeof(str));
read(fd_r,str,sizeof(str));
printf("读:%s\n",str);
sleep(1);
}
close(fd_r);
return 0;
}
/* fifo_write.c 写端代码 */
/* fifo_write.c 写端代码 */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
int ret;
ret = mkfifo("./FIFO", 0666);
if(ret != 0)
{
perror("mkfifo");
}
int fd_w;
printf("open之前\n");
/* 1. 以只写方式打开有名管道 */
//fd_w = open("./FIFO",O_WRONLY);
/* 2. 以只写方式打开有名管道,非阻塞 */
fd_w = open("./FIFO",O_WRONLY);
/* 3. 以可读可写方式打开有名管道 */
//fd_w = open("./FIFO",O_RDWR);
printf("open之后\n");
if(fd_w < 0)
{
perror("open");
_exit(-1);
}
char str[64];
int i = 0;
while (i<5)
{
i++;
memset(str,0,sizeof(str));
sprintf(str,"%d: hello world!",i);
printf("写:%s\n",str);
write(fd_w,str,strlen(str)+1);
sleep(2);
}
close(fd_w);
return 0;
}
执行步骤:
- 打开虚拟机的一个终端,编译两个文件,执行写操作。
- 这时此端口会阻塞,因为没有进程执行读操作来接受内容。
- 不要关掉终端,重新打开一个终端,执行读操作。即可实现管道通信。