16.1.1 pipe系统调用

16.1.1  pipe系统调用

系统调用pipe用来建立管道。与之相关的函数只有一个,即pipe()函数,该函数被定义在头文件unistd.h中,它的一般形式是:

 

int pipe(int filedes[2]);

 

pipe系统调用需要打开两个文件,文件标识符通过参数传递给pipe()函数。文件描述符filedes[0]用来读数据,filedes[1]用来写数据。调用成功时,返回值为0,错误时返回–1。管道的工作方式可以总结为以下3个步骤。

1.将数据写入管道

将数据写入管道使用的是write()函数,与写入普通文件的操作方法一样。与文件不同的是,管道的长度受到限制,管道满时写入操作会被阻塞。执行写操作的进程进入睡眠状态,直到管道中的数据被读取。fcntl()函数可将管道设置为非阻塞模式,管道满时,write()函数的返回值为0。如果写入数据长度小于管道长度,则要求一次写入完成。如果写入数据长度大于管道长度,在写完管道长度的数据时,write()函数将被阻塞。

2.从管道读取数据

读取数据使用read()函数实现,读取的顺序与写入顺序相同。当数据被读取后,这些数据将自动被管道清除。因此,使用管道通信的方式只能是一对一,不能由一个进程同时向多个进程传递同一数据。如果读取的管道为空,并且管道写入端口是打开的,read()函数将被阻塞。读取操作的进程进入睡眠状态,直到有数据写入管道为止。fcntl()函数也可将管道读取模式设置为非阻塞。

3.关闭管道

管道虽然有2个端口,但只有一个端口能被打开,这样避免了同时对管道进行读和写的操作。关闭端口使用的是close()函数,关闭读端口时,在管道上进行写操作的进程将收到SIGPIPE信号。关闭写端口时,进行读操作的read()函数将返回0。如下例所示:

 

#include <unistd.h>                       // 标准函数库

#include <sys/types.h>                    // 该头文件提供系统调用的标志

#include <sys/wait.h>                 // wait系统调用相关函数库

#include <stdio.h>                        // 基本输入输出函数库

#include <string.h>                       // 字符串处理函数库

int main()

{

   int fd[2], cld_pid, status;         // 创建文件标识符数组

   char buf[200], len;                    // 创建缓冲区

   if (pipe(fd) == -1) {                // 创建管道

      perror("创建管道出错");

      exit(1);

   }

   if ((cld_pid=fork()) == 0) {         // 创建子进程,判断进程自身是否是子进程

      close(fd[1]);                        // 关闭写端口

      len = read(fd[0], buf, sizeof(buf));        // 从读端口中读取管道内数据

      buf[len]=0;                              // 为缓冲区内的数据加入字符串

                                                // 结束符

      printf("子进程从管道中读取的数据是:%s ",buf);    // 输出管道中的数据

      exit(0);                                    // 结束子进程

   }

   else {

      close(fd[0]);                                // 关闭读端口

      sprintf(buf, "父进程为子进程(PID=%d)创建该数据", cld_pid);

                                                // 在缓冲区创建字符串信息

      write(fd[1], buf, strlen(buf));            // 通过写端口向管道写入数据

      exit(0);                                    // 结束父进程

   }

   return 0;

}

 

程序中,首先创建了一个管道,并且将管道的文件标识符传递给fp[]数组。该数组有2个元素,fd[0]是读取管道的端口,fd[1]是写入管道的端口。然后,通过fork()系统调用创建了一个子进程。父进程的操作是向管道写入数据,子进程的操作是读取管道内的数据,最后子进程将所读取的数据显示到终端上。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值