子进程的过程和状态有问题

时间:2014-03-07 19:34:29

标签: c process

我无法理解什么是错的......它不会给我在父进程中执行程序返回的任何消息。有人可以解释并帮助出错吗?谢谢。任何帮助将不胜感激。

基本上,我的程序应该读取用户ID和密码,创建一个新进程来运行VALIDATE程序(在文件validate.c中),向VALIDATE程序发送用户ID和密码,并打印消息&# 34;密码已验证"如果用户ID和密码匹配或者“#34;密码无效"或"没有这样的用户"取决于验证程序的返回值。)0 - 一切正常,2和3 smth出错了。

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

#define MAXLINE 256
#define MAXPASSWD 10

void
strip (char *str, int capacity)
{
  char *ptr;
  if ((ptr = strchr (str, '\n')) == NULL)
    {
      str[capacity - 1] = '\0';
    }
  else
    {
      *ptr = '\0';
    }
}


int
main (void)
{
  char userid[MAXLINE];
  char password[MAXLINE];
  pid_t pid;
  int fd[2];
  /* Read a user id and password from stdin */
  printf ("User id:\n");
  if ((fgets (userid, MAXLINE, stdin)) == NULL)
    {
      fprintf (stderr, "Could not read from stdin\n");
      exit (1);
    }
  strip (userid, MAXPASSWD);
  printf ("Password:\n");
  if ((fgets (password, MAXLINE, stdin)) == NULL)
    {
      fprintf (stderr, "Could not read from stdin\n");
      exit (1);
    }
  strip (password, MAXPASSWD);
  pipe (fd);
  pid = fork ();
  if (pid == -1)
    {
      printf ("Error making process\n");
      return (-1);
    }
  if (pid == 0)
    {
      close (fd[0]);
      printf ("Hey I am the child with pid: %d\n", getpid ());
      dup2 (fd[0], 0);
      execl ("/h/u15/c2/00/validate.c", "validate.c", NULL);

    }
  int status;

  if (pid > 0)
    {

      write (fd[1], password, (strlen (password) - 1));
      write (fd[1], userid, (strlen (userid) - 1));
      printf ("status %d\n", WEXITSTATUS (status));
      if (waitpid (pid, &status, 0) == 0)
        {
          printf ("status %d\n", WEXITSTATUS (status));
          if (WIFEXITED (status) && WEXITSTATUS (status))
            {
              if (WEXITSTATUS (status) == 3)
                {
                  printf (" No such a user\n");
                }
              else if (WEXITSTATUS (status) == 2)
                {
                  printf ("Invalid password");
                }
              else
                printf ("Password verified\n");
            }
        }    
    }
  return 0;
}

1 个答案:

答案 0 :(得分:1)

您似乎使用pipe制作了管道,但未使用dup2使stdinstdout使用这些文件描述符。那么你execl的程序如何知道要读取哪个fd?

来自pipe的手册页:

  

pipe()创建一个管道,一个可用于进程间通信的单向数据通道。数组pipefd用于返回引用管道末端的两个文件描述符。 pipefd[0]指的是管道的读取端。 pipefd[1]指的是管道的写端。写入管道写端的数据由内核缓冲,直到从管道的读端读取。有关详细信息,请参阅pipe(7).

在你的程序中,父程序要写入管道,并且(我假设)孩子(execl)是从管道中读取的。

所以父母应该这样做:

close (fd[0]); /* close read end of pipe - NB you have close(fd[1]) currently */
write (fd[1], ...);

并且孩子应该做类似的事情:

close (fd[1]); /* close write end of pipe */
dup2 (fd[0], STDIN_FILENO); /* STDIN_FILENO is 0 */
close (fd[0]); /* now we have this on FD we don't need it any more *.
execl ( ... something that works with STDIN ...)

我认为你只是依赖于validate命令的退出状态?如果没有,并且您需要捕获写入STDOUT的内容,那么您需要另一个管道。

在您的下方,我会找到一个固定版本的代码,只要我没有您的密码验证程序就可以获得它:

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

#define MAXLINE 256
#define MAXPASSWD 10

void
strip (char *str, int capacity)
{
  char *ptr;
  if ((ptr = strchr (str, '\n')) == NULL)
    {
      str[capacity - 1] = '\0';
    }
  else
    {
      *ptr = '\0';
    }
}


int
main (void)
{
  char userid[MAXLINE];
  char password[MAXLINE];
  pid_t pid;
  int fd[2];
  /* Read a user id and password from stdin */
  printf ("User id:\n");
  if ((fgets (userid, MAXLINE, stdin)) == NULL)
    {
      fprintf (stderr, "Could not read from stdin\n");
      exit (1);
    }
  strip (userid, MAXPASSWD);
  printf ("Password:\n");
  if ((fgets (password, MAXLINE, stdin)) == NULL)
    {
      fprintf (stderr, "Could not read from stdin\n");
      exit (1);
    }
  strip (password, MAXPASSWD);
  pipe (fd);
  pid = fork ();
  if (pid == -1)
    {
      printf ("Error making process\n");
      return (-1);
    }
  if (pid == 0)
    {
      close (fd[0]);
      fprintf (stderr, "Hey I am the child with pid: %d\n", getpid ());
      dup2 (fd[0], 0);
      execl ("/h/u15/c2/00/validate.c", "validate.c", NULL);
      exit (1);
    }
  int status;

  if (pid > 0)
    {
      write (fd[1], password, (strlen (password) - 1));
      write (fd[1], userid, (strlen (userid) - 1));
      if (waitpid (pid, &status, 0) != -1)
        {
          printf ("status %d\n", WEXITSTATUS (status));
          if (WIFEXITED (status) && WEXITSTATUS (status))
            {
              if (WEXITSTATUS (status) == 3)
                {
                  printf (" No such a user\n");
                }
              else if (WEXITSTATUS (status) == 2)
                {
                  printf ("Invalid password");
                }
              else
                printf ("Password verified\n");
            }
        }
    }
  return 0;
}