UNIX 进程间的通信--IPC

来源:互联网 发布:大数据金融分析的意义 编辑:程序博客网 时间:2024/04/28 13:23

对于进程间的通信,我在除了fork和exec系列函数和文件系统,在这里将要介绍进程间通信的其它一些方法,在这里将讨论的是管道、FIFO、消息队列、以及信号量和共享存储器

管道PIPE

管道是所有UNIX都提供此种通信机制,是一种很古老的技术,但是仍然有很大用处,在历史上管道都是半双工的,虽然现在有些系统已经实现了全双工,但是为了移植性,我们一般认为是半双工的;pipe技术只能实现的是有共同祖先的进程之间的传递,因为pipe是匿名的,在后面我们讲到的FIFO就可实现多个不相关的进程之间的通信。

#include <unistd.h>int pipe( int fd[2]);
在参数中fd[0]表示的是以读打开,而fd[1]表示的是以写打开。fd[1]的输出是fd[0]的输入。
对于PIPE的用法一般是父进程调用pipe()函数,fork(),在依据通信的方向,关闭相应的描述符。过程如下图:

    
关闭相应的描述符后,实现父子进程通信,由父进程写,  子进程读取父进程写入的数据

在这个过程中我们需要注意:
当一端关闭后下面两条规则其作用:
1. 当读一个写端已经关闭的管道时,所有数据被读取完成后,read返回0,表示达到了文件结束处。
2. 当写一个读端已经关闭的管道,则产生SIGPIPE。如果忽略该信号并从处理程序返回,则write函数返回-1.
当多进程在写管道的时候,由系统规定了管道的缓冲区为PIPE_BUF,那么我们在一次写入大于PIPE_BUF的字节 数目,那么就有可能产生进程之间的数据的交错,造成数据的错误,那么我们一般都保证在每次写入的数据小于PIPE_BUF。

在很多情况下,我们都是使用下面这种情景:父进程调用pipe函数,fork()出两个进程,父子进程关闭相应的描述符,由子进程执行一个shell命令后,将执行结构写入到pipe中,父进程读取该结果。在这里系统为我们提供了两个库函数来实现上面的功能。
#include <stdio.h>FILE* popen(char* cmdstring, char * type);int pclose( FILE * fp);
popen作用执行pipe函数,创建一个子进程,执行cmdstring的shell脚本,由于PIPE是单向的所以需要由type指定,是读还是写,但是不能指定为读写。
对于cmdstring是通过类似shell -sh -c cmdstring。
返回值:一个普通的文件流,但是关闭必须是pclose,而不是fclose。
pclose函数,等待shell执行完毕,关闭popen产生的流,并且返回shell执行终止状态。

注意:popen函数不能被设置了set-user-id、set-group-id的程序调用,有可能造成不安全的情况发生。

为了实现两个相关进程的双向通信,我们应该将使用两个PIPE来间接实现。

FIFO

FIFO在一些时候被称为命名管道,和PIPE管道只能是相关进程使用相比,FIFO则可以在不相关进程之间也能进行交换数据。
我们知道FIFO仍然是一个文件,它是真实存在于计算机文件系统上面的。所以呢,就是说一般的文件I/O函数都是可以用于FIFO的。
对于FIFO函数的创建只能用下面这个函数,当创建成功后则可以使用open函数打开它:

#include <sys/stat.h>int mkfifo( const char* pathname, mode_t mode);


对于FIFO有两种用途:

  1. FIFO由shell命令使用以便将数据从一条管道线传送到另一条,为此无需创建中间临时文件。
  2. FIFO用于客户-服务器进程。

原创粉丝点击