图2:示例代码1中半双工管道的示意图
这个例子中,通信是在具有共同祖先的进程间发生的,即父进程和子进程通信。这样做局限性太大,但我们只是用它来给读者一个感性的认识。接下来,我们将介绍更为高级的进程间的管道通信。
2.进程间通信管道编程
在利用管道技术进行编程时,处理要用到上面介绍的pipe函数外,还用到另外三个函数,如下所示。
pipe函数:该函数用于创建一个新的匿名管道。
dup函数:该函数用于拷贝文件描述符。
mkfifo函数:该函数用于创建一个命名管道(fifo)。
当然,在管道通信过程中还用到其它函数,到时我们会加以介绍。需要注意的是,说到底,管道无非就是一对文件描述符,因此任何能够操作文件操作符的函数都可以使用管道。这包括但不限于这些函数:select、read、write、 fcntl、freopen,等等。
2.1函数pipe
函数pipe用来建立一个新的管道,该管道用两个文件描述符进行描述。函数pipe的原型如下所示:
当调用成功时,函数pipe返回值为0,否则返回值为-1。成功返回时,数组fds被填入两个有效的文件描述符。数组的第一个元素中的文件描述符供应用程序读取之用,数组的第二个元素中的文件描述符可以用来供应用程序写入。
下 面我们考察在一个包含多个进程的应用程序中的管道示例。在该程序中(见示例代码2),第14行用于创建一个管道,然后进程在第16行分叉,变成一个父进程 和一个子进程。在子进程中,我们尝试从(在第18行建立的)管道的输入描述符读取,这时该进程将被挂起,直到管道中有可以读取的内容为止。
读完后,我们用NULL作为读取的内容的结束符,这样的话,读的这些内容就能使用printf函数正确打印输出了。父进程先是利用存放在thePipe[1]中的“写文件标识符”向管道写入测试字符串,然后就使用wait函数来等待子进程退出。
在 我们的这个程序中需要加以注意的是,我们的子进程是如何继承父进程利用pipe函数建立的文件描述符的,以及如何利用该文件描述符进行通信的。函数 fork一旦执行,子进程会继承父进程的功能和管道的文件描述符,但对于内核来说,父进程和子进程是平等的,它们是独立运行的。也就是说,两个进程分别具 有单独的内存空间,它们正是通过pipe函数来互通有无的。
原文转自:http://yp.oss.org.cn/blog/show_resource.php?resource_id=598