进程间通信

匿名管道

/*
    匿名管道
        用在具有关系的进程间,原因是共享文件描述符
        环形队列,双指针-读指针、写指针
        管道中没有数据,read将会被堵塞
        管道写满时,write将会被堵塞
    
    创建匿名管道
        #include <unistd.h>
            

        int pipe(int pipefd[2]);
            参数:
                pipefd[2]:两个文件描述符,传出参数
                    pipefd[0]:指向读端
                    pipefd[1]:指向写端
            返回值:
                成功:返回0
                失败:-1

        在命令行中可以在两个命令之间使用 |,如ls | wc -l

    查看管道缓冲区大小命令
        ulimit -a
    查看管道缓冲区大小函数
        #include <unistd.h>

        long fpathconf(int fd, int name);
            参数:
                name:_PC_PIPE_BUF      宏值,可查文档看到
    注意事项:
        1、所有写描述符都关闭了,当所有数据都被读取后,如果进行读,返回0
        2、如果存在写描述符没有关闭,当所有数据都被读取后,如果进行读,则阻塞
        3、如果读描述符都关闭了,如果有进程进行写操作,则该进程会收到SIGPIPE信号,异常终止
        4、如果存在读描述符没有关闭,管道写满时,再写会堵塞,直到有空位置
*/



// 子进程向父进程传输数据
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main()
{

    int pipefd[2];
    int pipe_flag = pipe(pipefd);
    if(pipe_flag == -1)
    {
        perror("pipe error");
        return -1;
    }



    int fork_flag = fork();

    if(fork_flag == 0)
    {
        char str[1024];
        strcpy(str, "I am a Chinese");
        printf("In the child process: %s\n", str);
        write(pipefd[1], str, strlen(str));
    }
    else
    {
        char str[1024];
        read(pipefd[0], str, sizeof(str));
        printf("In the parent process: %s\n", str);
    }





    return 0;
}

 

ps aux -> grep root 示例

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

// ps aux | grep xxx

int main()
{
    int pipefd[2];

    int pipe_flag = pipe(pipefd);
    if(pipe_flag == -1)
    {
        perror("pipe error");
        return -1;
    }

    int fork_flag = fork();
    if(fork_flag == -1)
    {
        perror("fork error");
        exit(-1);
    }
    else if(fork_flag == 0)
    {
        close(pipefd[0]);
        dup2(pipefd[1], STDOUT_FILENO);
        execl("/bin/ps", "ps", "aux", NULL);
    }
    else
    {
        close(pipefd[1]);
        dup2(pipefd[0], STDIN_FILENO);
        execl("/bin/grep", "grep", "root", NULL);
    }


    return 0;

}

 

非堵塞示例

// 非阻塞管道示例
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int main()
{

    int pipefd[2];
    int pipe_flag = pipe(pipefd);
    if(pipe_flag == -1)
    {
        perror("pipe error");
        return -1;
    }



    int fork_flag = fork();

    if(fork_flag == 0)
    {
        close(pipefd[0]);
        char str[1024];
        strcpy(str, "I am a Chinese");
        while(1)
        {
            // printf("In the child process: %s\n", str);
            write(pipefd[1], str, strlen(str));
            sleep(10);
        }
    }
    else
    {
        
        int fd_flag = fcntl(pipefd[0], F_GETFD); // 获取文件flag
        fd_flag |= O_NONBLOCK;  // 追加不堵塞
        fcntl(pipefd[0], F_SETFL, fd_flag);   // 设置新的flag


        close(pipefd[1]);
        
        while(1)
        {
            char str[1024];
            int len = read(pipefd[0], str, sizeof(str)); 
            printf("%d\n", len);
            if(len <= 0)  // 不要用str的长度进行判断,通过返回值判断
                printf("no info\n");
            else
                printf("parent process recv info: %s\n", str);
            sleep(1);
        }
    }


    return 0;
}

 

posted @ 2023-04-28 15:45  WTSRUVF  阅读(13)  评论(0编辑  收藏  举报