我写了一个非常基本的shell,出于某种原因,当我使用fork()然后waitpid()时,父进程不会等待子进程。
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <linux/limits.h>
#include "LineParser.h"
#include <termios.h>
#define MAX_STR 2048
void execute(cmdLine *pCmdLine);
int main()
{
char isContinuing = 1;
char path[PATH_MAX];
char str[MAX_STR];
char something[MAX_STR+PATH_MAX];
cmdLine* cmd;
while(isContinuing)
{
getcwd(path, PATH_MAX);
printf("%s$ ", path);
fgets(str, MAX_STR, stdin);
if(!strncmp(str, "quit", strlen("quit")))
{
isContinuing = 0;
}
else
{
cmd = parseCmdLines(str);
if(cmd->arguments != '\0')
{
execute(cmd);
}
}
}
freeCmdLines(cmd);
return 0;
}
void execute(cmdLine *pCmdLine)
{
pid_t id = fork();
if(id == 0)
{
printf("I AM CHILD.\n");
if(!execvp(pCmdLine->arguments[0], pCmdLine->arguments))
{
perror("execvp failed.\n");
exit(1);
}
exit(0);
}
printf("I AM PARENT.\n");
printf("WAITING FOR CHILD.\n");
waitpid(id);
printf("DONE WAITING\n");
}
LineParser头文件是我的,它完全正常工作。 现在,出于某种原因,只有第一个命令按预期工作, 我们假设输入“echo hi”,输出为:
I AM PARENT.
WAITING FOR CHILD.
I AM CHILD.
DONE WAITING.
按预期然后打印“hi”和路径,再次等待命令。 出于某种原因,当我第二次输入SAME输入“echo hi”时,输出为:
I AM PARENT.
WAITING FOR CHILD.
DONE WAITING.
$PATH$ //(WITHOUT WAITING FOR INPUT !!!)
I AM CHILD.
hi
//and here waiting for input//
为什么会这样?
答案 0 :(得分:1)
通过使用错误数量的参数调用waitpid()
函数来调用未定义的行为。任何事情都可能发生。
这个简化的代码变体对我来说很好用:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main ()
{
int i;
for (i = 0; i < 3; i += 1)
{
pid_t id = fork();
if(id == 0)
{
char *argv[] = { "echo", "hi", NULL };
printf("I AM CHILD.\n");
execvp("echo", argv);
/* failed to exec */
perror("execvp failed.\n");
exit(1);
} else if (id < 0) {
perror("fork failed.\n");
exit(1);
}
printf("I AM PARENT.\n");
printf("WAITING FOR CHILD.\n");
waitpid(id, NULL, 0);
printf("DONE WAITING\n");
}
return 0;
}
答案 1 :(得分:1)
您的代码存在一些问题:
while
循环exit()
语句waitpid()
功能something
fgets
函数#include
所以这是一个可编译的代码版本。编译器发现原始代码存在许多问题。
#include
答案 2 :(得分:0)
您对waitpid(2)
的来电是错误的。
根据man 2 waitpid
,它是:
pid_t waitpid(pid_t pid, int *status, int options);
您可能需要定义int
并将其命名为:
waitpid(id, &status, 0);
或使用更简单的版本wait(2)
,它适用于任何孩子:
wait(&status);
答案 3 :(得分:0)
您的主要问题是您不要让编译器检查您的代码。您通常应该启用编译器警告并尝试理解它们。
$ gcc -Wall -Wextra -Werror -Os -c myshell.c
这是我使用的最小命令行。当您的代码使用这些设置进行编译时,您已经消除了代码中一堆难以发现的错误。正如其他人已经提到的那样,这些错误包括对waitpid
的调用。
看看http://pubs.opengroup.org/onlinepubs/7908799/xsh/waitpid.html。在使用#include
函数之前,Open Group规范要求您<sys/types.h>
两个标头<sys/wait.h>
和waitpid
。你的程序没有这样做。