【问题标题】:Trouble with status of pid after waitpid in my own implemented shell在我自己实现的 shell 中 waitpid 后 pid 的状态出现问题
【发布时间】:2015-12-30 12:38:59
【问题描述】:

我正在尝试实现我自己的 shell 作为家庭作业。在 shell 中,我需要一个名为“status”的新命令,它显示 pids 的当前状态,例如:

当我输入时它必须显示

myshell>>状态

PID PGID 状态程序

1412 1412 密码退出(0)

1454 1454 /opt/firefox/bin/firefox 正在运行

1462 1462 ls 退出(1)

1463 1463 xterm 停止

但是在我的 shell 中,我没有退出进程的子进程错误,它为停止的进程写入了 signaled(29)。You can see my output from here

这是我的进程列表结构

typedef struct 
{
  pid_t ppid;
  pid_t ppgid;
  char *prog;
  char status[30];
}Process;

这是我执行新进程的分支:

if(forkexec){
    int pid=fork();
    iterator=iterator+1;
    processList[iterator].prog=ptr;
    processList[iterator].ppid=pid;
    processList[iterator].ppgid=getpgid(pid); 
    strcpy(ptr,worte[0]);

    switch (pid){
    case -1:
      perror("Fehler bei fork"); 
      return(-1);
    case 0: //child process

      if(umlenkungen(k))
    exit(1);
      if(!setpgid(0, 0))
      {
        do_execvp(k->u.einfach.wortanzahl, k->u.einfach.worte); //for executing program
      }

      abbruch("interner Fehler 001"); //error
    default: //parent process
      if(k->endeabwarten){
        if(!setpgid(pid, 0))
        {
          tcsetpgrp(0,getpgid(pid));
          waitpid(pid, NULL, WUNTRACED);
          tcsetpgrp(0,getpgid(shellpid));
        }

      }
      return 0;
    }
  }

在子进程中调用do_execvp函数:

void do_execvp(int argc, char **args){
  if(execvp(*args, args)==-1)
  {
   perror("exec-Fehler");
  fprintf(stderr, "bei Aufruf von \"%s\"\n", *args);
  exit(1); 
  } 
}

对于我拥有的新状态命令,这意味着如果用户输入状态,这部分将运行:

if (strcmp(worte[0], "status")==0) { 
    int i;
    fputs("PID: PGID: PROGRAM: STATUS: \n",stdout);
    for(i=0; i<=iterator; i++)
      {
      find_status(i);
      printf("%d %d %s %s\n", processList[i].ppid,processList[i].ppgid,processList[i].prog,processList[i].status);
      }
      return 0;
  }

当我使用上面的代码迭代进程列表以打印时,我还调用 find_status 函数:

void find_status(int current)  

{
  pid_t w;
  int status;
  char stat[30];

  w=waitpid(processList[current].ppid, &status, WNOHANG | WUNTRACED | WCONTINUED);

  switch(w){
      case -1: 
      strcpy(stat, "No child process");
      break;

      case 0:
         strcpy(stat,"running");
      default:
            if (WIFEXITED(status)!=0) {
                sprintf(stat, "exit(%d)", WEXITSTATUS(status));
            } else if (WIFSIGNALED(status)!=0) {
                sprintf(stat, "signaled(%d)", WTERMSIG(status));
            } else if (WIFSTOPPED(status)!=0) {
                strcpy(stat,"stopped");
            } 
      break;
  }
  strcpy(processList[current].status, stat);
}

顺便说一句,迭代器变量是全局变量,它保存进程列表中最后一个元素的索引。进程列表也是全局变量。那么,我在代码中的错误在哪里,为什么它没有显示退出和停止进程的状态?谢谢。

【问题讨论】:

    标签: c linux gnu


    【解决方案1】:

    由于您没有显示所有代码,因此无法确定,但我推测您已经等待这些进程。

    在您的 fork 代码中,父分支(默认情况)有一个 waitpid 调用。该代码是否正在执行?一旦您成功等待子进程(至少一个实际上已经退出),它将从内核进程表中删除,并且您以后不能(成功)再次调用waitpid:它不再存在。

    要了解到底发生了什么,您应该在waitpid 失败时打印errno 值(更好的是,打印strerror(errno),这样您就不必查找errno 值)。这将准确地告诉您为什么 waitpid 失败,而不仅仅是它失败了。

    【讨论】:

      猜你喜欢
      • 2021-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-02
      • 2013-01-11
      • 1970-01-01
      相关资源
      最近更新 更多