【问题标题】:Sending and receiving character array using piping through argv in C在 C 中通过 argv 使用管道发送和接收字符数组
【发布时间】:2016-09-27 01:15:59
【问题描述】:

所以,我正在尝试创建一个管道,该管道通过通过 argv[] 连接的管道来回发送 char 数组。现在,我坚持在 interface.c 中接收数组(从父级到子级发送到 c_param 的参数)以在 db.c 中接收字符 3 和 5。我知道 3 和 5 是我的管道所在的 argv[] 的索引,但我不确定如何获取它并在 db.c 中打印出我的消息。

interface.c 创建管道,分叉成父进程和子进程。 char 数组 param 被传递给子进程到 char 数组 c_param。使用 snprintf,我将管道变成了一个 char,以便使用 execl 和我的 char 数组 c_param 发送。

interface.c:

int main (int argc, char *argv[])
{
  int to_Child[2];
  int to_Parent[2];
  int id, toChildPipe, toParentPipe, err;
  char param[100] = "This is the parameter!";
  char sendPipe[100];
  char recPipe[100];

  /*CREATING PIPE*/
  toChildPipe = pipe(to_Child);
  toParentPipe = pipe(to_Parent);


  if(toChildPipe == -1 || toParentPipe == -1)
  {
    printf ("Error on pipe creation: %d", errno);
    exit (1);
  }

  /*Creating Child Process*/
  id = fork();
  if(id == 0)
  {
    /**
     *
     * IN THE CHILD Process
     *
     */
    close(to_Child[1]); //reading
    close(to_Parent[0]); //writing
    char c_param[100];


    toChildPipe = read(to_Child[0], c_param, 100);
    if (toChildPipe == -1)
    {
      //If failed
      printf("Error on read from pipe from parent: %d\n",errno);
      //exit with error
      exit(2);
    }//Error pipe from parent


    snprintf(sendPipe,sizeof(sendPipe), "%d",to_Parent[0]);
    snprintf(recPipe,sizeof(recPipe), "%d",to_Child[0]);

    err = execl("./db","db",sendPipe,recPipe,(char *)0);
      if(err == -1)
      {
        printf("Error on execl: %d\n", errno);
      }//Error execl

      toChildPipe = read(to_Child[0], c_param, 100);
      if (toChildPipe == -1)
      {
        //If failed
        printf("Error on read from pipe from parent: %d\n",errno);
        //exit with error
        exit(2);
      }//Error pipe from parent

    }//CHILD PROCESS

  else if (id > 0)
  {
    /**
     *
     *IN THE PARENT PROCESS
     *
     */
    close(to_Child[0]); //writing
    close(to_Parent[1]); //reading


    toChildPipe = write(to_Child[1],param,100);
    if(toChildPipe == -1)
    {
      printf("Error on write to pipe: %d", errno);
      exit(3);
    }
    /*Piping was successful!*/
    exit(0);
  }//PARENT PROCESS
  else
  {
    exit(4);
  }
}

db.c 从 interface.c execl 启动并且应该通过 argv[] 接收参数,然后应该将其打印出来。 db.c

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


int main(int argc, char *argv[])
{
  FILE *finput;
  int j = 0;
  int fd;
  int toChildPipe;
  char c_param[100];

  if(argc > 1)
  {
    for(j ; j < argc ; j++)
    printf("argv = %s\n", argv[j]);
    printf("argc = %d\n",argc);
  }
  fd = atoi(argv[1]);
  printf("Statement: %s\n", argv[fd]);

  strcpy(c_param, argv[3]);
  printf("filename: %s\n", c_param);

}

这是我得到的当前输出,我知道 5 和 3 是我需要发送消息和接收我当前尝试在 db.c 中打印的消息的索引

输出(db.c):

argv = db
argv = 5
argv = 3
argc = 3
Statement: TERM=xterm

我希望我给了你足够的信息,感谢你愿意给我的任何帮助。提前谢谢!

