有分叉过程的问题

时间:2017-03-01 22:57:52

标签: c++ unix process fork

所以我正在为我的一个类写一个UNIX shell,基本上我接受一个参数,如果参数有'&'在它结束时,我需要父进程来调用wait();。

我的问题是程序应该接受输入,直到我输入exit,所以一切都在'while'循环中。在我用'&'调用命令之前,事情一直很顺利在它结束时,然后我可以看到父进程结束,然后子进程结束,但后来我不正常接受输入“osh>”。

所以基本上这是我运行简单命令时的正常输出:

osh> ls -l
child:0
a.out  main  main.cpp  main.cpp~
parent: 8695 

但是当我用'&'运行命令时最后会发生这种情况:

osh> ls -l &
parent: 27082
osh> child:0
total 44
-rwxr-xr-x 1 myuser users 10368 Mar  1 14:46 a.out
-rwxr-xr-x 1 myuser users 23368 Mar  1 14:00 main
-rw-r--r-- 1 myuser users  1658 Mar  1 14:46 main.cpp
-rw-r--r-- 1 myuser users  1676 Mar  1 14:45 main.cpp~
<cursor is here accepting commands, but no osh> prompt>

如果有人有任何意见或建议,将不胜感激。我觉得这只是一个小错误,但我已经多次通过调试器,找不到任何东西。我只是没有那么多经验。以下是完整的代码:

#include <stdio.h>
#include <unistd.h>
#include <iostream>
#include <string.h>
#include <string>
#include <cstring>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>

#define MAX_LINE 80 //the maximum length command

using namespace std;

int main()
{
  char* args[MAX_LINE/2 + 1]; //command line arguments
  char str[41]; //intitialize string for input
  int should_run = 1; //flag to determine when to exit program
  bool status; //status of whether or not an ampersand is in the passed argument

  while (should_run) {
    int index = 0;

    cout << "osh> ";
    fflush(stdout);

    cin.getline(str, 41);

    args[index] = strtok(str, " ");

    while (args[index] != NULL) {
      index++;
      args[index] = strtok(NULL, " ");
    }

    if (strcmp (args[0], "exit") == 0) //in input is "exit", exit the while loop
      break;

    if (*args[index - 1] == '&') //check whether to run processes concurrently
      status = true;

    args[index - 1] = NULL; //remove & to make sure arguments are valid

    // (1) fork a child process using fork()
    pid_t pid = fork();

    if (pid < 0) { //error handling
      perror("Fork Failed.");
      break;
      }
    // (2) the child process will invoke execvp()
    if (pid == 0) {
      //child process
      cout << "child:" << pid << endl;
      if ( execvp (args[0], args) == -1 ) {
        perror ("exec");
      }
    }

    // (3) if command didn't included &, parent will invoke wait()
    //parent process
    if (pid > 0) {
        // parent process
       if (!status) {
         wait(0);
         }
       cout << "parent: " << pid << endl;
    }
  }

  return 0;
}

编辑:也刚刚意识到在我发布的第二个输出中,它显示“osh&gt;”在父进程之后第二次,不知道如何描述该错误。

1 个答案:

答案 0 :(得分:3)

不,您已经在命令提示符下:

osh> child:0
total 44

这是你的命令,提示,osh>提示。

您的问题在于,您的计算机正在完全按照您要求它执行的操作,而不是您希望它执行的操作。你的代码(它有一个不相关的主要错误,我将在那一刻得到)说不要等到子进程完成,并继续,如果输入&

而这正是发生的事情。子进程已启动,您的父进程立即发出下一个osh>提示符。并且,它在子进程甚至进行了更改以产生任何输出之前就这么快。因此,在osh>提示符后,子进程的输出将显示在终端上。由于你的父进程已经产生了它的提示,它现在正在等待你的下一个输入,它没有理由不继续等待,在子进程终止后,并完成产生它的输出。

这回答了你的提示发生了什么的问题。你没有解释你预期会发生什么,所以没有什么可以说的;但是如果您想再次重新发出提示,则在子进程终止后,您可以通过正确处理SIGCHLD信号来实现。有关更多信息,请参阅您的C ++书籍。

就你的无关错误而言,实际上是两个错误:

if (*args[index - 1] == '&')
  status = true;

args[index - 1] = NULL; //re

第一个错误:任何以'&'开头的内容,而不仅仅是“&amp;”它本身将触发后台工作行为。

第二个错误:如果未输入'&',此代码仍将删除输入的最后一个单词。这就是为什么当您输入命令ls -l时,您最终执行ls,并从第一个命令获得结果输出。