进程间通信之:管道
/* 关闭子进程读描述符 */
close(pipe_fd[0]);
exit(0);
}
else if (pid > 0)
{
/* 父进程关闭读描述符,并通过使父进程暂停1s等待子进程已关闭相应的写描述符 */
close(pipe_fd[0]);
sleep(DELAY_TIME);
if((real_write = write(pipe_fd[1], data, strlen(data))) != -1)
{
printf("Parent wrote %d bytes : '%s'\n", real_write, data);
}
/*关闭父进程写描述符*/
close(pipe_fd[1]);
/*收集子进程退出信息*/
waitpid(pid, NULL, 0);
exit(0);
}
}
将该程序交叉编译,下载到开发板上的运行结果如下所示:
$ ./pipe
Parent wrote 17 bytes : 'Pipe Test Program'
17 bytes read from the pipe is 'Pipe Test Program'
5.管道读写注意点
n 只有在管道的读端存在时,向管道写入数据才有意义。否则,向管道写入数据的进程将收到内核传来的SIGPIPE信号(通常为Broken pipe错误)。
n 向管道写入数据时,Linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读取管道缓冲区中的数据,那么写操作将会一直阻塞。
n 父子进程在运行时,它们的先后次序并不能保证,因此,在这里为了保证父子进程已经关闭了相应的文件描述符,可在两个进程中调用sleep()函数,当然这种调用不是很好的解决方法,在后面学到进程之间的同步与互斥机制之后,请读者自行修改本小节的实例程序。
8.2.4 标准流管道
1.标准流管道函数说明
与Linux的文件操作中有基于文件流的标准I/O操作一样,管道的操作也支持基于文件流的模式。这种基于文件流的管道主要是用来创建一个连接到另一个进程的管道,这里的"另一个进程"也就是一个可以进行一定操作的可执行文件,例如,用户执行"ls -l"或者自己编写的程序"./pipe"等。由于这一类操作很常用,因此标准流管道就将一系列的创建过程合并到一个函数popen()中完成。它所完成的工作有以下几步。
n 创建一个管道。
n fork()一个子进程。
n 在父子进程中关闭不需要的文件描述符。
n 执行exec函数族调用。
n 执行函数中所指定的命令。
这个函数的使用可以大大减少代码的编写量,但同时也有一些不利之处,例如,它不如前面管道创建的函数那样灵活多样,并且用popen()创建的管道必须使用标准I/O函数进行操作,但不能使用前面的read()、write()一类不带缓冲的I/O函数。
与之相对应,关闭用popen()创建的流管道必须使用函数pclose()来关闭该管道流。该函数关闭标准I/O流,并等待命令执行结束。
2.函数格式
popen()和pclose()函数格式如表8.2和表8.3所示。
表8.2 popen()函数语法要点
所需头文件 | #include <stdio.h> | |
函数原型 | FILE *popen(const char *command, const char *type) | |
函数传入值 | command:指向的是一个以null结束符结尾的字符串,这个字符串包含一个shell命令,并被送到/bin/sh以-c参数执行,即由shell来执行 | |
type: | "r":文件指针连接到command的标准输出,即该命令的结果产生输出 | |
函数返回值 | 成功:文件流指针 | |
出错:-1 |
表8.3 pclose()函数语法要点
所需头文件 | #include <stdio.h> |
函数原型 | int pclose(FILE *stream) |
函数传入值 | stream:要关闭的文件流 |
函数返回值 | 成功:返回由popen()所执行的进程的退出码 |
出错:-1 |
3.函数使用实例
在该实例中,使用popen()来执行"ps -ef"命令。可以看出,popen()函数的使用能够使程序变得短小精悍。
/* standard_pipe.c */
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#define BUFSIZE 1024
int main()
{
FILE *fp;
char *cmd = "ps -ef";
char buf[BUFSIZE];
/*调用popen()函数执行相应的命令*/
if ((fp = popen(cmd, "r")) == NULL)
{
- Windows CE 进程、线程和内存管理(11-09)
- 如何监控和保护Linux下进程安全 (07-12)
- uClinux进程调度器的实现分析(04-13)
- linux操作系统下的进程通信设计(01-24)
- Windows操作系统多核CPU内核线程管理方法(01-21)
- 一种基于嵌入式实时操作系统的微机保护装置网络通信方案(05-07)