Linux进程间通信——使用匿名管道
#include <stdio.h>
FILE* popen (const char *command, const char *open_mode);
int pclose(FILE *stream_to_close);
如果type是“w”,则是文件指针是可写的,向这个流 的 写入被转化为 对 command 命令的标准输入;而 command 命令的 标准输出 则是和 调用 popen(), 函数 的 进程 相同,除非 这个被command命令 自己改变. 相反的, 如果type是“r”,则返回的文件指针是可读的,读取 一个 “被popen了的” 流, 就相当于 读取 command 命令的标准输出, 而 command 的标准输入 则是和 调用 popen, 函数的进程 相同.
注意, popen 函数的 输出流默认是被全缓冲的.
pclose 函数 等待 相关的进程结束并返回 一个 command 命令的 退出状态, 就像 wait4 函数 一样
函数popen先执行fork,然后调用exec以执行cmdstring,并且返回一个标准I/O文件指针。如果type是“r”,则文件指针连接到cmdstring的标准输出(见图15-5)。
fp相当于管道的fd[0], stdout相当于管道的fd[1].
图15-5 执行fp = popen(cmdstring, “r”)函数的结果
如果type是“w”,则文件指针连接到cmdstring的标准输入(见图15-6)。
fp相当于管道的fd[1], stdin相当于管道的fd[0].
图15-6 执行fp = popen(cmdstring, “w”)函数的结果
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
FILE *read_fp = NULL;
FILE *write_fp = NULL;
char buffer[BUFSIZ + 1];
int chars_read = 0;
//初始化缓冲区
memset(buffer, ‘\0‘, sizeof(buffer));
//打开ls和grep进程
read_fp = popen("ls -l", "r");
write_fp = popen("grep rwxrwxr-x", "w");
//两个进程都打开成功
if(read_fp && write_fp)
{
//读取一个数据块
chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
while(chars_read > 0)
{
buffer[chars_read] = ‘\0‘;
//把数据写入grep进程
fwrite(buffer, sizeof(char), chars_read, write_fp);
//还有数据可读,循环读取数据,直到读完所有数据
chars_read = fread(buffer, sizeof(char), BUFSIZ, read_fp);
}
//关闭文件流
pclose(read_fp);
pclose(write_fp);
exit(EXIT_SUCCESS);
}
exit(EXIT_FAILURE);
}
#include <unistd.h>
int pipe(int file_descriptor[2]);
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
int data_processed = 0;
int filedes[2];
const char data[] = "Hello pipe!";
char buffer[BUFSIZ + 1];
pid_t pid;
//清空缓冲区
memset(buffer, ‘\0‘, sizeof(buffer));
if(pipe(filedes) == 0)
{
//创建管道成功
//通过调用fork创建子进程
pid = fork();
if(pid == -1)
{
fprintf(stderr, "Fork failure");
exit(EXIT_FAILURE);
}
if(pid == 0)
{
//子进程中
//读取数据
data_processed = read(filedes[0], buffer, BUFSIZ);
printf("Read %d bytes: %s\n", data_processed, buffer);
exit(EXIT_SUCCESS);
}
else
{
//父进程中
//写数据
data_processed = write(filedes[1], data, strlen(data));
printf("Wrote %d bytes: %s\n", data_processed, data);
//休眠2秒,主要是为了等子进程先结束,这样做也只是纯粹为了输出好看而已
//父进程其实没有必要等等子进程结束
sleep(2);
exit(EXIT_SUCCESS);
}
}
exit(EXIT_FAILURE);
}
#include <unistd.h>
int dup(int file_descriptor);
int dup2(int file_descriptor_one, int file_descriptor_two);
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
int data_processed = 0;
int pipes[2];
const char data[] = "123";
pid_t pid;
if(pipe(pipes) == 0)
{
pid = fork();
if(pid == -1)
{
fprintf(stderr, "Fork failure!\n");
exit(EXIT_FAILURE);
}
if(pid == 0)
{
//子进程中
//使标准输入指向fildes[0],以后对标准输入的操作都是对管道的pips[0]的操作
close(0);
dup(pipes[0]);
//关闭pipes[0]和pipes[1],只剩下标准输入
close(pipes[0]);
close(pipes[1]);
//启动新进程od
execlp("od", "od", "-c", 0);
exit(EXIT_FAILURE);
}
else
{
//关闭pipes[0],因为父进程不用读取数据
close(pipes[0]);
data_processed = write(pipes[1], data, strlen(data));
//写完数据后,关闭pipes[1]
close(pipes[1]);
printf("%d - Wrote %d bytes\n", getpid(), data_processed);
}
}
exit(EXIT_SUCCESS);
}