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

二十六. 管道相关概念

 

 

 二十七. pipe函数的使用

 

 首先,这里我们写一个pipe.c文件

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.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]);

    close(fd[0]);
    close(fd[1]);

    return 0;
}

 运行一下,结果是

[root@VM_0_15_centos 6Day]# ls
a.out          eng.txt      ipc.c               pipe.c       write_fifo.c
brother_ipc.c  fpathconf.c  mmap.c              pipe_test.c
english.txt    homework     parent_child_ipc.c  read_fifo.c
[root@VM_0_15_centos 6Day]# vim pipe_test.c
[root@VM_0_15_centos 6Day]# gcc pipe_test.c -o pipe_test
[root@VM_0_15_centos 6Day]# ls
a.out          eng.txt      ipc.c               pipe.c       read_fifo.c
brother_ipc.c  fpathconf.c  mmap.c              pipe_test    write_fifo.c
english.txt    homework     parent_child_ipc.c  pipe_test.c
[root@VM_0_15_centos 6Day]# ./pipe_test
fd[0] = 3
fd[1] = 4

 因为文件描述符0,1,2被占用,所以这里自然而然文件描述符分别是3,4

二十八. 有血缘关系的进程间通信fork的位置

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.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]);
    
    //fork放这里的原因是,子进程中的3号文件描述符与4号文件描述符,同父进程中的文件描述符一样,都指向了这个管道。
    pid_t pid = fork();

    return 0;
}

二十九. 使用匹配父子进程间通信练习思路

 

 下面这个图很重要,我们大概解释一下

一般情况下,当没有管道的时候,终端连接着STDOUT_FILENO,终端也连接着STDIN_FILENO。当我们要用管道时,将STDOUT_FILENO重定向到内核缓冲区的写端,将STDIN_FILENO重定向到内核缓冲区的读端。

在下图中,我们说父进程的3号文件描述符对应管道的读端, 4号文件描述符对应管道的写端。那么我们做了fork操作后,子进程的3号文件描述符也对应读端,4号文件描述符也对应写端。

这里由于数据只能读一次。

因此父进程读的时候,关闭写端。子进程写的时候,关闭读端。

因此父进程

 三十. 父子进程通信——代码实现ps aux grep bash

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


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

    // 创建子进程
    pid_t pid = fork();
    if(pid == -1)
    {
        perror("fork error");
        exit(1);
    }

    // ps aux | grep bash
    // 父进程 ps aux , 写管道, 关闭读端
    if(pid > 0)
    {
		//注意这里父进程写的时候,关闭读端
        close(fd[0]);
		//文件描述符的重定向
        // 数据写到管道,STDOUT_FILENO 指向管道的写端
        dup2(fd[1], STDOUT_FILENO);
        execlp("ps", "ps", "aux", NULL);
        perror("execlp ps");
        exit(1);
    }
    // 子进程 grep bash 从管道中搜索, 读管道, 关闭写端
    else if(pid == 0)
    {
		//注意这里子进程读的时候,关闭写端
        close(fd[1]);
        dup2(fd[0], STDIN_FILENO);
        execlp("grep", "grep", "bash", NULL);
        perror("execlp grep");
        exit(1);
    }
    
    return 0;
}

猜你喜欢

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