只有一条消息通过管道

发布于 2024-12-22 23:51:55 字数 3105 浏览 0 评论 0原文

我已经一遍又一遍地做这个作业,这已经是第十个版本了。问题是只有一条消息通过管道,并且计算出正确的结果。以下字符串根本不会通过,或者在摆弄缓冲区后仅传递一些字符。请帮忙,我真的在这方面浪费了很多时间,我需要学习这些东西以应对即将到来的测试。

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

/* Prototypes */

void usage(void);
void calchild(void);

char command[] = "<not yet set>";

int main(int argc, char **argv)
{
  char input1[512];
  char input2[512];
  char tmp[512];
  char *endptr;
  char c = 0;
  int a, b, result;
  pid_t cpid;
  int status = 0;
  int stocpipe[2]; /* Server to client pipe. [0] -read; [1]- write*/
  int ctospipe[2]; /* Client to server pipe.       - || -         */
  int i = 0;
  FILE *send, *receive;

  if(argc > 1)
    {
      usage();
    }

  /* Pipe Setup */
  if(pipe(stocpipe) != 0 || pipe(ctospipe) != 0)
    {
      fprintf(stderr, "ERROR: Can't create unnamed pipe! \n");
      exit(EXIT_FAILURE);
    }

  switch(cpid = fork())
    {
    case -1:
      fprintf(stderr, "ERROR: Can't fork! \n");
      exit(EXIT_FAILURE);
      break;
    case 0:
      /* calchild */
      close(stocpipe[1]);
      close(ctospipe[0]);

      receive = fdopen(stocpipe[0], "r");
      send = fdopen(ctospipe[1], "w");

/*Gets the string from the parent process and does the computation.*/
      while(fgets(input2, 17, receive) != NULL)
        {
      strcpy(tmp, input2);
      fprintf(stdout, "After receive: %s", tmp);
      a = strtol(tmp, &endptr, 10);
      fprintf(stdout, "a = %d\n", a);
      b = strtol(endptr, &endptr, 10); 
      fprintf(stdout, "b = %d\n", b);
      c = endptr[0];

/*Loops until it finds a non-space char*/
      for(i = 0; isspace(c = endptr[i]); i++);

      switch(c)
    {
    case '+':
      /*add*/
      result = a + b;
      break;
    case '-':
      /*subtract*/
      result = a - b;
      break;
    case '*':
      /*multiply*/
      result = a * b;
      break;
    case '/':
      /*divide*/
      result = a / b;
      break;
    default:
      fprintf(stderr, "the funk!? %c\n", c);
      break;
    }

      fprintf(stderr, "%d\n", result);
      fprintf(send, "%d", result);

    }
      break;
    default:

  close(stocpipe[0]);
  close(ctospipe[1]);

  send = fdopen(stocpipe[1], "w");
  receive = fdopen(ctospipe[0], "r");

/*Reads string from stdin and sends it to the child process through a pipe. */
  while(fgets(input1, 17, stdin) != NULL)
    {
      fprintf(stdout, "Before send: %s", input1);
      fwrite(input1, 17, 1, send);

if(fflush(send) == EOF)
    {
      fprintf(stderr, "Flush error!");
  }
}

  (void) waitpid(cpid, &status, 0);
  if(status != 0)
    {
      fprintf(stderr, "ERROR: Child calculator exited with %d \n", status);
    }
      break;
   }


  return 0;
}

void usage(void)
{
  fprintf(stderr,"Usage: %s", command);
  exit(EXIT_FAILURE);
}

该程序是一个计算器。其目的是学习IPC。父进程接受来自标准输入的字符串(例如 3 5 +)并将其发送给子进程。孩子解析字符串并计算结果。然后它将结果发送回父进程,然后将其打印到标准输出。

我被困在将字符串发送给孩子的部分。接受的第一个字符串被发送给孩子。它计算结果很好。第二个字符串以及之后的每个字符串都是空的,或者至少看起来是空的。

I've been doing this assignment over and over again, this is about the 10th version. The problem is that only one message passes through the pipe, and the correct result is computed. The following strings don't pass at all, or after fiddling with the buffers only some characters. Please help, I've really lost a lot of time on this one and I need to learn this stuff for a test coming soon.

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

/* Prototypes */

void usage(void);
void calchild(void);

char command[] = "<not yet set>";

