我最近一直在与以下概念作斗争,但我仍然无法理解。我有这段代码
int foo(int f){
int fail = 10; //some random initialization value
int status;
pid_t child_pid;
child_pid = fork();
if(child_pid == 0) {
/* This is done by the child process. */
if (execvp(tokens2[0], tokens2)<0){
fail =1;
perror(tokens2[0]);
exit(1);
}
}else if(child_pid<0){
perror("Fork failed");
exit(1);
} else {
waitpid(child_pid, &status, WUNTRACED);
}
//handle execvp error return value
if (fail == 1){
return -1;
}else{
return 0;
}
}
它没有多大意义(不要介意tokens2[]
数组,它已经正确声明并且可以正常工作),因为它是抽象形式的,以便可以听见且易于理解了解。问题是:函数foo
的输出是什么?这是到目前为止我得到的:
1)如果
execvp
成功,则不返回任何值。如果失败,它将返回-1
(我认为此返回值不必与我的foo
函数无关)。2)
exit(1)
杀死子进程并将控制流返回给父进程。
据我了解,如果execvp
成功,foo
应该返回-1
(根据变量fail
),如果失败,它应该返回0
,但这不是我的printf
在主要功能显示中检查的内容。实际上,结果总是与我期望的相反。
PS:我发现了一些关于execvp
的错误处理方法,这些错误处理方法使用了很好的 shelf-pipe 技巧,但对我来说太吵了。我想要一种更简单的方法来处理错误。
答案 0 :(得分:1)
问题是:函数foo的输出是什么?
您似乎在问foo()
的返回值是什么。 “输出”通常是指写入终端或外部文件的数据。但是问题仍然存在:在哪个过程中?假设fork()
成功,则您有两个实际上相同的进程,都执行foo()
。
1)If execvp succeeds, it does not return any value.
如果execvp()
成功,则完全不返回 。
如果失败,则返回-1(我认为此返回值不必执行任何操作 和我的foo函数)。
是的。但是,只有您的子进程执行execvp()
,并且在返回时,该进程最终会调用exit()
。
2)exit(1) kills the child process and returns the control flow to the parent.
那会在从foo()
返回之前终止该进程,因此在子进程foo()
中永远不会返回,无论execvp
是否成功。控件不会返回父级。派生进程与调用函数根本不同。父母可以通过进行的waitpid()
调用来了解孩子的退出代码。
在父级中,如果fork()
失败,则该过程也会调用exit()
,因此不会从foo()
返回。另一方面,假设fork()
成功,则父级等待直到子级终止。子进程是一个单独的进程,具有所有变量的自己的副本,因此,对其fail
副本所做的任何操作均不会对父进程产生影响。也就是说,派生子进程也不同于在同一进程中启动线程。
由于父级本身不会修改fail
,因此如果达到,父级仍具有其初始值10。
if (fail == 1){
10!= 1,所以如果foo()
返回,则返回0。
答案 1 :(得分:0)
execvp
用您exec
处理的过程覆盖整个过程。
如果execvp
成功,则fail
变量将不再存在于子级中。 foo
函数在子级中不再存在。子级中不再存在称为foo
的函数。如果execvp
成功,则孩子现在正在运行不同程序的 main
函数。
最终,该程序将退出,然后子进程退出。它永远不会回到您的程序。 (这就是为什么您需要创建一个单独的流程来调用execvp
的原因-如果您使用的是原始流程,就永远无法取回它)