date

2022 0601

简介

带管道(简单实现 只支持一个管道)

#测试样例
ls -l | more
ps -ef | wc -l

代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
int main(void)
{
    char buf[256], *argv[256], **p;
    int sv = 0;
    //管道参数
    char *cmd2, *argv2[256];
    int fd[2];
    for (;;) 
    {
        printf("=> ");
        //读入标准输入
        if (fgets(buf, sizeof(buf), stdin) == NULL) exit(0); //ctrl+D退出

        //没有管道 退出
        if((cmd2 = strstr(buf, "|")) == NULL) exit(0);

        //确定第二个命令的起点
        *(cmd2++) = '\0';

        //对字符串进行分割 结果放到argv里面
        for (p = &argv[0], *p = strtok(buf, " \t\n"); *p != NULL; 
            *++p = strtok(NULL, " \t\n"));
        //第二个命令 数组argv2[] 起点 cmd2
        for (p = &argv2[0], *p = strtok(cmd2, " \t\n"); *p != NULL; 
            *++p = strtok(NULL, " \t\n"));
        //空输入
        if (argv[0] == NULL || argv2[0] == NULL) exit(0);
            
        //创建管道
        pipe(fd);
        //两个进程分别执行两个cmd(argv[] 和 argv2[])
        // int sv1 = fork();
        // int sv2 = fork();

        if(fork() == 0) {
            //用管道写端口 替换 子进程的标准输出, 即子进程输出到写端口
            dup2(fd[1], 1);
            //这里其实管道还在 只有管道所有写段读端全部关闭 管道才消失 下面同理
            close(fd[1]);
            close(fd[0]);
            execvp(argv[0], argv);
            fprintf(stderr, "** bad command 1 : %m\n");
            exit(1);
        } else if(fork() == 0) {
            //用管道的读端口 替换子进程的标准输入 即子进程冲管道读端口获取输入
            dup2(fd[0], 0);
            close(fd[0]);
            close(fd[1]);
            execvp(argv2[0], argv2);
            fprintf(stderr, "** bad command 2 : %m\n");
            exit(1);
        }
        close(fd[0]);
        close(fd[1]);
        wait(&sv);
        wait(&sv);
    }
    return 0;
}
posted on 2022-06-01 10:39  彼岸花不开彼岸  阅读(43)  评论(0)    收藏  举报