linux里面的过滤符号 | 是如何实现的

ls -l | grep ".txt" 的实现过程涉及无名管道的创建、进程的创建(fork())以及输入输出的重定向(dup2())。以下是详细的实现步骤和代码示例:


实现步骤

  1. 创建无名管道

    • 使用pipe()系统调用创建一个无名管道,管道会返回两个文件描述符:pipefd[0](读端)和pipefd[1](写端)。

  2. 创建子进程

    • 使用fork()创建子进程。父进程和子进程会共享管道的文件描述符。

  3. 重定向输入输出

    • 在父进程中:

      • 关闭管道的读端(pipefd[0])。

      • 将标准输出(STDOUT_FILENO)重定向到管道的写端(pipefd[1])。

      • 执行ls -l命令,其输出会写入管道。

    • 在子进程中:

      • 关闭管道的写端(pipefd[1])。

      • 将标准输入(STDIN_FILENO)重定向到管道的读端(pipefd[0])。

      • 执行grep ".txt"命令,其输入会从管道读取。

  4. 等待子进程完成

    • 父进程使用wait()等待子进程结束。


代码实现

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

int main() {
    int pipefd[2]; // 用于存储管道的文件描述符
    pid_t pid;

    // 创建无名管道
    if (pipe(pipefd) == -1) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }

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

    if (pid == 0) { // 子进程:执行 grep ".txt"
        // 关闭管道的写端
        close(pipefd[1]);

        // 将标准输入重定向到管道的读端
        if (dup2(pipefd[0], STDIN_FILENO) == -1) {
            perror("dup2");
            exit(EXIT_FAILURE);
        }

        // 关闭管道的读端(已经重定向,不再需要)
        close(pipefd[0]);

        // 执行 grep ".txt"
        execlp("grep", "grep", ".txt", NULL);
        perror("execlp"); // 如果 execlp 失败
        exit(EXIT_FAILURE);
    } else { // 父进程:执行 ls -l
        // 关闭管道的读端
        close(pipefd[0]);

        // 将标准输出重定向到管道的写端
        if (dup2(pipefd[1], STDOUT_FILENO) == -1) {
            perror("dup2");
            exit(EXIT_FAILURE);
        }

        // 关闭管道的写端(已经重定向,不再需要)
        close(pipefd[1]);

        // 执行 ls -l
        execlp("ls", "ls", "-l", NULL);
        perror("execlp"); // 如果 execlp 失败
        exit(EXIT_FAILURE);
    }

    // 父进程等待子进程结束
    wait(NULL);
    return 0;
}
 

代码说明

  1. pipe(pipefd)

    • 创建一个无名管道,pipefd[0]是读端,pipefd[1]是写端。

  2. fork()

    • 创建子进程。父进程和子进程会同时运行,但通过if (pid == 0)区分逻辑。

  3. dup2(pipefd[1], STDOUT_FILENO)

    • 将标准输出重定向到管道的写端,使得ls -l的输出写入管道。

  4. dup2(pipefd[0], STDIN_FILENO)

    • 将标准输入重定向到管道的读端,使得grep ".txt"从管道读取输入。

  5. execlp()

    • 替换当前进程的映像,执行指定的命令(如ls -lgrep ".txt")。

  6. wait(NULL)

    • 父进程等待子进程结束,避免僵尸进程。


运行结果

运行该程序后,会输出当前目录下所有包含.txt的文件列表,效果与直接在终端运行ls -l | grep ".txt"相同。


总结

通过无名管道和进程间通信,我们可以实现类似Shell管道的功能。无名管道的核心在于:

  • 父子进程共享文件描述符。

  • 通过dup2()重定向输入输出。

  • 使用execlp()执行命令。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嵌入式园姐

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值