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 <iostream>
-
#include <unistd.h>
-
#include <cstring>
-
#include <cstdlib>
-
#include <errno.h>
-
#include <signal.h>
-
#include <linux/limits.h>
-
#include <fcntl.h>
-
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。
阅读(1128) | 评论(0) | 转发(0) |