进程间通信(上)

管道

管道分为两种类型:全双工管道与半双工管道。半双工管道即意味着数据只能在一个方向上流动。全双工管道上的数据可以两个方向流动。老旧系统上大多不提供全双工管道,所以为了移植性考虑,应主要使用半双工管道。通常管道只能在具有公共祖先的两个进程间使用。

尽管有局限性,但是半双工管道仍旧是最常用的进程间通信方式。管道通过pipe()函数创建。

      int pipe(int fd[2]);

fd返回两个文件描述符,fd[0]为读而打开,fd[1]为写而打开。我们通过一个例子来说明。

      int fd[2];
      char line[length];
      pipe(fd);
      if(pid = fork()>0) {
          close(fd[0]);
          write(fd[1], "hello world!\n", 12);
      }//parent
      else {
          close(fd[1]);
          n = read(fd[0], line, length);
          printf("%s", line);
      }//child

首先我们创建一个半双工管道,然后通过fork()函数生成子进程。子进程会继承父进程的所有文件描述符,显然fd[0]、fd[1]都继续保存着。然后父进程关闭读通道,子进程关闭写通道,父进程向半双工管道写入一串字符串,然后子进程读入后写入标准输出。

其实实现全双工管道也不是一件复杂的事。我们只需要建立两个半双工管道即可。

      int fd1[2],fd2[2];
      char line1[length],line2[length];
      pipe(fd1);
      pipe(fd2);
      if(pid = fork()>0) {
          close(fd1[0]);
          close(fd2[1]);
          write(fd1[1], "hello world!\n", 12);
          read(fd2[0],line1,length);
          printf("%s", line1);
      }//parent
      else {
          close(fd1[1]);
          close(fd2[0]);
          n = read(fd1[0], line, length);
          write(fd2[1], "hello world!\n", 12);
          printf("%s", line2);
      }//child

FIFO

FIFO有时被称为命名管道。未命名的管道只能在两个有共同祖先的进程之间使用。FIFO是一个半双工管道。

FIFO由mkfifo()函数创建。

      int mkfifo(const char *pathname, mode_t mode);

mode参数指定文件权限位,类似于open函数的第二个参数。而pathname是一个普通的Unix路径名,代表FIFO的位置。

需要注意的是mkfifo()函数只能创建一个新的管道,而打开一个新的管道只能用open()函数。

      #define FIFO1 "tmp/fifo.1"
      #define FIFO2 "tmp/fifo.2"
      char line1[length],line2[length];
      mkfifo(FIFO1, FILE_MODE);
      mkfifo(FIFO2, FILE_MODE);
      if(pid = fork()>0) {
          readfd = open(FIFO1, O_RDONLY, 0);
          writefd = open(FIFO2, O_wDONLY, 0);
          write(writefd, "hello world!\n", 12);
          read(readfd, line1, length);
          printf("%s", line1);
      }//parent
      else {
          readfd = open(FIFO2, O_RDONLY, 0);
          writefd = open(FIFO1, O_wDONLY, 0);
          write(writefd, "hello world!\n", 12);
          read(readfd, line2, length);
          printf("%s", line2);
      }//child

可以看到这和半双工管道很像,可以把理解成存储在Unix系统中的管道。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容