进程间通信(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\npipe[1] = %d\n", 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\npipe[1] = %d\n", fd[0], fd[1]);

        int i = 0;
        for(; i<2; i++)
        {
                pid_t pid = fork();
                printf("pid = %d\n", 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\n", 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\n");
                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\n");
                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\n, len = %d", buf, len);
        }

        close(fd);

        return 0;
}
read_fifo.c

 

posted @ 2019-12-02 16:34  xd_xumaomao  阅读(96)  评论(0编辑  收藏  举报