副标题[/!--empirenews.page--]

进程间通信基本概念
进程间通信意味着两个不同进程间可以交换数据,为了完成这一点,操作系统中应提供两个进程可以同时访问的内存空间。但我们知道,进程具有完全独立的内存结构,就连通过fork函数创建的子进程也不会和父进程共享内存,因此,进程间通信只能通过其他特殊方法完成。
基于管道实现进程间通信
图1-1表示基于管道(PIPE)的进程间通信结构模型
图1-1 基于管道的进程间通信模型
从图1-1可以看到,为了完成进程间通信,需要创建管道。管道并非属于进程资源,而是和套接字一样,属于操作系统资源(也就不是fork函数的复制对象)。下面介绍创建管道函数
- #include
- int pipe (int filedes[2]);//成功时返回0,失败时返回-1
- filedes[0]:通过管道接收数据时使用的文件描述符,即管道出口
- filedes[1]:通过管道传输数据时使用的文件描述符,即管道入口
以长度为2的int数组地址值作为参数调用上述函数时,数组中存有两个文件描述符,它们将被用作管道的出口和入口。父进程调用该函数时将创建管道,同时获取对应于出入口的文件描述符,此时父进程可以读写同一管道。但父进程的目的是与子进程进行数据交换,因此需要将入口和出口中的一个文件描述符传递给子进程,如何完成传递呢?答案还是调用fork函数。
- pipe1.c
- #include <stdio.h>
- #include <unistd.h>
- #define BUF_SIZE 30
- int main(int argc, char *argv[])
- {
- int fds[2];
- char str[] = "Who are you?";
- char buf[BUF_SIZE];
- pid_t pid;
- pipe(fds);
- pid = fork();
- if (pid == 0)
- {
- write(fds[1], str, sizeof(str));
- }
- else
- {
- read(fds[0], buf, BUF_SIZE);
- puts(buf);
- }
- return 0;
- }
- 第12行:调用pipe函数创建管道,fds数组中保存用于I/O的文件描述符
- 第13行:接着调用fork函数,子进程将同时拥有通过12行函数调用获取的两个文件描述符。注意!复制的并非管道,而是用于管道I/O的文件描述符。至此,父子进程同时拥有I/O文件描述符
- 第16、20行:子进程通过第16行代码向管道传递字符串,父进程通过第20行代码从管道接收字符串
编译pipe1.c并运行
- # gcc pipe1.c -o pipe1
- # ./pipe1
- Who are you?
上述示例中的通信方法及路径如图1-2所示,重点在于,父子进程都可以访问管道的I/O路径,但子进程仅用输入路径,父进程仅用输出路径
图1-2 示例pipe1.c的通信路径
以上就是管道的基本原理及通信方法,应用管道时还有一部分内容需要注意,通过双向通信示例进一步说明
通过管道进行进程间双向通信
下面创建两个进程通过一个管道进行双向数据交换的示例,其通信方式如图1-3所示
图1-3 双向通信模型1
从图1-3可以看出,通过一个管道可以进行双向通信,但采用这种模型需格外小心,先给出示例,稍后再讨论。
pipe2.c
- #include <stdio.h>
- #include <unistd.h>
- #define BUF_SIZE 30
- int main(int argc, char *argv[])
- {
- int fds[2];
- char str1[] = "Who are you?";
- char str2[] = "Thank you for your message";
- char buf[BUF_SIZE];
- pid_t pid;
- pipe(fds);
- pid = fork();
- if (pid == 0)
- {
- write(fds[1], str1, sizeof(str1));
- sleep(2);
- read(fds[0], buf, BUF_SIZE);
- printf("Child proc output: %s n", buf);
- }
- else
- {
- read(fds[0], buf, BUF_SIZE);
- printf("Parent proc output: %s n", buf);
- write(fds[1], str2, sizeof(str2));
- sleep(3);
- }
- return 0;
- }
- 第17~20行:子进程运行区域,通过第17行行传输数据,通过第19行接收数据。第18行的sleep函数至关重要,这一点稍后再讨论
- 第24~26行:父进程的运行区域,通过第24行接收数据,这是为了接收第17行子进程传输的数据。另外通过第26行传输数据,这些数据将被第19行的子进程接收
- 第27行:父进程先终止时会弹出命令提示符,这时子进程仍然在工作,故不会产生问题。这条语句主要是为了防止子进程终止前弹出命令提示符(故可删除)
(编辑:晋中站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|