linux编程—管道编程,Linux 平台管道编程笔记

commit f24da015d79edf4b8d5a1cec5aec37103d4b6626

Author: weijiaqiang

Date:   Sat Feb 22 16:43:48 2014 +0800

测试:如果使用 O_ASYNC 和 信号处理机制。

测试结果:

如果管道描述符的状态发生改变时(可以在fd[0]上读取到数据或可以往fd[1]上写入数据)

进程会收到信号。

commit b7de551beea93ddf05da4da7281349ecfcf18c9c

Author: weijiaqiang

Date:   Sat Feb 22 16:26:26 2014 +0800

测试: 当管道的读端处于非阻塞状态下,read 一个没有数据的管道时

会有什么影响?

测试结果:

read 函数返回 -1, errno 别设置为 EAGIN

commit bed40410ba3c14fbaec1d6f14e64e990c9bf2ef7

Author: weijiaqiang

Date:   Sat Feb 22 16:06:52 2014 +0800

测试:在Linux 下,宏定义 PIPE_BUF 的值

测试结果:

PIPE_BUF 宏定义在 /usr/include/linux/limits.h 头文件中定义

它的值为4096, 这个值的含义为当多个往同一个管道写时,写入的

数据小于PIPE_BUF 所定义的字节数,系统可以保证这次该写操作是

原子的。

commit e637dd4f551b14badca5110a47590280f4b87a6f

Author: weijiaqiang

Date:   Sat Feb 22 16:01:31 2014 +0800

测试: 当管道所有的写端都已经关闭时, 调用read

从管道的读端读数据会有什么应影响?

测试结果:

当read读出管道内所有数据之后,会返回0(end of

file)的意思,读端可以通过这个返回值看看,管道是否还有写端

commit 27814d9c694b7cd630ceecd04b5c7df0b5367c85

Author: weijiaqiang

Date:   Sat Feb 22 15:53:36 2014 +0800

测试管道的读端关闭后,往管道上写数据会有如何影响。

测试的结果是:

进程会收到SIGPIPE信号,同时 errno 被设置为 EPIPE

commit ecc0da3180274217e45fb83f3738c5160b6c03f5

Author: weijiaqiang

Date:   Sat Feb 22 15:45:37 2014 +0800

测试管道的默认缓冲区大小, 测试结果为65535个字节

commit f390ae0d9c2b90a9f6eecbe9e4da0efe568c0a68

Author: weijiaqiang

Date:   Sat Feb 22 15:41:50 2014 +0800

创建 读写会阻塞的 管道

点击(此处)折叠或打开

#include

#include

#include

#include

#include

#include

#include

#include

using namespace std;

void sig_pipe(int signo, siginfo_t* info, void* context)

{

cout << "[INFO] ############## in sigal SIGPIPE handler .!" << endl;

}

int main(int argc, char* argv[])

{

/*==================== 注册信号处理函数 ========================*/

struct sigaction act;

act.sa_flags = SA_SIGINFO;

act.sa_sigaction = sig_pipe;

sigemptyset(&act.sa_mask);

if (sigaction(SIGIO, &act, NULL) == -1)

{

cerr << "[ERROR] ############# failed to call sigaction to get orginal SIGIN disption info .!" << endl;

exit(EXIT_FAILURE);

}

/* =================== 创建管道,并将管道读端的设置为读非阻塞、管道数据后信号通知 ================== */

int fd[2];

if (pipe(fd) != 0)

{

cerr << "[ERROR] ########### faile to create pipe, error message .!" << endl;

exit(EXIT_FAILURE);

}

/*======================= 将管道的读端设置为读非阻塞 ===================== */

long cur_flag = fcntl(fd[0], F_GETFL);

if (cur_flag == -1)

{

cerr << "[ERROR] ######### failed to call fcntl .!" << endl;

exit(EXIT_FAILURE);

}

cur_flag |= (O_NONBLOCK | O_ASYNC);

if (fcntl(fd[0], F_SETFL, cur_flag) == -1)

{

cerr << "[ERROR] ######### failed to call fcntl to F_SETFL, error message: " << strerror(errno) << endl;

exit(EXIT_FAILURE);

}

/* ====================== 管道有数据可读,进程接收到SIGIO 信号 ========== */

if (fcntl(fd[0], F_SETSIG, SIGIO) == -1)

{

cerr << "[ERROR] ######### failed to call fcntl to F_SETSIG, error message: " << strerror(errno) << endl;

exit(EXIT_FAILURE);

}

if (fcntl(fd[0], F_SETOWN, getpid()) == -1)

{

cerr << "[ERROR] ######### failed to call fcntl to F_SETOWN, error message: " << strerror(errno) << endl;

exit(EXIT_FAILURE);

}

/*

* 第1次测试往管道上写东西, 将会看到

* write 函数返回之前 sig_io 信号处理函数会被调用

*/

char c = 'a';

if (write(fd[1], &c, sizeof(c)) != sizeof(c))

{

cerr << "[ERROR] ########### write to pipe failed ,error message :" << strerror(errno) << endl;

}

cout << "[INFO] ########## write to pipe ok .!" << endl;

/*

* 测试从管道读消息,我们将会看到:

* 虽然管道上现在只有一个字节的数据,因为管道的读端描述符已经设置为读非阻塞,

* 所以,循环第1次调用read 能从管道上读取一个字节,第2此调用read 会返回-1,表示出错,而错误信息为 资源不可用

*/

char buf[128];

ssize_t byte_read;

while ((byte_read = read(fd[0], buf, sizeof(buf))) > 0);

cout << "The last call to read return " << byte_read << ", error message: " << strerror(errno) << endl;

cout << "================================================================" << endl;

/*

* 第2次测试往管道上写东西, 将会看到

* write 函数返回之前 sig_io 信号处理函数会被调用

*/

write(fd[1], &c, 1);

cout << "[INFO] ########## write to pipe ok .!" << endl;

// 这里没有必要显示调用close来关闭描述符,因为在main函数返回值,进程退出函数会自动

// 关闭所有打开着的文件描述符

return 0;

}

管道测试:

读端 调用open(file_name, O_RDONY | O_NONBLOCK) 来获取管道描述。 因为指定 O_NONBLOCK, 所以即使没有任何进程打开该管道写, open 都不会堵塞。

接下来,调用 read 尝试从管道读取数据,会由一下的情景。

1)当前还没有任何进程打开该管道用于写, read 的返回值是 0

2)当前有进程在打开该管道用于写, <1>管道上由数据可读,read 返回读取的数据大小;<2> 管道上没有数据, read 返回-1,errno 的值为 EAGAIN。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值