【问题标题】:infinite loop when using execvp and fork in a while loop在while循环中使用execvp和fork时的无限循环
【发布时间】:2019-04-20 15:22:34
【问题描述】:

我正在尝试编写一个小型 shell 程序,我希望它在调用另一个程序后保持活动状态(通过execvp())。我希望fork 系统调用“复制”该进程,创建发行(父)进程的几乎相同的副本(子)。因此,当父级因excevp() 调用而终止时,子级仍然活着。

在我附在下面的代码中,我读取了一个用户输入(要执行的程序和参数),然后我希望父 fork 将执行该程序,而子 fork 将等待用户的下一个输入,但之后第一次插入输入(要执行的程序及其参数)时,程序陷入无限循环。当子 fork 获得控制权时,它会执行前一个程序并且不等待新的输入(好像在第一个 fgets() 之后它不再等待用户输入)。

这是代码中存在问题的部分:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "LineParser.h"
#include <limits.h>
#include <unistd.h>

char buf[PATH_MAX];
char buf_user[2048];
int pid;

void execute(cmdLine* pCmdLine) {
   int pid = fork();
   if(pid != 0) {
     printf("I'm the parent.\n");
       if(execvp(pCmdLine->arguments[0], pCmdLine->arguments) == -1) {
         perror("execute failed");
         _exit(1);
       }
   } else {
     freeCmdLines(pCmdLine);        
   }
}

int main(int argc, char *argv[])
{  
    while(1) {
        getcwd(buf, PATH_MAX);
        printf("%s> ", buf);
        fgets(buf_user, 2048, stdin);
        fflush(stdin);
        if(strcmp(buf_user, "quit\n") == 0) {
            exit(0);
        }
        cmdLine* parsedCmd = parseCmdLines(buf_user);
        execute(parsedCmd);
    }
    return 0;
}

cmdLine结构:

#define MAX_ARGUMENTS 256

typedef struct cmdLine
{
    char *const arguments[MAX_ARGUMENTS]; /* command line arguments (arg 0 is the command) */
    int argCount;       /* number of arguments */
    char const *inputRedirect;  /* input redirection path. NULL if no input redirection */
    char const *outputRedirect; /* output redirection path. NULL if no output redirection */
    char blocking;  /* boolean indicating blocking/non-blocking */
    int idx;                /* index of current command in the chain of cmdLines (0 for the first) */
    struct cmdLine *next;   /* next cmdLine in chain */
} cmdLine;

/* Parses a given string to arguments and other indicators */
/* Returns NULL when there's nothing to parse */ 
/* When successful, returns a pointer to cmdLine (in case of a pipe, this will be the head of a linked list) */
cmdLine *parseCmdLines(const char *strLine);    /* Parse string line */

/* Releases all allocated memory for the chain (linked list) */
void freeCmdLines(cmdLine *pCmdLine);       /* Free parsed line */

/* Replaces arguments[num] with newString */
/* Returns 0 if num is out-of-range, otherwise - returns 1 */
int replaceCmdArg(cmdLine *pCmdLine, int num, const char *newString);

【问题讨论】:

  • 我不确定这是否是你唯一的问题,因为你没有展示你的整个程序,但你应该让 child 成为打电话给@987654328 的人@,并且您应该让父调用waitpid,因此在调用的程序完成之前它不会继续读取另一行输入。
  • @zwol 可以,谢谢!但是,为什么在它们之间切换会使其工作?
  • 这很复杂,我不能 100% 确定到底出了什么问题。但我认为它的要点是当你运行这个程序时,有另一个程序(你的“shell”或你的 IDE)启动它并等待它完成。一旦父进程退出,它就会收到您的程序已完成的通知。然后它和孩子都试图同时从同一个地方读取输入并相互绊倒。

标签: c fork execvp


【解决方案1】:

您不应该在父级中执行vp,而应在子级中执行。

您的终端等待父母完成。完成父进程而不等待它的子进程结束会导致 zombie process

修改您的代码以便在子进程中执行命令并等待它在父进程中完成在我测试时解决了您的问题。

我建议你阅读ma​​n 3 wait

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-29
    • 2015-06-25
    • 2012-12-24
    • 2013-02-22
    • 2011-11-19
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    相关资源
    最近更新 更多