zoukankan      html  css  js  c++  java
  • Linux 进程通信(无名管道)

    无名管道
    无名管道是半双工的,就是对于一个管道来讲,只能读,或者写。
    无名管道只能在相关的,有共同祖先的进程间使用(即一般用户父子进程)。
    一个fork或者execve调用创建的子进程继承了父进程的文件描述符。
    打开和关闭管道
    int pipe(int filedes[2]);
    在你从一个管道中读出或者写入数据,这个管道必须存在。
    如果成功建立了管道,则会打开两个文件描述符,并把他们的值保存在一个整数数组中。
    第一个文件描述符用于读取数据,第二个文件描述符用于写入数据。
    管道的两个文件描述符相当于管道的两端,一端只负责读数据,一端只负责写数据 如果出错返回
    -1,同时设置errno 关闭一个文件描述符用close()函数
    关闭一个管道的所有文件描述符等于关闭这个管道(不能读不能写) pipe()函数打开管道一般不会失败
    读写管道
    读写管道与读写普通文件方式一样,调用write与read函数即可。
    几乎不会在一个进程中打开一个管道仅供进程自己使用,管道是用来交换数据的。
    因为一个进程已经能够访问它要通过管道共享的数据,和自己共享数据是没有意义的。
    试图对一个管道的某一端同时进行读写操作是一个严重的错误。
    //无名管道
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    int main(int arg, char * args[])
    {
        //定义文件描述符数组
        int fdarr[2] = { 0 };
        int no = 0;
        int status;
        //create the conduit  创建一个管道 并且打开两个文件描述符
        //管道中,第一个文件描述符只读,第二个文件描述符只写
        no = pipe(fdarr);
        if (no == -1)
        {
            printf("pipe() is failed ! message :%s
    ", strerror(errno));
            return -1;
        }
        //创建父子进程
        pid_t child = fork();
        if (child == -1)
        {
            printf("system is game over !
    ");
            return -1;
        }
        //定义缓存字符串数组
        char buf[100] = { 0 };
        if (child == 0)
        {
            /*
             管道和文件一样,文件read函数以O_RDONLY方式打开也会阻塞,但是文件数据在本地,读取非常快,感觉不到阻塞,
             但是管道以O_RDONLY方式打开,会阻塞进程,read()函数会等待管道另一端写入数据,直到另一端关闭文件描述符
             */
            //关闭子进程中的写文件描述符--对于父子进程共享文件描述符,只在单个进程中关闭,只能将文件描述符引用减一,
            //因为父子进程中,文件描述符被引用了两次,所以需要在父子进程中分别关闭,才能使文件描述符引用次数减一
            close(fdarr[1]);
            while (read(fdarr[0], buf, sizeof(buf)) > 0)
            {
                printf("%s", buf);
                //清空缓存区
                memset(buf, 0, sizeof(buf));
            }
            //关闭子进程中读文件描述符
            close(fdarr[0]);
        } else
        {
            //关闭父进程中的读描述符
            close(fdarr[0]);
            //将键盘输入数据写入到管道中
            strcpy(buf,"fly on air!
    ");
            write(fdarr[1], buf, strlen(buf));
            //关闭管道写文件描述符
            close(fdarr[1]);
            //等待子进程结束
            wait(&status);
            printf("child process is close ! message :%d
    ", WEXITSTATUS(status));
        }
        return 10;
    }

  • 相关阅读:
    Android ActivityGroup的使用代码将子activty 的layout加入到主activity中
    ERROR: Application requires API version 10. Device API version is 8
    简单实现Android实现九宫格
    继承中new 与 override的作用
    Sql server 数量累计求和
    Android 应用程序窗体显示状态操作(requestWindowFeature()的应用)
    UDP传输错误 无法找到程序集“client, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
    堆与栈的区别
    Decorator模式
    时间为O(1)删除节点的代码
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/5829801.html
Copyright © 2011-2022 走看看