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, '
/*
* 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;
}
', 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, '
/*
* 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;
}
', 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; }



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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

发表回复

您的电子邮箱地址不会被公开。

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