Linux, waitpid, WNOHANG and zombies
Linux, waitpid, WNOHANG and zombies
我需要能够:
- 派生一个进程并使其成为execvp(我就是这么做的)
- 检查子进程execvp是否成功(不知道如何)
- 检查子进程是否已完成(存在问题)
我正在分叉一个进程,我没有任何方法来检查子进程的execvp是否工作或失败。如果它失败了,我需要知道它失败了。目前我正在使用
-1 != waitpid( pid, &status, WNOHANG )
但是,如果pid进程的execv失败,waitpid似乎不会返回-1。
我该怎么查?我读了等待的人页,但我不清楚;也许我的英语不够好。
编辑:为了解释更多:
我正在为家庭作业建造自己的终端。我需要获得一个命令字符串作为输入,比如说"ls",然后我必须执行该命令
在子分叉之后,子调用execvp以执行命令(在我解析字符串之后),父需要检查是否存在'&'是否在命令结束时
如果符号"&"不存在,则父级需要等待子级执行。
所以我需要知道execvp是否失败了。如果没有失败,则父级使用waitpid等待子级完成执行。如果失败,则父级将不会等待子级。
#2的一个常见解决方案是在fork()之前打开一个管道,然后在exec之后的子级中写入。在父级中,成功读取表示exec失败;读取失败意味着exec成功,而写入从未发生。
// ignoring all errors except from execvp...
int execpipe[2];
pipe(execpipe);
fcntl(execpipe[1], F_SETFD, fcntl(execpipe[1], F_GETFD) | FD_CLOEXEC);
if(fork() == 0)
{
close(execpipe[0]);
execvp(...); // on success, never returns
write(execpipe[1], &errno, sizeof(errno));
// doesn't matter what you exit with
_exit(0);
}
else
{
close(execpipe[1]);
int childErrno;
if(read(execpipe[0], &childErrno, sizeof(childErrno)) == sizeof(childErrno))
{
// exec failed, now we have the child's errno value
// e.g. ENOENT
}
}
这让父级明确地知道exec是否成功,以及作为副产品,如果不成功,errno值是多少。
如果exec成功,则子进程可能仍会失败,并返回退出代码,使用WEXITSTATUS
宏检查状态也会给出该条件。
注意:使用WNOHANG
标志调用waitpid
是非阻塞的,您可能需要轮询进程,直到返回有效的pid。
如果exec调用成功,则根本不应返回,因为它将用另一个进程映像替换当前进程映像,因此如果返回,则意味着发生了错误:
execvp(...);
/* exec failed and you should exit the
child process here with an error */
exit(errno);
要让父进程知道exec
是否失败,您应该读取子进程的状态:
waitpid(pid, &status, WNOHANG);
然后使用WEXITSTATUS(status)
宏,从手册页:
WEXITSTATUS(status)返回子级的退出状态这个由状态自变量的最低有效8位组成在对exit(3)或_exit(2)的调用中指定的子级,或在main()中指定为return语句的参数
请注意,最后一条语句意味着,如果exec
成功并运行该命令,您将获得该命令的main()
函数的退出状态,换句话说,您无法通过这种方式可靠地区分失败的exec
和失败的命令,所以这取决于您是否对此感兴趣。
另一个问题:
如果符号'&'不存在于命令末尾,则父级需要等待子级执行。
您需要在程序中的某个时刻调用子进程上的wait()
,而不考虑&
,以避免使子进程处于僵尸状态,
注意:当你使用WNOHANG
时,这意味着如果没有进程改变其状态,waitpid()
将立即返回,即它不会阻塞,我想你知道,否则使用wait()
或调用waitpid()
作为主循环的一部分。
- C++核心准则 C35 对于接口类"A base class destructor should be either public and virtual, or protected and nonv
- 为什么C++逐位AND运算符在不同大小的操作数中表现为这样
- 为什么 Clang 不允许"and"作为函数名称?
- 位阵列上的快速AND运算
- 是否可以在 C++03 中定义'move-and-swap idiom'等效项
- BoostPython and CMake
- OpenSSL BIO and SSL_read
- Gurobi GRBModel and GRBmodel in C++
- std::visit and std::variant usage
- SHBrowseForFolder with BIF_BROWSEFORCOMPUTER and SHGetPathFr
- Directx12 and keystrokes
- different between int **arr =new int [ n]; and int a[i][j]?
- C++ getenv and setenv
- Inference pytorch C++ with alexnet and cv::imread image
- Visual Studio 2019 C++ and std::filesystem
- 保证逻辑 AND 表达式中的函数调用
- python ctypes and C++ pointers
- C++ const char with .begin() and .end()
- Threads with Classes and std::packaged_task
- Linux, waitpid, WNOHANG and zombies