Chinaunix首页 | 论坛 | 博客
  • 博客访问: 112792
  • 博文数量: 27
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 360
  • 用 户 组: 普通用户
  • 注册时间: 2013-08-07 00:14
文章分类

全部博文(27)

文章存档

2015年(1)

2014年(20)

2013年(6)

我的朋友

分类: C/C++

2014-02-26 21:53:57

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

        创建 读写会阻塞的 管道



点击(此处)折叠或打开

  1. #include <iostream>
  2. #include <unistd.h>
  3. #include <cstring>
  4. #include <cstdlib>
  5. #include <errno.h>
  6. #include <signal.h>
  7. #include <linux/limits.h>
  8. #include <fcntl.h>
  9. using namespace std;


  10. void sig_pipe(int signo, siginfo_t* info, void* context)
  11. {
  12.     cout << "[INFO] ############## in sigal SIGPIPE handler .!" << endl;
  13. }
  14. int main(int argc, char* argv[])
  15. {
  16.     /*==================== 注册信号处理函数 ========================*/
  17.     struct sigaction act;
  18.     act.sa_flags = SA_SIGINFO;
  19.     act.sa_sigaction = sig_pipe;
  20.     sigemptyset(&act.sa_mask);
  21.     if (sigaction(SIGIO, &act, NULL) == -1)
  22.     {
  23.         cerr << "[ERROR] ############# failed to call sigaction to get orginal SIGIN disption info .!" << endl;
  24.         exit(EXIT_FAILURE);
  25.     }

  26.     /* =================== 创建管道,并将管道读端的设置为读非阻塞、管道数据后信号通知 ================== */
  27.     int fd[2];
  28.     if (pipe(fd) != 0)
  29.     {
  30.         cerr << "[ERROR] ########### faile to create pipe, error message .!" << endl;
  31.         exit(EXIT_FAILURE);
  32.     }

  33.     /*======================= 将管道的读端设置为读非阻塞 ===================== */
  34.     long cur_flag = fcntl(fd[0], F_GETFL);
  35.     if (cur_flag == -1)
  36.     {
  37.         cerr << "[ERROR] ######### failed to call fcntl .!" << endl;
  38.         exit(EXIT_FAILURE);
  39.     }
  40.     cur_flag |= (O_NONBLOCK | O_ASYNC);
  41.     if (fcntl(fd[0], F_SETFL, cur_flag) == -1)
  42.     {
  43.         cerr << "[ERROR] ######### failed to call fcntl to F_SETFL, error message: " << strerror(errno) << endl;
  44.         exit(EXIT_FAILURE);
  45.     }
  46.     /* ====================== 管道有数据可读,进程接收到SIGIO 信号 ========== */
  47.     if (fcntl(fd[0], F_SETSIG, SIGIO) == -1)
  48.     {
  49.         cerr << "[ERROR] ######### failed to call fcntl to F_SETSIG, error message: " << strerror(errno) << endl;
  50.         exit(EXIT_FAILURE);
  51.     }
  52.     if (fcntl(fd[0], F_SETOWN, getpid()) == -1)
  53.     {
  54.         cerr << "[ERROR] ######### failed to call fcntl to F_SETOWN, error message: " << strerror(errno) << endl;
  55.         exit(EXIT_FAILURE);
  56.     }


  57.     /*    
  58.      * 第1次测试往管道上写东西, 将会看到
  59.      * write 函数返回之前 sig_io 信号处理函数会被调用
  60.      */
  61.     char c = 'a';
  62.     if (write(fd[1], &c, sizeof(c)) != sizeof(c))
  63.     {
  64.         cerr << "[ERROR] ########### write to pipe failed ,error message :" << strerror(errno) << endl;
  65.     }
  66.     cout << "[INFO] ########## write to pipe ok .!" << endl;

  67.     /*
  68.      * 测试从管道读消息,我们将会看到:
  69.      * 虽然管道上现在只有一个字节的数据,因为管道的读端描述符已经设置为读非阻塞,
  70.      * 所以,循环第1次调用read 能从管道上读取一个字节,第2此调用read 会返回-1,表示出错,而错误信息为 资源不可用
  71.      */
  72.     char buf[128];
  73.     ssize_t byte_read;
  74.     while ((byte_read = read(fd[0], buf, sizeof(buf))) > 0);
  75.     cout << "The last call to read return " << byte_read << ", error message: " << strerror(errno) << endl;
  76.     cout << "================================================================" << endl;

  77.     /*    
  78.      * 第2次测试往管道上写东西, 将会看到
  79.      * write 函数返回之前 sig_io 信号处理函数会被调用
  80.      */
  81.     write(fd[1], &c, 1);
  82.     cout << "[INFO] ########## write to pipe ok .!" << endl;

  83.     // 这里没有必要显示调用close来关闭描述符,因为在main函数返回值,进程退出函数会自动
  84.     // 关闭所有打开着的文件描述符
  85.     return 0;

  86. }


管道测试:
         读端 调用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) |
给主人留下些什么吧!~~