ITPub博客

首页 > > > linux管道的那点事

linux管道的那点事

作者:u_453e1a12781dea 时间:2017-03-17 16:23:22 0 删除 编辑

点击上方“蓝字”可以关注我们哦



|本文来自:ChinaUnix博客

|作者:yjchen218

|原文链接:http://blog.chinaunix.net/uid-29259073-id-5760663.html



管道是一种两个进程间进行单向通信的机制。因为管道传递数据的单向性,管道又称为半双工管道。管道的这一特点决定了器使用的局限性。管道是Linux支持的最初Unix IPC形式之一,具有以下特点:


  1. 数据只能由一个进程流向另一个进程(其中一个读管道,一个写管道);如果要进行双工通信,需要建 立两个管道。

  2. 管道只能用于父子进程或者兄弟进程间通信。,也就是说管道只能用于具有亲缘关系的进程间通信。


使用管道进行通信时,两端的进程向管道读写数据是通过创建管道时,系统设置的文件描述符进行的。从本质上说,管道也是一种文件,但它又和一般的文件有所不同,可以克服使用文件进行通信的两个问题,这个文件只存在内存中。


通过管道通信的两个进程,一个进程向管道写数据,另外一个从中读数据。写入的数据每次都添加到管道缓冲区的末尾,读数据的时候都是从缓冲区的头部读出数据的。

#include
int pipe(int pipefd[2]);


(匿名)管道两端分别用描述符pipefd[0]及pipefd[1]来描述。需要注意的是,管道两端的任务是固定的,一端只能用于读,有描述符pipefd[0]表示,称其为管道读端;另一端只能用于写,由描述符pipe[1]来表示,称其为管道写端。


该函数创建的管道的两端处于一个进程中间,在实际应用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,然后通过管道实现父子进程间的通信。在此不再作多介绍,下面看看有名管道吧。


管道的一个不足之处就是没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道(name pipe或FIFO)提出后,该限制得到了解决。FIFO不同与管道之处在与她提供一个路径名与之关联,以FIFO的文件形式存储在文件系统中。有名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够通过FIFO相互通信了。值得注意的是FIFO(First In First Out)总是按照先进先出的原则工作,第一个被写入的数据首先从管道中读出。


在Linux中我们经常使用管道重定向数据。比如:


下面介绍一下创建有名管道的系统调用,有两个,mknod和mkfifo



#include  

#include 

int mknod(const char *pathname, mode_t mode, dev_t dev);

int mkfifo( const char *pathname, mode_t mode );


函数mknod参数中pathname为创建有名管道的全路径名,mode为创建有名管道的模式,指明其存取权限;dev为设备值,该值取决于文件创建的种类,它只在创建设备文件是才会用到。这两个函数调用成功都返回0,否则返回-1.


读写有名管道:


#include 

ssize_t read (int fd , void * buf , size_t nbytes)

ssize_t write (int fd , void * buf , size_t nbytes)


接下来给大家演示一下通过有名管道通信的聊天程序。。。


  1. // 李四.c  

  2. #include <stdio.h>

  3. #include <stdlib.h>

  4. #include <string.h>

  5. #include <sys/types.h>

  6. #include <sys/stat.h>

  7. #include <fcntl.h>

  8. #include <unistd.h>

  9. #include <errno.h>


  10. #define FIFO_READ    "writefifo" //另外一个程序只要把本程序

  11. #define FIFO_WRITE    "readfifo"   //拷贝一份然后调换这两个宏即可


  12. #define BUF_SIZE    1024

  13. int left = 0;

  14. void *read_buf()

  15. {

  16.     int rfd = -1;

  17.     char buf[BUF_SIZE] = { '\0' };

  18.     int i;


  19.     printf("等待对方……\n");

  20.     while ((rfd = open(FIFO_READ, O_RDONLY)) == -1) {

  21.         sleep(1);

  22.     }

  23.     while (left != 1) {

  24.         //printf("i=%d ",i++);

  25.         int len = read(rfd, buf, BUF_SIZE);

  26.         if (len > 0) {

  27.             buf[len] = '\0';

  28.             

  29.             if(strcmp(buf,"不理你了") == 0){

  30.                 printf("\n对方已经走开!\n");

  31.                 left = 1;

  32.                 break;

  33.             //    exit(0);

  34.             }

  35.             for(i = 0; i < strlen("我:"); i++)

  36.                 printf("\b");


  37.             printf("对方:%s\n", buf);

  38.             printf("我:");

  39.             fflush(stdout);

  40.         }

  41.     }

  42.     

  43.     close(rfd);

  44.     return NULL;

  45. }


  46. void *write_to()

  47. {

  48.     int wfd;

  49.     char buf[BUF_SIZE];

  50.     int len;


  51.     umask(0);

  52.     if (mkfifo(FIFO_WRITE, S_IFIFO | 0666)) {

  53.         printf("Can't create FIFO %s because  %s", FIFO_WRITE,

  54.                strerror(errno));

  55.         exit(1);

  56.     }

  57.     umask(0);

  58.     wfd = open(FIFO_WRITE, O_WRONLY);

  59.     if (wfd == -1) {

  60.         printf("open FIFO %s error: %s", FIFO_WRITE, strerror(errno));

  61.         exit(1);

  62.     }

  63.     while (left != 1) {

  64.         printf("我: ");

  65.         fgets(buf, BUF_SIZE, stdin);

  66.         buf[strlen(buf) - 1] = '\0';

  67.         if (strcmp(buf, "不理你了") == 0 || left == 1) {

  68.             write(wfd, buf, strlen(buf));//通知对方

  69.             close(wfd);

  70.             unlink(FIFO_WRITE);

  71.             exit(0);

  72.         }

  73.         write(wfd, buf, strlen(buf));

  74.         fflush(stdin);

  75.     }

  76. }

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

  78. {

  79.     pthread_t thIDr, thIDw;

  80.     

  81.     pthread_create(&thIDr, NULL,(void *)read_buf, NULL);

  82.     pthread_create(&thIDw, NULL,(void *)write_to, NULL);

  83.     pthread_join(thIDr, NULL);

  84.     pthread_join(thIDw, NULL);


  85.     return 0;

  86. }


学以置用,呵呵,效果如下:


 我知道一种学习

○

于坚




原文作者:;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-07-17

  • 博文量
    1982
  • 访问量
    17885