【问题标题】:Why does the child process behave differently when exec is supplied an invalid command?当为 exec 提供无效命令时,为什么子进程的行为会有所不同?
【发布时间】:2021-06-03 22:15:43
【问题描述】:
        pid_t pid;
        pid = fork(); //Two processes are made
        const char* ptr = secondlinecopy;
        if (pid > 0 && runBGflag==0) //Parent process. Waits for child termination and prints exit status
        {
            int status;
            if (waitpid(pid, &status, 0) == pid && WIFEXITED(status))
            {
                printf("Exitstatus [");
                for (int i = 0; i < noOfTokens; i++)
                {
                    printf("%s ", commands[i]);
                }
                printf("\b] = %d\n", WEXITSTATUS(status));
            }
        }
        else if (pid == 0)  //Child process. Executes commands and prints error if something unexpected happened
        {
             printf("why does this only print when an invalid command is supplied?");
             if (runBGflag==1) insertElement(getpid(),ptr);
             execvp(commands[0], commands);
             printf ("exec: %s\n", strerror(errno));
             exit(1);
        }

在代码摘录中,我们看到通过 fork() 创建进程。当 execvp 被提供一个真实的命令时,例如“ls”,我们得到输出。

/home/kali/CLionProjects/clash/cmake-build-debug: ls
clash      CMakeCache.txt  cmake_install.cmake  Testing
clash.cbp  CMakeFiles      Makefile
Exitstatus [ls] = 0

但是,如果我们提供了一个无效的命令,输出将是:

/home/kali/CLionProjects/clash/cmake-build-debug: sd
why does this only print when an invalid command is supplied?exec: No such file or directory
Exitstatus [sd] = 1

为什么会这样?进程是否应该总是先调用 printf("Why does ...") 然后运行 ​​exec?

【问题讨论】:

    标签: c process


    【解决方案1】:

    为什么会这样?进程不应该总是先调用 printf("Why does ...") 然后运行 ​​exec 吗?

    假设它是这样工作的:

    printf(...) --> internal buffer --(fflush? newline? max_buffer_size?)--> output
    

    通常stdout 是行缓冲的,而您的printf 没有换行符。要打印的数据存储在某个内部缓冲区中。当exec-ing stdout 不是fflushed 并且父进程被子进程作为一个整体替换时 - 所以存储在父进程中的所有数据,包括一些内部stdout 状态,都是删除。当exec 失败时,stdout 在你printf(...\n" 时被刷新(或者在stdout 被块缓冲时调用exit() 之后)并显示数据。研究:工作室缓冲模式and setvbuf() function

    【讨论】:

      【解决方案2】:

      为什么会这样?进程是否应该总是先调用 printf("Why does ...") 然后运行 ​​exec?

      是的,它应该,而且你没有提出任何理由认为它没有。

      printf 将输出定向到标准输出流,并且在连接到交互式设备时默认为行缓冲,否则为块缓冲 .当execvp() 成功时,它将整个程序映像替换为新程序的映像,包括任何 I/O 缓冲区的内容。任何已缓冲但未刷新到底层设备的数据都将丢失。

      execvp() 失败并且程序随后正常终止(无论其退出状态如何)时,所有当时缓冲的缓冲数据都会自动刷新到相关的输出设备。

      如果您在要打印的消息中附加换行符,或者如果您在 printfexecvp 调用之间调用 fflush(stdout),或者如果您打印到 stderr 而不是 @ 987654328@,或者如果您关闭了stdout 的缓冲。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-26
        • 2016-03-14
        • 2012-08-28
        相关资源
        最近更新 更多