1. 程式人生 > >黑馬《linux系統程式設計》學習筆記(從26到30)

黑馬《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;
}

 執行一下,結果是

[[email protected]_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
[[email protected]_0_15_centos 6Day]# vim pipe_test.c
[
[email protected]
_0_15_centos 6Day]# gcc pipe_test.c -o pipe_test [[email protected]_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 [
[email protected]
_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;
}