在 C 中通过 argv 使用管道发送和接收字符数组

Sending and receiving character array using piping through argv in C

因此,我正在尝试创建一个管道,通过通过 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

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

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

这是 'fixed' 代码,一些调试代码仍然存在。

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]

请注意,代码向标准错误报告错误(这就是它的用途)。它还对打印的数据进行了分隔,这样更容易识别 意想不到的问题。它不假设数据是空填充的;它将打印的长度限制为读取的长度,但实际上数据末尾有许多空值。