本文共 3551 字,大约阅读时间需要 11 分钟。
一、Linux进程间通信概述
Linux 下的进程通信手段基本上是从UNIX 平台上的进程通信手段继承而来的。经过不断的发展形成了如下图所示的进程间通信类型:
二、无名管道
1、无名管道的特点。
管道是基于文件描述符的通信方式,当一个管道建立时,它会创建两个文件描述符fds[0]和fds[1],其中fds[0]固定用于读管道,而fd[1]固定用于写管道。管道关闭时只需将这两个文件描述符关闭即可,可使用普通的close()函数逐个关闭各个文件描述符。
3、管道创建函数
int pipe(int fd[2])fd[2] : 管道的两个文件描述符,之后就可以直接操作这两个文件描述符
返回值:0成功,其他返回错误代码
4、管道创建实例
编写一个无名管道的测试例程:创建两个进程,实现父子进程之间的通信。具体的测试代码如下:
#include编译并运行,结果如下: 由结果可知,实现了父子进程的通信。#include #include #include #define BUFFER_SIZE 256 // 定义缓冲区的大小/* * 使用pipe实现父子进程之间的通信 */int main(void){ pid_t pid; int pipefd[2]; int ret; char buf[BUFFER_SIZE]; int buflen; /* 创建一个管道 * pipefd[0] : read * pipefd[1] : write */ ret = pipe(pipefd); if(-1 == ret) { printf("pipe error!\n"); return -1; } /* fork出一个子进程 */ pid = fork(); if(-1 == pid) // 错误 { printf("fork error!\n"); return -1; } else if(0 == pid) // 子进程 { /* 1、子进程向父进程发送一条消息 */ sprintf(buf, "%s", "to main process!"); write(pipefd[1], buf, BUFFER_SIZE); printf("(1) child to parent : %s\n", buf); /* 4、子进程获得父进程发送的消息 */ buflen = read(pipefd[0], buf, BUFFER_SIZE); buf[buflen] = '\0'; printf("(4) child from parent : %s\n", buf); } else if(pid > 0) // 父进程 { /* 2、父进程获得子进程发送的消息 */ buflen = read(pipefd[0], buf, BUFFER_SIZE); buf[buflen] = '\0'; printf("(2) parent from child : %s\n", buf); /* 3、父进程向子进程发送一条消息 */ sprintf(buf, "%s", "to child process!"); write(pipefd[1], buf, BUFFER_SIZE); printf("(3) parent to child : %s\n", buf); /* 等待子进程执行完毕 */ waitpid(pid, NULL, 0); } return 0;}
三、标准流管道
1、标准流管道创建过程
与Linux 的文件操作中有基于文件流的标准I/O 操作一样,管道的操作也支持基于文件流的模式。创建一个标准流管道需要以下几步:
2、标准流管道创建函数
FILE *popen(const char *command, const char *type)command : 指向的是一个以null 结束符结尾的字符串,这个字符串包含一个shell 命令,并被送到/bin/sh 以-c 参数执行,即由shell 来执行
type:“r”:文件指针连接到command 的标准输出,即该命令的结果产生输出;“w”:文件指针连接到command 的标准输入,即该命令的结果产生输入
返回值:成功返回文件流指针,出错返回-1
int pclose(FILE *stream)stream : 要关闭的文件流
返回值:成功返回进程的退出码,出错返回-1
3、测试例程编写一个测试程序:使用标准流管道把一个命令的产生结果打印出来。
#include编译并运行结果如下:#define BUFFER_SIZE 256 // 定义缓冲区的大小/* 实现一个标准流管道的测试小例子 * usage : stream_pipe */int main(int argc, char *argv[]){ FILE *fp; char buf[BUFFER_SIZE]; if(2 != argc) { printf("usage : %s \n", argv[0]); return -1; } /* 打开一个标准流管道从相应的进程当中 */ fp = popen(argv[1], "r"); if(NULL == fp) { printf("popen error!\n"); return -1; } /* 把内容打印出来 */ while(fgets(buf, BUFFER_SIZE, fp) != NULL) // 判断是否读完 { printf("%s", buf); } /* 关闭一个标准流管道 */ pclose(fp); return -1;}