操作系统:Windows 11、WSL
Cp:GCC 11.4.0
硬件:英特尔
我有一个从 shell 程序中提取的示例。我正在尝试执行多个由 & '分隔'的程序。给定一个固定的字符串数组,这些字符串是有效的 bash,命令参数由“&”分隔,我应该能够并行分叉和执行所有单独的程序调用。不幸的是,我在分叉时遇到退出状态 0x3(无法打开指定的路径)。我不确定这是从哪里来的,也不知道为什么。
下面是我的原始程序的简化版本。首先,构建程序数组,然后将其传递给“execute_programs”函数,该函数将分叉并执行每个新的有效调用。对“execv”的调用可以忽略,但我保留它是为了显示完整的图片。在此示例中,仅发生一个分叉。我收到输出,
PID -1 的子进程退出,状态为 0x3。
我不明白为什么会发生这种情况。可能还有其他错误,但这个结果对我来说完全出乎意料且难以捉摸。我希望得到一些帮助。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>
int execute_programs(int argc, char *argv[])
{
int n = 0;
int cnt = 0;
int current_cnt = 0;
while (argv[cnt] != NULL && cnt < argc)
{
if (strcmp(argv[cnt], "&") == 0)
{
// Block the array.
argv[cnt] = NULL;
// Update variables.
n++; // Number of programs grows.
current_cnt = 0; // Number of current arguments goes back to zero.
if (current_cnt > 0) // There is an adequate number of child processes.
{
// Start child process.
pid_t rc;
if ((rc = fork()) < 0)
{
// There was an error.
abort();
}
else if (rc == 0)
{
// Run the i'th process.
// printf("%d\n", execv(argv[cnt - current_cnt], &argv[cnt]));
exit(0);
}
}
}
current_cnt++; // Increment number of current arguments.
cnt++; // Increment count;
}
/* Wait for children to exit. */
int status;
pid_t pid;
while (n > 0)
{
pid = wait(&status);
printf("Child with PID %ld exited with status 0x%x.\n", (long)pid, status);
--n;
}
// return;
return 0;
}
int main(int argc, char *argv[])
{
char *programs[5];
programs[0] = strdup("echo");
programs[1] = strdup("\"ah\"");
programs[2] = strdup("&");
programs[3] = strdup("ls");
programs[4] = NULL;
execute_programs(5, programs);
return 0;
}
编辑:“execv”调用被注释掉,因为我可能没有正确使用它。尽管如此,如果没有它,错误就会发生。给出了相同的错误消息。
您的代码有错误。您将
current_cnt
分配给 0,这会导致 fork()
和 execv()
无法到达。在我看来,current = 0;
应该移到if
子句的末尾。
current_cnt = 0;
if (current_cnt > 0) // can NOT reach below
{
// Start child process.
pid_t rc;
if ((rc = fork()) < 0) {
// There was an error.
abort();
} else if (rc == 0) {
// Run the i'th process.
printf("%d\n", execv(argv[cnt - current_cnt], &argv[cnt]));
exit(0);
}
}
如果失败,wait()
返回(pid_t)(-1)
,详细原因可以查看errno
。我在 WSL 中测试了您的代码,并且 errno
指出生成子进程失败。
#include <errno.h>
pid = wait(&status);
int err = errno;
printf("Error: %s\n", strerror(err)); // Error: No child processes