| 
                        副标题[/!--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行:父进程先终止时会弹出命令提示符,这时子进程仍然在工作,故不会产生问题。这条语句主要是为了防止子进程终止前弹出命令提示符(故可删除)
 
 
                                                (编辑:52站长网) 
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! 
                     |