Linux系统编程 83 管道读写行为

学习笔记
APUE这本书内容
读管道
1.管道中有数据,read返回实际读到的字节数
2.管道没有数据:
1)判断管道的写端是否被全部关闭,全部关闭,read返回为0
2)管道的写端没有全部被关闭,read阻塞等待。(不久的将来,可能有数据传达,此时会让出cpu)

写管道
1.管道读端全部被关闭,进程异常终止(也可以使用捕捉SIGPIPE信号,使进程不终止)
2.管道读端没有全部被关闭:
1)管道已满,write阻塞
2)管道未满,write将数据写入,并返回实际写入的字节数。

程序: 父进程一上来就跑去睡觉,子进程读不到数据,
根据读写行为可知道子进程处于read阻塞等待。

$cat mypipe.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<errno.h>

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}
int main(int argc, char *argv[])
{
    int ret;
    int fd[2];
    pid_t pid;

    char *str ="hello pipe\n";
    char buf[1024];

    ret = pipe(fd);

    if(-1 == ret)
    {
        sys_err("pipe error!");
    }

    pid = fork();

    if(pid > 0)
    {
        close(fd[0]); //guanbi du duan
        sleep(3);
        write(fd[1],str,strlen(str));
        close(fd[1]);
    }
    else if(0 == pid)
    {
        close(fd[1]);//guanbi xie duan 
        ret = read(fd[0],buf,sizeof(buf));
        write(STDOUT_FILENO,buf,ret);
        close(fd[0]);
    }
    return 0;
}

$make mypipe
gcc  mypipe.c -o mypipe -Wall -g
$./mypipe
$hello pipe


提示: $./mypipe 三秒之后才显示 $hello pipe

如果管道写端全部被关闭,根据管道读写行为,
这个时候read 返回值为0.
修改程序如下:

$cat mypipe.c
#include&lt;stdio.h&gt;
#include&lt;stdlib.h&gt;
#include&lt;string.h&gt;
#include&lt;unistd.h&gt;
#include&lt;errno.h&gt;

void sys_err(const char *str)
{
    perror(str);
    exit(1);
}
int main(int argc, char *argv[])
{
    int ret;
    int fd[2];
    pid_t pid;

    char *str =&quot;hello pipe\n&quot;;
    char buf[1024];

    ret = pipe(fd);

    if(-1 == ret)
    {
        sys_err(&quot;pipe error!&quot;);
    }

    pid = fork();

    if(pid &gt; 0)
    {
        close(fd[0]); //guanbi du duan
        sleep(3);
//        write(fd[1],str,strlen(str));//不去写,直接关闭写端
        close(fd[1]);
    }
    else if(0 == pid)
    {
        close(fd[1]);//guanbi xie duan 
        ret = read(fd[0],buf,sizeof(buf));
        printf(&quot;child read ret = %d\n&quot;,ret);
        write(STDOUT_FILENO,buf,ret);
        close(fd[0]);
    }
    return 0;
}
$make mypipe
gcc  mypipe.c -o mypipe -Wall -g
mypipe.c: In function ‘main’:
mypipe.c:18:11: warning: unused variable ‘str’ [-Wunused-variable]
   18 |     char *str ="hello pipe\n";
      |           ^~~
$./mypipe 
$child read ret = 0


可以看到read为0,相当于文件末尾一样。


管道已满的没有办法测试,向4096的缓冲区,不断写入数据,还要保证读那一端要比较慢。
实际上,管道是有缓冲区构造的,当内核发现缓冲区满了(4096),它会自动给它扩容。
内核2.7还是2.6版本之后,有这个功能。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值