如果通过文件实现进程间通信一来影响程序运行速度,二来要关注的细节过多,开发调试不方便,而且严重依赖文件系统中的文件,容易造成软件运行的不稳定性。
管道是在基本的文件形式的进程间通信的基础上的一个机制,就像在进程之间架设了一个“管道”,一个管道在两个进程间架设的通信是单向的,总是从一个进程将数据输送到另一个进程。
特点1:管道使用文件描述符来进行操作;
特点2:一个管道对应两个文件描述符,这两个文件描述符分别表示管道的“入口”和“出口”。
特点3:数据传输的特点是FIF0(First In First Out)
特点4:如果管道数据为空,则读数据方会阻塞(默认设置);如果管道为满时,则写入数据方则阻塞(默认设置)。
特点5:管道实现的进程间的通信一定是父子进程之间(爷孙进程之间)。
int pipe(int filedes[2]); 建立管道函数
pipe()会建立管道,并将文件描述符由参数fiedes数组返回,filedes[0]为管道里的读取段,filedes[1]则为管道的写入端
返回值:成功则返回0,否则返回-1
FILE *popen(const char *command,const char *type);
函数声明:popen()会调用fork()产生子进程,然后从子进程中调用/bin/sh -c来执行参数command的指令。type可以使用"r"表示读取,"w"表示写入。按照这个type值,popen()会建立管道连接到子进程的标准输入或标准输出,然后返回一个指针文件。
返回值:成功则返回文件指针,否则返回NULL。
int pclose(FILE *stream)
函数说明:pclose()用来关闭由popen()所建立的管道及文件指针。参数Stream为先前由popen所返回的文件指针
返回值:返回子进程的结束状态。如果有错误则返回-1.
参考代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
int testPipe(void)
{
pid_t pid;
char buff[128];
int i = 0,ret;
int fds[2],fps[2];
ret = pipe(fds);
if(ret < 0)
{
printf("fds初始换管道失败\n");
exit(-1);
}
ret = pipe(fps);
if(ret < 0)
{
printf("初始换fps管道失败\n");
exit(-1);
}
pid = fork();
if(0 == pid)
{
close(fds[1]);
close(fps[0]);
while(1)
{
ret = read(fds[0],buff,sizeof(buff));
if(ret < 0)
{
printf("读出数据失败\n");
exit(-1);
}
fflush(stdout);
printf("%s",buff);
//pause();
sleep(1);
sprintf(buff,"我是父进程的第 %d 次输出\n",i);
fflush(stdout);
ret = write(fps[1],buff,strlen(buff));
if(ret < 0)
{
printf("管道fps写入失败\n");
exit(-2);
}
i++;
sleep(1);
// pause();
}
}else if(pid > 0)
{
close(fds[0]);
close(fps[1]);
while(1)
{
sprintf(buff,"这是子进程第 %d 次输出\n",i);
fflush(stdout);
ret = write(fds[1],buff,strlen(buff));
if(ret < 0)
{
printf("写入数据失败\n");
exit(-1);
}
sleep(1);
i++;
// pause();
ret = read(fps[0],buff,sizeof(buff));
if(buff < 0)
{
printf("fps管道读出失败\n");
exit(-2);
}
fflush(stdout);
printf("%s",buff);
sleep(1);
}
}else
{
printf("fork()失败\n");
return 0;
}
}
int testPopen()
{
char buff[512];
FILE *fp = popen("ls -a","r");
if(fp == NULL)
{
printf("函数popen执行失败\n");
exit(-1);
}
while(fgets(buff,sizeof(buff),fp) > 0)
{
puts(buff);
}
}
int main(void)
{
// testPipe();
testPopen();
return 0;
}