Fork() 和 Wait() 与 C 中的 execvp()
Fork() and Wait() with execvp() in C
我正在尝试使用 fork 方法调用不同的程序并等待它完成,
我试图检查问题是什么,似乎等待函数没有等待 childReturns 并且它不打印答案。
(分配是循环比较方法直到 ctrl+c )
我调用的程序是比较 2 个字符串的比较器。
问题是等待函数不等待 child
编译是 GCC
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/wait.h>
#define LINELEN (80)
char *mygets(char *buf, int len);
char *progName(char *prog);
int main(int argc, char *argv[])
{
char *args[3];
char str1[LINELEN + 1];
char str2[LINELEN + 1];
int childReturns;
if (argc != 2)
return -1;
char *prog = progName(argv[1]);
if (prog == NULL)
return -1;
args[0] = prog;
while (1)
{
printf("Enter string:");
if (mygets(str1, LINELEN) == NULL)
break;
printf("Enter string:");
if (mygets(str2, LINELEN) == NULL)
break;
args[1] = str1;
args[2] = str2;
int processId = fork();
if (processId == 0)
execvp(prog, args);
else
{
wait(&childReturns); // Wait for the child
printf("Child code is %d\n", WEXITSTATUS(childReturns));
}
}
free(prog);
return 0;
}
char *progName(char *prog)
{
char *filePath = (char *)malloc(strlen(prog) + 3);
if (!filePath)
return NULL;
strcpy(filePath, "./");
strcat(filePath, prog);
return filePath;
}
char *mygets(char *buf, int len)
{
char *retval;
retval = fgets(buf, len, stdin);
buf[len] = '[=10=]';
if (buf[strlen(buf) - 1] == 10) /* trim \r */
buf[strlen(buf) - 1] = '[=10=]';
else if (retval)
while (getchar() != '\n')
; /* get to eol */
return retval;
} ```
fork()
系统调用复制了母进程。生成的子进程和父进程将拥有自己的地址空间。所以子进程不能修改父进程的childReturns
变量。
此外,wait(NULL)
等待子进程结束。
尝试链接这些行:
if (processId == 0)
execvp(prog, args);
else
致这些:
if (processId == 0) {
execvp(prog, args);
perror(prog);
abort();
} else
另请注意,WEXITSTATUS 仅在 WIFEXITTED() 为真时才有效。在这种情况下,当您的 child 处理 abort() 时,它不会成立。
所以
wait(&childReturns); // Wait for the child
printf("Child code is %d\n",
需要更多的工作,例如:
if (WIFEXITTED(childReturns)) {
printf("Child code is %d\n", WEXITSTATUS(childReturns));
} else if (WIFSIGNALED(childReturns)) {
printf("Child killed by signal %d\n", WTERMSIG(childReturns);
} else {
printf("Child suffered %#x\n", childReturns);
}
但是,您真正的问题是为什么 execvp() 会失败?仔细看看你的 args 数组有多大。它与文档相符吗?
正如 Jonathan Leffler 所说,问题出在 args 上,execvp()
需要 args 的数组最后 NULL
。
这解决了问题。
正确的代码:
char str1[LINELEN + 1];
char str2[LINELEN + 1];
int childReturns = 1;
if (argc != 2)
return -1;
char *prog = progName(argv[1]);
if (prog == NULL)
return -1;
char *args[4];
args[3] = NULL;
args[0] = prog;
while (1)
{
printf("Enter string:");
if (mygets(str1, LINELEN) == NULL)
break;
printf("Enter string:");
if (mygets(str2, LINELEN) == NULL)
break;
args[1] = str1;
args[2] = str2;
int processId = fork();
if (processId == 0)
{
execvp(prog, args);
}
else
{
wait(&childReturns); // Wait for the child
printf("Child code is %d\n", WEXITSTATUS(childReturns));
}
}
free(prog);
return 0;```
我正在尝试使用 fork 方法调用不同的程序并等待它完成, 我试图检查问题是什么,似乎等待函数没有等待 childReturns 并且它不打印答案。 (分配是循环比较方法直到 ctrl+c )
我调用的程序是比较 2 个字符串的比较器。
问题是等待函数不等待 child 编译是 GCC
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/wait.h>
#define LINELEN (80)
char *mygets(char *buf, int len);
char *progName(char *prog);
int main(int argc, char *argv[])
{
char *args[3];
char str1[LINELEN + 1];
char str2[LINELEN + 1];
int childReturns;
if (argc != 2)
return -1;
char *prog = progName(argv[1]);
if (prog == NULL)
return -1;
args[0] = prog;
while (1)
{
printf("Enter string:");
if (mygets(str1, LINELEN) == NULL)
break;
printf("Enter string:");
if (mygets(str2, LINELEN) == NULL)
break;
args[1] = str1;
args[2] = str2;
int processId = fork();
if (processId == 0)
execvp(prog, args);
else
{
wait(&childReturns); // Wait for the child
printf("Child code is %d\n", WEXITSTATUS(childReturns));
}
}
free(prog);
return 0;
}
char *progName(char *prog)
{
char *filePath = (char *)malloc(strlen(prog) + 3);
if (!filePath)
return NULL;
strcpy(filePath, "./");
strcat(filePath, prog);
return filePath;
}
char *mygets(char *buf, int len)
{
char *retval;
retval = fgets(buf, len, stdin);
buf[len] = '[=10=]';
if (buf[strlen(buf) - 1] == 10) /* trim \r */
buf[strlen(buf) - 1] = '[=10=]';
else if (retval)
while (getchar() != '\n')
; /* get to eol */
return retval;
} ```
fork()
系统调用复制了母进程。生成的子进程和父进程将拥有自己的地址空间。所以子进程不能修改父进程的childReturns
变量。
此外,wait(NULL)
等待子进程结束。
尝试链接这些行:
if (processId == 0)
execvp(prog, args);
else
致这些:
if (processId == 0) {
execvp(prog, args);
perror(prog);
abort();
} else
另请注意,WEXITSTATUS 仅在 WIFEXITTED() 为真时才有效。在这种情况下,当您的 child 处理 abort() 时,它不会成立。 所以
wait(&childReturns); // Wait for the child
printf("Child code is %d\n",
需要更多的工作,例如:
if (WIFEXITTED(childReturns)) {
printf("Child code is %d\n", WEXITSTATUS(childReturns));
} else if (WIFSIGNALED(childReturns)) {
printf("Child killed by signal %d\n", WTERMSIG(childReturns);
} else {
printf("Child suffered %#x\n", childReturns);
}
但是,您真正的问题是为什么 execvp() 会失败?仔细看看你的 args 数组有多大。它与文档相符吗?
正如 Jonathan Leffler 所说,问题出在 args 上,execvp()
需要 args 的数组最后 NULL
。
这解决了问题。
正确的代码:
char str1[LINELEN + 1];
char str2[LINELEN + 1];
int childReturns = 1;
if (argc != 2)
return -1;
char *prog = progName(argv[1]);
if (prog == NULL)
return -1;
char *args[4];
args[3] = NULL;
args[0] = prog;
while (1)
{
printf("Enter string:");
if (mygets(str1, LINELEN) == NULL)
break;
printf("Enter string:");
if (mygets(str2, LINELEN) == NULL)
break;
args[1] = str1;
args[2] = str2;
int processId = fork();
if (processId == 0)
{
execvp(prog, args);
}
else
{
wait(&childReturns); // Wait for the child
printf("Child code is %d\n", WEXITSTATUS(childReturns));
}
}
free(prog);
return 0;```