【问题标题】:WAIT does not wait for childWAIT 不等待孩子
【发布时间】:2012-09-10 01:31:37
【问题描述】:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>

char *getdir()  /*find working directory*/
{
  char *buffer;/*buffer is going to be used in getcwd function to get the current directory*/
  char *path_buffer;//path_buffer is going to contain the directory//
  long maxsize = pathconf(".", _PC_PATH_MAX);/* we set maxsize as the maximum pathname length*/
  if((buffer=(char*) malloc((size_t)maxsize))!=NULL)
    {
      path_buffer=getcwd(buffer,maxsize); /*get the current directory*/
      printf("\nMy working directory = %s",path_buffer);
      return path_buffer;
    }
  else{
    exit(-1);
  }
}

char * getcmline() /*get command from stdin by the user*/
{
  int bytes_read;
  int nchars=200;/*max possible number for the input of the user*/
  int nbytes=(sizeof(char))*nchars; /*size of chars in bytes*/
  char *line=(char*) malloc(nbytes+1);
  bytes_read=getline(line,&nbytes,stdin);/*read line from stdin*/
  if(bytes_read == -1){
    printf("Read line error");
    exit(-1);
  } /*error handling for bytes_read*/
  else{
    if(line[strlen(line)-1]=='\n')
      {
        line[strlen(line)-1]='\0'; /*change new line character in the end of the line of stdin*/
      }
  }
  return line;
}

int main(void)
{
  pid_t pid,child_pid;
  int rv=0;
  char* exit_string="exit";
  char *path_buffer=NULL;
  int nchars=200;
  int nbytes=(sizeof(char))*nchars;
  char *line=malloc(nbytes+1);
  char *commands[2];
  while(1){
    switch(pid = fork())
      {
      case -1:
        perror("fork"); /* something went wrong */
        exit(1);
      case 0:
        printf(" CHILD: This is the child process!\n");
        child_pid=getpid();
        printf(" CHILD: My PID is %d\n", child_pid);
        path_buffer=getdir();/*get the directory path*/
        line=getcmline();/*get a command by the user*/
        if(strcmp(line,exit_string)==0)
          {
            rv=3;
            exit(rv);
          }
        commands[0]=line;
        commands[1]=NULL;
        execvp(commands[0],commands);
        perror("Execution error");
        exit(-1);



      default:
        waitpid(-1, &rv, 0);
        if(WIFEXITED(rv)){
          printf("Child exited normally and child's exit status is: %d\n", WEXITSTATUS(rv));
          if((WEXITSTATUS(rv))==3){
            exit(1);
          }
        }
      }
  }
  return 0;
}

我在getlinerv 中进行了更改,并为execvp 创建了一个适当的变量。但是现在发生的错误是在我输入例如“ls”之后。它说:

执行错误:没有这样的文件或目录。

再次感谢您的帮助和我缺乏的知识。

错误似乎在行变量中,但我无法理解问题所在!

Char Array and getline in C

这里给出了解决方案。它应该是 line[(strlen)-1] 而不是 line[(strlen-1)]

【问题讨论】:

  • 请正确缩进。这里的逻辑很难理解。
  • 添加case 0的代码。没关系。
  • 这不是不正确缩进和格式化代码的借口,尤其是在您需要帮助时。
  • 对,我为你缩进了代码。您实际上看到了什么问题?
  • 感谢@Useless。我收到了 5 个警告......我将它们包括在上面......

标签: c fork wait pid


【解决方案1】:

父母永远不会得到孩子的 pid,因此 waitpid 不会等待它。 waitpid(-1,...) 将等待所有子进程完成后再继续。

我还建议缩进 case 并以 break 结束每个 case 语句;

【讨论】:

  • 即使使用相同的 waitpid(-1,&rv,0) 或 wait(&rv) ,它也不会等待。它还会在等待后更改 rv 的值。
  • 它在wait之后改变rv的值而不是waitpid()?
  • 在默认部分的 wait(&rv) 或 waitpid(-1,&rv,0) 之后,rv 值被更改。
  • 所以它确实在等待它?你有一个返回值,不是吗?