int main(int argc, char **argv)
{
  char input1[512];
  char input2[512];
  char tmp[512];
  char *endptr;
  char c = 0;
  int a, b, result;
  pid_t cpid;
  int status = 0;
  int stocpipe[2]; /* Server to client pipe. [0] -read; [1]- write*/
  int ctospipe[2]; /* Client to server pipe.       - || -         */
  int i = 0;
  FILE *send, *receive;

  if(argc > 1)
    {
      usage();
    }

  /* Pipe Setup */
  if(pipe(stocpipe) != 0 || pipe(ctospipe) != 0)
    {
      fprintf(stderr, "ERROR: Can't create unnamed pipe! \n");
      exit(EXIT_FAILURE);
    }

  switch(cpid = fork())
    {
    case -1:
      fprintf(stderr, "ERROR: Can't fork! \n");
      exit(EXIT_FAILURE);
      break;
    case 0:
      /* calchild */
      close(stocpipe[1]);
      close(ctospipe[0]);

      receive = fdopen(stocpipe[0], "r");
      send = fdopen(ctospipe[1], "w");

/*Gets the string from the parent process and does the computation.*/
      while(fgets(input2, 17, receive) != NULL)
        {
      strcpy(tmp, input2);
      fprintf(stdout, "After receive: %s", tmp);
      a = strtol(tmp, &endptr, 10);
      fprintf(stdout, "a = %d\n", a);
      b = strtol(endptr, &endptr, 10); 
      fprintf(stdout, "b = %d\n", b);
      c = endptr[0];

/*Loops until it finds a non-space char*/
      for(i = 0; isspace(c = endptr[i]); i++);

      switch(c)
    {
    case '+':
      /*add*/
      result = a + b;
      break;
    case '-':
      /*subtract*/
      result = a - b;
      break;
    case '*':
      /*multiply*/
      result = a * b;
      break;
    case '/':
      /*divide*/
      result = a / b;
      break;
    default:
      fprintf(stderr, "the funk!? %c\n", c);
      break;
    }

      fprintf(stderr, "%d\n", result);
      fprintf(send, "%d", result);

    }
      break;
    default:

  close(stocpipe[0]);
  close(ctospipe[1]);

  send = fdopen(stocpipe[1], "w");
  receive = fdopen(ctospipe[0], "r");

/*Reads string from stdin and sends it to the child process through a pipe. */
  while(fgets(input1, 17, stdin) != NULL)
    {
      fprintf(stdout, "Before send: %s", input1);
      fwrite(input1, 17, 1, send);

if(fflush(send) == EOF)
    {
      fprintf(stderr, "Flush error!");
  }
}

  (void) waitpid(cpid, &status, 0);
  if(status != 0)
    {
      fprintf(stderr, "ERROR: Child calculator exited with %d \n", status);
    }
      break;
   }


  return 0;
}

void usage(void)
{
  fprintf(stderr,"Usage: %s", command);
  exit(EXIT_FAILURE);
}

The program is a calculator. The aim of it is learning IPC. The parent process accepts strings from stdin(e.g. 3 5 +) and sends it to the child. The child parses the string and computes the result. Then it sends the result back to the parent process which then prints it to stdout.

I got stuck on the part of sending the string to the child. The first string accepted gets sent to the child. And it computes the result fine. The second string and every after that is empty or at least it seems like empty.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜灵血窟げ 2024-12-29 23:51:55

请注意 fwrite(input1, 17, 1, send); 行。 进程可能在“\n”字符之后向进程发送了随机内容。在 child while(fgets(input2, 17, receive) != NULL) 中,fgets 在获取 '\n' 时停止,并且可能获取更少超过 17-1 个字符。它的下一个读取管道将获得随机的东西。

一个立即修复方法是 fwrite(input1, strlen(input1), 1, send);。参考'man fwrite',最好使用fwrite(input1, sizeof (input1[0]), strlen(input1), send);

无论如何,使用魔法数字 17 是危险的。请记住 PIPE 是连续的字符流。

Pay attention to the line fwrite(input1, 17, 1, send);. The parent process may have sent random stuff after '\n' character to child process. In child while(fgets(input2, 17, receive) != NULL), fgets stops while getting '\n' and may get less than 17-1 characters. Its next reading pipe will get random stuff.

One immediate fix is fwrite(input1, strlen(input1), 1, send);. Referring to 'man fwrite', it's better to use fwrite(input1, sizeof (input1[0]), strlen(input1), send);.

Anyway using magic number 17 is dangerous. Keep in mind PIPE is a continuous character stream.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文