zoukankan      html  css  js  c++  java
  • 进程间通信(IPC)

    进程间通信常用的4种方法

    1. 管道:简单

    2. 信号:系统开销小

    3. 共享映射区:有无血缘关系的进程间通信都可以

    4. 本地套接字:稳定

    管道

    匿名管道pipe

    适用于有血缘关系的进程间通信

    pipe函数

    #include<unistd.h>

    int pipe(int filedes[2]);

    返回值:成功,返回0,否则返回-1。参数数组包含pipe使用的两个文件的描述符。fd[0]:读管道,fd[1]:写管道。

    必须在fork()中调用pipe(),否则子进程不会继承文件描述符。两个进程不共享祖先进程,就不能使用pipe。但是可以使用命名管道。

    通过父子进程间通信,实现 ps aux | grep "bash"

    #include <stdio.h>
    #include <unistd.h>
    
    int main()
    {
            int fd[2];
            int ret = pipe(fd);
            if(ret == -1)
            {
                    printf("pipe error");
                    exit(1);
            }
            printf("pipe[0] = %d
    pipe[1] = %d
    ", fd[0], fd[1]);
    
            pid_t pid = fork();
            if(pid == -1)
            {
                    perror("fork error");
                    exit(1);
            }
    
            //父进程执行 ps aux
            if(pid)
            {
                    //写管道操作,关闭读端
                    close(fd[0]);
    
                    //把标准输出重定向到管道写端
                    dup2(fd[1], STDOUT_FILENO);
    
                    execlp("ps","ps", "aux", NULL);
            }
            //子进程执行 grep "bash"
            else if(pid == 0)
            {
                    //关闭写端
                    close(fd[1]);
    
                    //把管道读端重定向到标准输入
                    dup2(fd[0], STDIN_FILENO);
    
                    execlp("grep", "grep", "bash", NULL);
            }
    
            close(fd[0]);
            close(fd[1]);
            return 0;
    }
    View Code

    通过兄弟进程间通信,实现 ps aux | grep "bash"

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    
    int main()
    {
            int fd[2];
            int ret = pipe(fd);
            if(ret == -1)
            {
                    printf("pipe error");
                    exit(1);
            }
            printf("pipe[0] = %d
    pipe[1] = %d
    ", fd[0], fd[1]);
    
            int i = 0;
            for(; i<2; i++)
            {
                    pid_t pid = fork();
                    printf("pid = %d
    ", pid);
                    if(pid == -1)
                    {
                            perror("fork error");
                            exit(1);
                    }
                    else if(pid == 0)
                    {
                            break;
                    }
            }
    
            //子进程1执行 ps aux
            if(i == 0)
            {
                    //写管道操作,关闭读端
                    close(fd[0]);
    
                    //把标准输出重定向到管道写端
                    dup2(fd[1], STDOUT_FILENO);
    
                    execlp("ps","ps", "aux", NULL);
            }
            //子进程2执行 grep "bash"
            else if(i == 1)
            {
                    //关闭写端
                    close(fd[1]);
    
                    //把管道读端重定向到标准输入
                    dup2(fd[0], STDIN_FILENO);
    
                    execlp("grep", "grep", "bash", NULL);
            }
            //父进程
            else if(i == 2)
            {
                    close(fd[0]);
                    close(fd[1]);
                    pid_t wpid;
                    while((wpid = waitpid(-1, NULL, WNOHANG)) != -1)
                    {
                            if(wpid == 0)
                            {
                                    continue;
                            }
                            printf("child process %d died
    ", wpid);
                    }
            }
    
            close(fd[0]);
            close(fd[1]);
            return 0;
    }
    View Code

    有名管道fifo实现无血缘关系进程间通信

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <string.h>
    #include <fcntl.h>
    
    int main(int argc, const char* argv[])
    {
            if(argc < 2)
            {
                    printf("./a.out fifoname
    ");
                    exit(1);
            }
    
            //判断文件是否存在
            int ret = access(argv[1], F_OK);
            if(ret == -1)
            {
                    int r = mkfifo(argv[1], 0664);
                    if(r == -1)
                    {
                            perror("mkfifo error");
                            exit(1);
                    }
                    printf("fifo %s build success!", argv[1]);
            }
    
            int fd = open(argv[1], O_WRONLY);
            if(fd == -1)
            {
                    perror("open error");
                    exit(1);
            }
    
            char *p = "hello world";
            while(1)
            {
                    sleep(1);
                    int len = write(fd, p, strlen(p) + 1);
            }
    
            close(fd);
    
            return 0;
    }
    write_fifo.c
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <string.h>
    #include <fcntl.h>
    
    int main(int argc, const char* argv[])
    {
            if(argc < 2)
            {
                    printf("./a.out fifoname
    ");
                    exit(1);
            }
    
            //判断文件是否存在
            int ret = access(argv[1], F_OK);
            if(ret == -1)
            {
                    int r = mkfifo(argv[1], 0664);
                    if(r == -1)
                    {
                            perror("mkfifo error");
                            exit(1);
                    }
                    printf("fifo %s build success!", argv[1]);
            }
    
            int fd = open(argv[1], O_RDONLY);
            if(fd == -1)
            {
                    perror("open error");
                    exit(1);
            }
    
            char buf[512];
            while(1)
            {
                    int len = read(fd, buf, sizeof(buf));
                    buf[len] = 0;
                    printf("buf = %s
    , len = %d", buf, len);
            }
    
            close(fd);
    
            return 0;
    }
    read_fifo.c
  • 相关阅读:
    Scala教程之:静态类型
    java运行时跟编译时的区别,欢迎大家指正
    循环者的诅咒
    Python分支结构与流程控制
    底层剖析Python深浅拷贝
    I/O格式化与运算符
    详解Python垃圾回收机制
    LeetCode29 Medium 不用除号实现快速除法
    详解SkipList跳跃链表【含代码】
    高等数学——讲透微分中值定理
  • 原文地址:https://www.cnblogs.com/xumaomao/p/11971508.html
Copyright © 2011-2022 走看看