【解决方案2】:

所以,对于警告:你知道这些数字指的是什么行,我不得不猜测:你可以让这更容易!

int rv=NULL;

初始化从没有强制转换的指针生成整数 [默认启用] 第 42 行

NULL 是一个指针值,rv 是一个整数。如果您是这个意思,请将其设置为 0

execvp(line[0],line);

传递“execv”的参数 1 使指针从没有强制转换的整数 [默认启用] 第 64 行 从不兼容的指针类型[默认启用]第 64 行传递“execv”的参数 2

如果您调用execv,则您正在编译的代码不是您发布的。然而...linechar *,所以line[0]charexecvexecvp 的第一个参数是 const char *

execv 试图完成什么?它需要一个程序名来运行(第一个参数,const char *)和一个参数数组(这些将形成argv[]数组传递给新程序的main函数,数组中的最后一项必须为NULL) .

char *line=(char*) malloc(nbytes+1);
bytes_read=getline(&line,&nbytes,stdin);/*read line from stdin*/

从不兼容的指针类型[默认启用]第 29 行传递“getline”的参数 2

getline 需要缓冲区的地址才能将字符放入... line 这样的地址。但是,&amp;line指针的地址。只需取出&amp;


您的代码中存在更多问题,但这些警告都有一些共同点:

  • 您似乎不了解函数需要什么类型,
  • 你的变量是什么类型,
  • 您实际传递的是什么类型,
  • 或者当编译器抱怨你的类型不匹配时是什么意思

您需要在开始尝试编写多进程程序之前了解这一点。用一些简单的东西来学习它,学习阅读文档,并理解编译器警告。

【讨论】:

  • 感谢您的帮助。所以我设置 int rv=0;我创建了一个 char* commands[2];命令[0]=行;命令[1]=NULL;但在 getline 中,警告在第二个参数中。还有crasseux.com/books/ctutorial/getline.html它说第一个参数是一个指向块的指针......我再次编辑了代码以最终得到我做错的事情。
  • 当前代码看起来好多了!因此,现在您已成功构建,并且在运行时您的 exec 调用抱怨它找不到您希望它运行的程序。 execvp 应该在您的 PATH 环境变量中搜索它 - 确保它在那里。 execv 不搜索PATH,因此您需要提供程序的绝对路径,例如。 /bin/ls
  • 问题出在 if(line[strlen(line-1)]=='\n') { line[strlen(line-1)]='\0'; /*改变stdin行尾的换行符*/ }
【解决方案3】:
default:
waitpid(child_pid, &status, 0);
//wait(&rv);
printf("PARENT:My child's exit status is: %d\n", WEXITSTATUS(rv));
if((WEXITSTATUS(rv))==3){exit(1);}

您将未初始化的变量child_pid 传递给waitpid,该变量仅在子进程中设置。你应该通过pid。使用未初始化的变量会导致未定义的行为,因此无法预测会发生什么。你也可以用另一个未初始化的变量rv 调用WEXITSTATUS,你应该在那里传递status

孩子在这里什么都不做,因为

path_buffer=getcwd(buffer,sizeof(buffer));

传递给getcwd 的size 参数是char* 的大小,通常是4 或8 个字节,对于大多数目录的绝对路径来说太短了,path_buffer is set toNULLand the child immediately exits. You should pass the size of the buffer,maxsize` 那里。

【讨论】:

  • 编辑:没关系,我是个白痴。如果他通过-1,它将等待子进程。
  • Err, switch(pid = fork()) {, fork 如果成功则返回孩子的 PID。当然-1也是不错的选择。
  • 啊,对,我的错。如果我不是 100% 专注,叉子仍然让我感到困惑。 :P
  • 我改变了状态。那是一个错误。 rv 是等待中的变量。但即使使用 waitpid(-1,...) 它也不会等待...
  • @ThemisMavridis 孩子立即退出,看我的更新,所以wait 立即返回。
猜你喜欢
  • 1970-01-01
  • 2021-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-19
  • 1970-01-01
相关资源
最近更新 更多