文章目录
(一)管道
管道可以在两个进程间传递数据,比如ls -l | grep main.c,其中的"|"就是管道。上述命令的意思就是查看当前所在目录的结果写入管道,然后grep再从管道中过滤得到main.c的文件显示在屏幕上;
(二)管道的分类
(1)有名管道
- 创建方式
- 命令创建
mkfifo FIFO
- 系统调用创建
int mkfifo(const char* filename, mode_t mode);
头文件(sys/types.h sys/stat.h)
- 进程a从键盘获取数据,通过管道发送给进程b进行输出
a.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
void Send()
{
int fd = open("FIFO", O_WRONLY);
if(fd == -1) return;
printf("input data:");
while(1)
{
char buff[128] = {0};
fgets(buff, 127, stdin);
if(strncmp(buff, "end", 3) == 0)
{
break;
}
write(fd, buff, strlen(buff) - 1);
}
close(fd);
}
int main()
{
Send();
return 0;
}
b.c
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
void Recv()
{
int fd = open("FIFO", O_RDONLY);
if(fd == -1) return;
printf("reading data...\n");
while(1)
{
char buff[128] = {0};
int ret = read(fd, buff, 127);
if(ret <= 0)
break;
if(strncmp(buff, "end", 3) == 0)
{
break;
}
printf("%s\n", buff);
}
close(fd);
}
int main()
{
Recv();
return 0;
}
- 结果:
(2)无名管道
-
无名管道主要用于父子进程间通信
-
创建方式:
- 头文件 unistd.h
- 系统调用
int pipe(int pipefd[2]);
- pipe()返回值:成功0,失败-1
- fd[0]管道读端
- fd[1]管道写端
- 代码
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/wait.h>
void fun(int sig)
{
int status;
while(waitpid(-1, &status, WNOHANG) > 0);
}
void DataTransmission()
{
int fd[2];
int ret = pipe(fd);
if(ret == -1)
{
printf("pipe err\n");
return;
}
//注册SIGCHLD信号应答
signal(SIGCHLD, fun);
pid_t pid = fork();
if(pid == -1)
{
printf("fork err\n");
return;
}
if(pid == 0)
{
//子进程当作写端
close(fd[0]);
while(1)
{
printf("child input data:\n");
char buff[128] = {0};
fgets(buff, 127, stdin);
if(strncmp(buff, "end", 3) == 0)
{
break;
}
write(fd[1], buff, strlen(buff) - 1);
}
//关闭写端
close(fd[1]);
//退出子进程,自动向父进程发送SIGCHLD信号
exit(0);
}
//父进程
else
{
//关闭写端
close(fd[1]);
while(1)
{
char buff[128] = {0};
int ret = read(fd[0], buff, 127);
if(ret <= 0)
return;
if(strncmp(buff, "end", 3) == 0)
break;
printf("father read data:%s\n", buff);
}
close(fd[0]);
}
}
int main()
{
DataTransmission();
return 0;
}
- 结果:
(3)管道的特点
- 有名管道、无名管道写入管道的数据都存放在内存中
- 管道是一种半双工通信方式(通信方式有单工、半双工、全双工)
- 有名管道与无名管道区别:有名管道可以在任意进程间使用,而无名管道在父子进程间通信。