所以当我在没有sudo的情况下调用这个程序。它工作得很好。
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char** argv)
{
if(fork() == 0) execvp(argv[1], &argv[1]);
// else wait(NULL);
}但是使用sudo (当我需要输入密码时),它会给出一个奇怪的输出:
pasha@skynet:~$ sudo ./a.out bash
[sudo] password for pasha:
pasha@skynet:~$ root@skynet:~# 然后,在任何输入时,终端终止。此外,它只发生在新产生的终端上。当父母等待孩子的时候,sudo的问题就消失了。
有人能解释一下原因吗?
发布于 2020-05-01 17:33:47
为什么会发生这种情况
你正在fork你的进程,所以现在有两个进程。
一个进程是父进程,由您的shell运行的进程,如shell -> fork() -> exec(sudo) -> exec(./a.out)。父级终止,因为fork返回非零值,然后main()到达闭合的}。默认情况下,main返回0。因此,shell看到您的程序终止,退出状态为0。在您的程序完成后,shell会显示一个新的pasha@skynet:~$提示行。
另一个进程是子进程,从fork返回零的程序运行,比如shell -> fork() -> exec(sudo) -> exec(./a.out) -> fork() -> exec(bash)。子进程是bash,它打印root@skynet:~# (它在sudo之后运行)并等待输入。
这两个进程同时运行-即。您的bash (在其中执行sudo ./a.out)和新的shell从您的程序运行。这两个程序都试图同时读取和写入相同的输入和输出。
子进程,即。bash,需要对终端中的输入进行独占控制。因此,子进程bash执行tcsetpgrp。但是您的shell是控制您的终端的shell,而不是子进程。因此,子进程要么接收signal SIGTTOU,要么在尝试从输入读取时接收SIGTTIN。然后,子bash执行信号的默认处理程序-它终止。
从您的shell运行sudo bash &将导致与您的程序类似的问题。
发布于 2020-05-01 17:20:37
您的程序是正确的;尝试使用"ls“而不是"bash",
$ ./a.out ls -al /tmp它似乎不适用于bash的原因是,bash希望流程成为的组长,但事实并非如此。
也就是说,虽然程序是正确的,但它严重缺乏错误处理是令人不快的:-)。例如,当调用一个不存在的程序时,execvp()返回一个错误(而不是根本不返回),该错误被忽略。其效果是...好吧..。你只能猜测它是否有效。
$ ./a.out frobozzzzz
$ # (hm)这是我的化身。更长。处理错误。看看孩子生完孩子后的结果。
#include <assert.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
int main(int argc, char** argv)
{
int status;
pid_t pid, terminated;
pid = fork();
if (pid == -1 /*unlikely*/) {
perror("fork()");
exit(EXIT_FAILURE);
}
if (pid == 0 /*child*/) {
if (execvp(argv[1], &argv[1]) != 0) { // when argv[1] is no
// progrm in path
perror("execvp()");
exit(EXIT_FAILURE);
}
else
assert(!"not getting here because successful exec() never returns");
}
// optional: wait for child to terminate, and print diagnostics
terminated = waitpid(pid, &status, 0);
if (terminated == -1) {
perror("waitpid()");
exit(EXIT_FAILURE);
}
if (terminated == pid) { // how come those not be equal?
if (WIFEXITED(status))
fprintf(stderr, "child terminated with exit status %d\n", WEXITSTATUS(status));
else if (WIFSIGNALED(status))
fprintf(stderr, "child terminated by %d\n", WTERMSIG(status));
else
fprintf(stderr, "see \"man waidpid\" for what that could be\n");
}
return 0;
}https://stackoverflow.com/questions/61525002
复制相似问题