zoukankan      html  css  js  c++  java
  • linux进程间通信--管道通信

    管道进程间通信

    (1)无名管道
    特点:
      只能用于具有亲缘关系进程间通信(具有亲缘关系的进程具有数据拷贝动作(复制父进程创建子进程))或者兄弟进程之间

      是一种单工的通信模式,具有固定的读端和写端

    int pipe(int pipefd[2]);
     功能:创建一个无名管道
    参数:
    @pipefd 获取操作无名管道的文件描述符    pipefd[0]:读无名管道     pipefd[1]:写无名管道
    返回值:
    成功返回0,失败返回-1



    示例如下:

    void write_pipe(int fd)
    {
      int ret;
      char buf[1024];

    while(1)
    {
      fgets(buf,sizeof(buf),stdin);
      buf[strlen(buf) - 1] = '';

      ret = write(fd,buf,strlen(buf));
      printf("write %d bytes! ",ret);

      if(strcmp(buf,"quit") == 0){
        break;
      }
    }

    return;
    }

    void read_pipe(int fd)
    {
      int ret;
      char buf[1024];

    while(1)
    {
      printf("read ....! ");
      ret = read(fd,buf,sizeof(buf));
      buf[ret] = '';
      printf("Read %d bytes : %s ",ret,buf);

    if(strcmp(buf,"quit") == 0){
      break;
      }
    }

    return;
    }

    int main(int argc, const char *argv[])
    {
      int ret;
      pid_t pid;
      int pipefd[2];

      ret = pipe(pipefd);
      if(ret < 0){
        perror("Fail to pipe");
        exit(EXIT_FAILURE);
      }

    pid = fork();
    if(pid < 0){
      perror("Fail to fork");
      exit(EXIT_FAILURE);
    }

    if(pid == 0){
      close(pipefd[1]);
      read_pipe(pipefd[0]);
    }

    if(pid > 0){
      close(pipefd[0]);
      write_pipe(pipefd[1]);
    }

    return 0;
    }

    功能:让父进程从键盘读入数据,然后写到无名管道,让子进程从无名管道中读取数据,然后输出,
    如果输入"quit",则两个进程结束,功能比较简单


    (2)管道读写规则
    读端存在 ,写管道 ---->只要管道没有满,都可以写入数据到管道
    读端不存在,写管道 ---->此时写管道没有意义,操作系统会发送SIGPIPE杀死写管道的进程

    写端存在, 读管道 ---->此时管道中读取数据,管道中没有数据,读阻塞
    写端不存在,读管道 ---->此时管道中读取数据,管道中没有数据,此时不阻塞,立即返回,返回值0

    (3)有名管道
    特点:

    可以用于任意进程间通信,它是一种特殊的文件,在文件系统存在名字,
    而文件中存放的数据是在内核空间,而不是在磁盘上

    1.创建一个有名管道文件
    int mkfifo(const char *pathname, mode_t mode);
    @pathname 有名管道存在的路径
    @mode 有名管道的权限
    返回值:
    成功返回0,失败返回-1

    与FIFO相关的错误信息(主要如下)

    EEXIST:参数filename所指定的文件已存在

    EACCESS::参数filename所指定的目录无可执行权限

    常用的用法:

    if(access(FIFO,F_OK)==-1)

    {

      if(mkfifo(FIFO,0666)<0)&&(errno!=EEXIST)

      {

        printf("cannot create fifo file ");

        exit(1);

      }

    }

    2.打开有名管道文件

    open

    如果有名管道的一端以只读的方式打开,会阻塞,直到另一端以写(只写或读写)的方式打开
    如果有名管道的一端以只写的方式打开,会阻塞,直到另一端以读(只读或读写)的方式打开


    3.读写操作
    read /write

    4.关闭管道文件
    close(fd);

    示例如下:

    a_fifo.c:

    void read_fifo(int fd)
    {
      int ret;
      char buf[1024];

    while(1)
    {
      printf("read ....! ");
      ret = read(fd,buf,sizeof(buf));
      buf[ret] = '';

      printf("Read %d bytes : %s ",ret,buf);

      if(strcmp(buf,"quit") == 0){
        break;
      }
    }

    return;
    }

    int main(int argc, const char *argv[])
    {
      int ret;
      int fd;

    if(argc < 2){
      fprintf(stderr,"Usage : %s <fifo>! ",argv[0]);
      return -1;
    }

    ret = mkfifo(argv[1],0666);
      if(ret < 0 && errno != EEXIST){
        fprintf(stderr,"Fail to mkfifo %s : %s! ",argv[1],strerror(errno));
        return -1;
      }

    fd = open(argv[1],O_RDONLY);
    if(fd < 0){
      fprintf(stderr,"Fail to open %s : %s! ",argv[1],strerror(errno));
      return -1;
      }
    printf("open success, fd : %d! ",fd);

    read_fifo(fd);

    close(fd);

    return 0;
    }

    b_fifi.c:

    void write_fifo(int fd)
    {
      int ret;
      char buf[1024];

    while(1)
    {
      fgets(buf,sizeof(buf),stdin);
      buf[strlen(buf) - 1] = '';

      ret = write(fd,buf,strlen(buf));
      printf("write %d bytes! ",ret);

      if(strcmp(buf,"quit") == 0){
      break;
      }
    }

    return;
    }

    //./a.out fifo
    int main(int argc, const char *argv[])
    {
      int ret;
      int fd;

    if(argc < 2){
      fprintf(stderr,"Usage : %s <fifo>! ",argv[0]);
      return -1;
    }

    ret = mkfifo(argv[1],0666);
    if(ret < 0 && errno != EEXIST){
    fprintf(stderr,"Fail to mkfifo %s : %s! ",argv[1],strerror(errno));
    return -1;
    }

    fd = open(argv[1],O_WRONLY);
    if(fd < 0){
      fprintf(stderr,"Fail to open %s : %s! ",argv[1],strerror(errno));
      return -1;
    }
    printf("open success, fd : %d! ",fd);

    write_fifo(fd);

    close(fd);

    return 0;
    }

    功能如下:
     A进程向有名管道中写数据 , B进程从有名管道中读取数据 (A,B进程没有亲缘关系)

    编译a_fifi.c 和b_fifi.c

    gcc a_fifio.c -o a

    gcc b_fifio.c -o b

    并运行

    a fifo

    b fifo

     管道通信还是比较简单!

  • 相关阅读:
    android 项目
    input keyevent 数字对应的操作
    logcat 使用方法
    android查看内存使用情况
    图片点击放大效果
    禁止img图片拖动在新窗口打开
    人工智能
    游戏开发
    随手做的一个模拟弹出窗口
    Html的<meta>标签使用方法及用例
  • 原文地址:https://www.cnblogs.com/bwbfight/p/9289348.html
Copyright © 2011-2022 走看看