linux管道、EPIPE 和 SIGPIPE 的关系「建议收藏」

linux管道、EPIPE 和 SIGPIPE 的关系「建议收藏」试验目的:验证试验过程:

大家好,又见面了,我是你们的朋友全栈君。

试验目的:

1、向管道写端写入数据前,关闭管道写端fd,errno值会是什么?

2、向管道写端写入数据后,关闭管道写端fd,从管道读端读取数据时,是否能正常读取数据?

3、向管道写端写入数据后,关闭管道读端fd,从管道读端读取数据时,会发生什么?errno是什么?

4、向管道写端写入输入前,关闭管道读端fd,是否会触发SIGPIPE信号?程序如何不崩溃?errno值是否会为EPIPE?


正常代码流程:

1、创建一个管道pipefd[2]

2、向管道写端pipefd[1]写入数据

3、从管道读端pipefd[0]读取数据

4、正常关闭管道写端和读端


试验结果:

1、errno=8, 写端fd报:Bad file descriptor。不会触发SIGPIPE, errno也不会为EPIPE

2、可以正常读取到写入的数据

3、和1情况一样。errno=8, 读端fd报:Bad file descriptor。不会触发SIGPIPE, errno也不会为EPIPE

4、会触发SIGPIPE。

如果程序不处理SIGPIPE或者按照默认方式处理SIGPIPE,则程序会退出。

如果忽略SIGPIPE( 使用signal(SIGPIPE, SIG_IGN); ),则程序不会因为系统触发SIGPIPE而退出,会继续执行完。

在向管道写端写入数据时,errno=8, 为EPIPE, 报:Broken pipe


结论:

1、程序中忽略 SIGPIPE信号。

2、向管道写端写入数据时,可以检测errno是否为EPIPE,如果是,可以关闭管道写端fd。


代码:

/*
 * pipe_op.c
 *
 *  Created on: Jun 24, 2014
 *      Author: lingyun
 */


#include "pipe_op.h"

#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <assert.h>
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <bits/signum.h>
#include <signal.h>

#define BUFFER_SIZE 1024

void
pipe_create(int pipefd[2]) {

    int ret;

    ret = socketpair(PF_UNIX, SOCK_STREAM, 0, pipefd);
    assert(ret != -1);
}

void
pipe_close(int pipefd) {
    if (pipefd > 0) {
        close(pipefd);
    }
}

void
pipe_func_test() {

    //忽略SIGPIP信号
    signal(SIGPIPE, SIG_IGN);

    //按照默认处理方式处理SIGPIP信号
    //signal(SIGPIPE, SIG_DFL);

    int pipefd[2];

    pipe_create(pipefd);

    int pipe_read_fd = pipefd[0];
    int pipe_write_fd = pipefd[1];

    printf("pipe read end: %d\n", pipe_read_fd);
    printf("pipe write end: %d\n", pipe_write_fd);

    //write msg to write_pipe, and read from read_pipe

    char buf[BUFFER_SIZE];
    memset(buf, '\0', BUFFER_SIZE);
    const char* message = "hello, i'm lingyun";
    int message_len = strlen(message);
    strncpy(buf, message, message_len);

    printf("buf message: %s\n", buf);

    //1. 向管道写端写数据前, 关闭管道写端fd
    //pipe_close(pipe_write_fd);

    //4. 向管道写端写数据前, 关闭管道读端fd
    pipe_close(pipe_read_fd);

    ssize_t writed = 0;
    writed = write(pipe_write_fd, buf, message_len);

    int save_errno;

    if (writed == -1) {
        save_errno = errno;

        if (errno == EPIPE) {
            printf("pipe_write_fd is closed, write to this fd has EPIPE error\n");
        }
        perror("write");
        goto failed;
    }

    printf("want write message len: %d\n", message_len);
    printf("writed %d char\n", writed);

    memset(buf, '\0', BUFFER_SIZE);
    ssize_t readed = 0;

    //2. 向管道写端写完数据后, 关闭管道写端fd
    //pipe_close(pipe_write_fd);

    //3. 向管道写端写完数据后, 从管道读端读取数据前, 关闭管道读端fd
    //pipe_close(pipe_read_fd);

    readed = read(pipe_read_fd, buf, writed);

    if (readed == -1) {
        save_errno = errno;

        if (errno == EPIPE) {
            printf("pipe_write_fd is closed, read from pipe_read_fd has EPIPE error\n");
        }
        perror("read");
        goto failed;
    }

    printf("want read message len: %d\n", writed);
    printf("readed %d char\n", readed);

    printf("after read, buf message: %s\n", buf);

failed:
    if(pipe_read_fd != -1) {
        pipe_close(pipe_read_fd);
    }

    if(pipe_write_fd != -1) {
        pipe_close(pipe_write_fd);
    }
}

int main() {
    pipe_func_test();
    return 0;
}



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/139357.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • golang 2021. 激活码(JetBrains全家桶)

    (golang 2021. 激活码)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~1…

    2022年3月27日
    260
  • PostgreSQL ISO 8601

    PostgreSQL ISO 8601国际标准化组织的国际标准ISO8601是日期和时间的表示方法,全称为《数据存储和交换形式·信息交换·日期和时间的表示方法》。目前最新为第三版ISO8601:2004,第一版为ISO8601:1988,第二版为ISO8601:2000。(摘自百度百科)selectcast(‘2018-08-05T11:00:00Z’astimestamp),–标准时间 cast(‘2018-08-0…

    2025年7月4日
    3
  • python贪吃蛇编程代码大全_200行python代码实现贪吃蛇游戏

    python贪吃蛇编程代码大全_200行python代码实现贪吃蛇游戏本文实例为大家分享了python实现贪吃蛇游戏的具体代码,供大家参考,具体内容如下这次我们来写一个贪吃蛇游戏下面贴出具体代码importpygameimporttimeimportnumpyasnp#此模块包含游戏所需的常量frompygame.localsimport*#设置棋盘的长宽BOARDWIDTH=48BOARDHEIGHT=28#分数score=0cl…

    2022年6月28日
    44
  • 微型计算机及其接口技术

    微型计算机及其接口技术一.微机总线微机中总线一般有内部总线:是微机内部各外围芯片与处理器之间的总线,用于芯片一级的互连系统总线:是微机中各插件板与系统板之间的总线,用于插件板一级的互连1.ISA(industria

    2022年7月1日
    20
  • RabbitMQ VS Apache Kafka (九)—— RabbitMQ集群的分区容错性与高可用性

    RabbitMQ VS Apache Kafka (九)—— RabbitMQ集群的分区容错性与高可用性本章,我们讨论有关RabbitMQ的容错性,消息一致性及高可用性。RabbitMQ可以作为集群节点来运行,因此RabbitMQ通常被归为分布式消息系统,对于分布式消息系统,我们的关注点通常是一致性与可用性。我们为什么要讨论分布式系统的一致性与可用性,本质在于两者描述的是系统在失败的情况下表现如何。单节点持久化原语持久化消息队列/交换器RabbitMQ支持两种类型的消息队列:持久化队列和非持…

    2022年7月25日
    17
  • 大数据认知作业[通俗易懂]

    大数据认知作业[通俗易懂]大数据认知实习作业目录关于作者关于大数据我对大数据的认识目前大数据应用利用大数据的实例大数据分析交通目录关于作者各位博友大家好,我是新晋小白JW,作为一名刚步入学习的小白,我会发表一些我的主观看法,望大家多多指导关于大数据大数据(bigdata),指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。具有海量的数据规模、快速的数据流转、多样的数据类型和价值密度低的四大特征。大数据的5V

    2022年6月1日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号