• 五、进程间通信无名管道


    1、无名管道

      用于具有亲缘关系的进程间通信(常见的就是父子进程),数据只能单向流动。

    (1)创建管道

    #include<unistd.h> 
    int pipe(int pipefd[2]);
    参数:
    • pipefd[2]:参数为两个文件描述符,一个读文件描述符,一个写文件描述符。
    返回值:
    • 成功返回0
    • 失败返回-1,且errno错误码被设置。

    (2)特点:

    • 特殊文件(没有名字),无法使用open,但是可以使用close.

    • 只能通过子进程继承文件描述符的形式来使用。

    • write和read操作可能会zuse进程。

    • 所有文件描述符被关闭之后,无名管道被销毁。

    (3)使用步骤

    • 父进程pipe无名管道

    • fork子进程。

    • close无用端口。

    • write/read读写端口。

    • close读写端口。

     (4)应用实例

    #include<unistd.h>
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    #define MAX_DATA_LEN 256
    #define DELAY_TIME 1
    
    /******父进程通过管道传输数据到子进程**********/
    int main()
    {
        pid_t pid;
        int pipe_fd[2];
        char buf[MAX_DATA_LEN];
        const char data[]  = "Pipe Test Program";
        int real_read,real_write;
    
        memset((void*)buf,0,sizeof(buf));
    
        /*创建管道*/
        if(pipe(pipe_fd) < 0)
        {
            printf("pipe create error!\n");
            exit(1);
        }
    
        /*创建子进程*/
        if((pid=fork()) == 0)  
        {
            /*子进程关闭写文件描述符,并通过使子进程暂停3s等待父进程已关闭相应的读描述符*/
            close(pipe_fd[1]);
            sleep(DELAY_TIME*3);
    
            /*子进程读取管道内容*/
            if((real_read = read(pipe_fd[0],buf,MAX_DATA_LEN)) > 0)
            {
                printf("%d bytes read from the pipe is '%s'\n",real_read,buf);
            }
    
            /*关闭子进程读描述符*/
            close(pipe_fd[0]);
            exit(0);
        }
        else if(pid > 0)
        {
            /*关闭父进程读描述符,并通过使父进程暂停1s等待子进程已关闭相应的写描述符*/
            close(pipe_fd[0]);
            sleep(DELAY_TIME);
            if((real_write == write(pipe_fd[1],data,strlen(data)))!= -1)
            {
                printf("Parent write %d bytes:'%s'\n",real_write,data);;
            }
            /*关闭父进程写描述符*/
            close(pipe_fd[1]);
    
            /*收集子进程退出信息*/
            waitpid(pid,NULL,0);
    
            exit(0);
    
        }
        return 0;
    }
    • 定义一个数组pipe_fd,在创建匿名管道后通过数组返回管道的文件描述符。

    • 调用pipe()创建一个匿名管道,创建成功则得到两个文件描述符pipe_fd[0]、 pipe_fd[1],否则返回-1。

    • 调用fork()创建一个子进程,如果返回值是0则表示此时运行的是子进程,那么在子进程中调用close()函数关闭写描述符,并使子进程睡眠3s等待父进程已关闭相应的读描述符。

    • 子进程调用read()函数读取管道内容,如果管道没有数据则子进程将被阻塞,读取到数据就将数据打印出来。特别地如果调用read()函数读取一个关闭了写描述符的管道,那么read()会返回0,(本例子中父进程的写描述符没有关闭)。

    • 调用close()函数关闭子进程读描述符。

    • 如果fork()函数的返回值大于0,则表示此时运行的是父进程,那么在父进程中先调用close()关闭管道的读描述符,并且等待1s,因为此时可能子进程先于父进程运行,暂且.等待一会。

    • 父进程调用write()函数将数据写入管道。

    • 关闭父进程写描述符。

    • 调用waitpid()函数收集子进程退出信息并退出进程。

    运行结果:

  • 相关阅读:
    虚拟环境和包
    1105471854403716
    Sunshine on my shoulders
    ERROR: Command errored out with exit status 1:
    JAVA调用SAP ODATA服务
    reacthooks学习
    mtalb 密度图 制作
    vue3.0 + vite + ts 完成自动导入 vue API 和 自动导入组件
    【报告笔记】作物顺式调控模块的挖掘与利用
    【WDL】5. 实践与建议
  • 原文地址:https://www.cnblogs.com/yuanqiangfei/p/16197551.html
Copyright © 2020-2023  润新知