【问题讨论】:

    标签: c pipe exec argv execl


    【解决方案1】:

    有很多小问题。你最大的问题是你在db.c 中关于interface.c 传递给它的参数的假设/断言——传递的和预期的完全不匹配。 interface.c 中还有大量无关代码。特别是,子进程在执行db 之前从管道中读取,因此管道上没有任何内容可供db 读取。

    这是“固定”代码,还有一些调试代码。

    interface.c

    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
    int main(void)
    {
        int to_Child[2];
        int to_Parent[2];
        int id;
        char param[100] = "This is the parameter!";
        char sendPipe[100];
        char recPipe[100];
    
        if (pipe(to_Child) == -1 || pipe(to_Parent) == -1)
        {
            printf("Error on pipe creation: %d", errno);
            exit(1);
        }
        printf("Pipes: C(%d,%d), P(%d,%d)\n", to_Child[0], to_Child[1], to_Parent[0], to_Parent[1]);
    
        id = fork();
        if (id == 0)
        {
            close(to_Child[1]);     // Child does not write to itself
            close(to_Parent[0]);    // Child does not read what it writes
            snprintf(sendPipe, sizeof(sendPipe), "%d", to_Parent[1]);
            snprintf(recPipe, sizeof(recPipe), "%d", to_Child[0]);
            execl("./db", "db", sendPipe, recPipe, (char *)0);
            fprintf(stderr, "Error on execl: %d\n", errno);
            exit(2);
        }
        else if (id > 0)
        {
            close(to_Child[0]);     // Parent does not read childs input
            close(to_Parent[1]);    // Parent does not
            int nbytes = write(to_Child[1], param, 100);
            if (nbytes == -1)
            {
                fprintf(stderr, "Error on write to pipe: %d\n", errno);
                exit(3);
            }
            close(to_Child[1]);
            if ((nbytes = read(to_Parent[0], param, 100)) <= 0)
            {
                fprintf(stderr, "Error on read from pipe: %d\n", errno);
                exit(5);
                }
            printf("Data from pipe: [%.*s]\n", nbytes, param);
            exit(0);
        }
        else
        {
            perror("fork failed");
            exit(4);
        }
    }
    

    ### db.c

    #include <assert.h>
    #include <errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    
    int main(int argc, char *argv[])
    {
    
        printf("argc = %d\n", argc);
        for (int j = 0; j < argc; j++)
            printf("argv[%d] = %s\n", j, argv[j]);
    
        if (argc != 3)
        {
            fprintf(stderr, "Usage: %s write-fd read-fd\n", argv[0]);
            return 1;
        }
        int ofd = atoi(argv[1]);
        int ifd = atoi(argv[2]);
        printf("ifd = %d; ofd = %d\n", ifd, ofd);
    
        char c_param[100];
        int nbytes = read(ifd, c_param, sizeof(c_param));
        if (nbytes <= 0)
        {
            fprintf(stderr, "Error: failed to read any data (%d)\n", errno);
            return 1;
        }
        printf("Child: [%.*s]\n", nbytes, c_param);
    
        assert(strlen(c_param) + sizeof(" - sent back to parent") <= sizeof(c_param));
        strcat(c_param, " - sent back to parent");
    
        if (write(ofd, c_param, nbytes) != nbytes)
        {
            fprintf(stderr, "Error: failed to write all the data (%d)\n", errno);
            return 1;
        }
    
        return 0;
    }
    

    样品运行

    Pipes: C(3,4), P(5,6)
    argc = 3
    argv[0] = db
    argv[1] = 6
    argv[2] = 3
    ifd = 3; ofd = 6
    Child: [This is the parameter!]
    Data from pipe: [This is the parameter! - sent back to parent]
    

    请注意,代码会将错误报告为标准错误(这就是它的用途)。它还划定了打印数据,使其更容易被发现 意想不到的问题。它不假设数据是空填充的;它将打印的长度限制为读取的长度,尽管实际上数据末尾有许多空值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-30
      • 2010-10-19
      • 1970-01-01
      • 2012-03-02
      • 2023-04-04
      相关资源
      最近更新 更多