【问题标题】:grep doesn't work in custom shellgrep 在自定义 shell 中不起作用
【发布时间】:2011-10-27 05:40:00
【问题描述】:

我正在尝试用 c 编写一个 shell,它除了 grep 之外大部分都可以工作。每当我在 shell 中发出 grep 命令时,它就不会输出任何东西。这是我用来创建新子进程然后在其中运行 execvp() 的部分代码。

dup2 中的文件描述符(fd_in 和 fd_out)作为参数传递给具有此代码的函数。最有趣的是,当我输入 'grep' 或 'grep --help' 时,它会像往常一样显示。我错过了什么吗?还是必须用 grep 做一些特别的事情?

这就是我的 shell 发生的情况:从 bash 运行时的最后一个命令输出。

--> grep
Usage: grep [OPTION]... PATTERN [FILE]...
Try `grep --help' for more information.
--> wc /etc/hosts
 11  33 314 /etc/hosts
--> grep -i "perror" shell.c
--> 

代码如下:

void 
create_process(char *cmd_argv[], int fd_in, int fd_out, char *buffer_copy) {

    /*Flag bit for Background processes*/
    int FLAG = 0;

    pid_t cpid;
    int status;
    int i = 0,j = 0;

    /*Find the no. of arguments*/
    while(cmd_argv[j] != NULL)
        j++;

    /*Set the flag bit*/
    if(strcmp("&", cmd_argv[j-1]) == 0) {
        FLAG = 1;
        cmd_argv[j-1] = NULL;
    }

    //Create a child process
    cpid = fork();

    if (cpid == -1) {
        perror("fork");
        exit(EXIT_FAILURE);
    }

    //In the child...
    if (cpid == 0) {

    /*Checking if the file descriptors are already assigned*/

        /*For stdin*/
        if (fd_in != STDIN_FILENO) {
            dup2(fd_in, STDIN_FILENO);
            close(fd_in);
        }

        /*For stdout*/
        if (fd_out != STDOUT_FILENO) {
            dup2(fd_out, STDOUT_FILENO);
            close(fd_out);
        }

        /*Run the cmd specified*/
        status = execvp(cmd_argv[0], cmd_argv);

        /*In case of errors*/
        if(status < 0) {
            perror("execvp ");
            exit(1);
        }
    }

    //In the parent...
    else {

        if(FLAG == 1) {
            /*Find where the new bg process can be inserted*/
            while(1) {
                if (bgprocess[i].pid == 0) {
                    bgprocess[i].pid = cpid;
                    strcpy(bgprocess[i].cmd, buffer_copy);
                    break;
                }
                i++;
            }
            printf("[%d] : %s\n", cpid, cmd_argv[0] );
        }

        /*If not bg, wait for the process to exit*/
        else 
            waitpid(cpid, NULL, 0);
    }
}

【问题讨论】:

  • 告诉我们你是如何设置cmd_argv的。
  • char *cmd_argv[10];代码的前一部分用适当的参数填充它,然后是 NULL。
  • 在你运行 grep 时显示你的 shell。此外,您可能应该关心 stderr 以及 stdin/stdout。
  • shell.c 中有"perror" 的实例吗?您的玩具外壳是否正确或完全处理引号 (")?当 grep 不匹配时,它的行为是什么?当它什么也没找到时,grep 的返回值是什么?您的外壳如何读取返回值值(提示:waitpid 的第二个参数)?

标签: c shell grep execvp


【解决方案1】:

问题是在你的 shell 中使用引号。 Bash 在后台做了很多事情。 grep -i perror shell.c 应该在你的 shell 上为你提供输出,无论是从 bash 运行时的预期结果。

【讨论】:

    【解决方案2】:

    Qman dup2:

    从这些系统调用之一成功返回后,旧的和 新的文件描述符可以互换使用。他们指的是 相同的打开文件描述(参见 open(2))...

    因此,在您调用 dup2(您应该检查错误返回)之后,您关闭 oldfdnewfd,因为它们是完全相同的描述符。

    我不明白为什么grep --help 完全有效,但您没有显示足够的代码来回答这个问题。

    添加了以下评论:您仍然没有提供足够的代码。如果grep 不起作用,那是什么? wc /etc/hosts 有效吗? grep 没有什么特别之处,实际上它是一个完全不特殊的 Unix 过滤器。

    【讨论】:

    • 不,不可能。您可以在不影响底层文件描述的情况下 关闭 文件描述 - 否则您将无法仅从进程重定向 stdout(因为 stdout 和 stderr 最初指的是同一个打开的文件,而您必须先关闭 fd 1,然后才能 dup2 到它上面)。除了close之外的所有else都会影响底层文件描述。
    • 在主帖中更新了我的 shell 的输出。
    猜你喜欢
    • 2013-11-01
    • 1970-01-01
    • 2021-10-04
    • 1970-01-01
    • 2023-03-18
    • 2020-03-29
    • 2020-10-22
    • 1970-01-01
    • 2021-03-11
    相关资源
    最近更新 更多