黑马《linux系统编程》学习笔记(从31到35)

三十一. 复习文件描述符重定向

在下面的图中,dup2(fd[1],1)这里的1号文件描述符,跟随老的fd[1],由于这里1号文件描述符,已经有指向,于是原指向关系撤销,1重新建立指向,并指向fd[1]所在。

 接下来,grep "bash"这里是从0号文件描述符,即STDIN_FILENO中读取内容,本来STDIN_FILENO指向的是/dev/tty,也就是终端,换言之。如果没有管道和重定向的话,grep "bash"将直接从终端中读取内容

然而现在,我们通过dup2(fd[0],0)这一操作,使得0号文件描述符,重新定向到了内核缓冲区的读端,因此,现在的grep"bash"指读取的内容,实际是0号文件描述符现在所指的内核缓冲区中的读端。

 

 三十二. 复习有血缘关系的进程间通信思路

下图所示,是子进程写,父进程读。。。

如果说父进程读,子进程写,那么我们需要再创建另一个管道,并且对于父进程,关闭写端。对于子进程,关闭读端。

三十三. 兄弟进程间通信

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

int main(int argc, const char* argv[])
{
    int fd[2];
    int ret  = pipe(fd);
    if(ret == -1)
    {
        perror("pipe error");
        exit(1);
    }

    printf("fd[0] = %d\n", fd[0]);
    printf("fd[1] = %d\n", fd[1]);

    int i = 0;
    int num = 2;
    for(; i<num; ++i)
    {
        pid_t pid = fork();
        if(pid == 0)
        {
            break;
        }
    }

    // parent recyle child pcb
    if(i == num)
    {
        close(fd[0]);
        close(fd[1]);

        // recyle
        pid_t wpid;
        while( (wpid = waitpid(-1, NULL, WNOHANG)) != -1 )
        {
            if(wpid == 0)
            {
                continue;
            }
            printf("died child pid = %d\n", wpid);
        }
    }
    else if(i == 0)
    {
        // ps aux
        close(fd[0]);
        dup2(fd[1], STDOUT_FILENO);
        execlp("ps", "ps", "aux", NULL);
    }
    else if(i == 1)
    {
        // grep bash
        close(fd[1]);
        dup2(fd[0], STDIN_FILENO);
        execlp("grep", "grep", "bash", NULL);
    }
	
	printf("pipe[0]="%d\n",fd[0]);
	printf("pipe[1]="%d\n",fd[1]);	

    return 0;
}

三十四. 创建子进程需要判断pid是否为0

三十五. 管道的读写行为

 

猜你喜欢

转载自blog.csdn.net/garrulousabyss/article/details/85271785