在 C 中通过 argv 使用管道发送和接收字符数组 [英] Sending and receiving character array using piping through argv in C

查看:34
本文介绍了在 C 中通过 argv 使用管道发送和接收字符数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

So, I'm trying to create a pipe that sends char arrays back and forth through pipes that connect through argv[]. Right now, I'm stuck at receiving the array (param which is sent to c_param from the parent to the child.) in interface.c to receiving the characters 3 and 5 at db.c. I know that 3 and 5 are the index for argv[] that my pipes are at, but I'm not sure how to take that and print out my message in db.c.

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

interface.c creates the pipes, forks into a parent process and a child process. The char array param is transfered to the child process to char array c_param. Using snprintf, I made my pipe into a char to send using execl with my char array c_param.

interface.c:

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

db.c started up from interface.c execl and should receive the parameters over argv[], which then should print it out. 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 中打印的消息的索引

This is the current output I'm getting, I'm aware that 5 and 3 are the indexes I need to send a message and receive the message that I'm currently trying to print in db.c

输出(db.c):

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

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

I hope I gave you enough information, I appreciate any help you are willing to give me. Thank you in advance!

推荐答案

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

There were lots of little things wrong. Your biggest problems were your assumptions/assertions in db.c about the parameters passed to it by interface.c — there was a total mismatch between what was passed and what was expected. There was also a good deal of extraneous code in interface.c. In particular, the child read from the pipe before executing db, so there was nothing left on the pipe for db to read.

这是固定"代码,一些调试代码仍然存在.

Here's the 'fixed' code, with some debug code still in place.

#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]

请注意,代码将错误报告给标准错误(这就是它的用途).它还对打印的数据进行了分隔,这可以使其更容易被发现意想不到的问题.它不假设数据是空填充的;它将打印的长度限制为读取的长度,尽管实际上数据最后有许多空值.

Note that the code reports errors to standard error (that's what it is for). It also delimits the printed data which can make it easier to spot unexpected problems. It doesn't assume that the data is null padded; it limits the length printed to the length read, though in fact the data has numerous nulls at the end.

这篇关于在 C 中通过 argv 使用管道发送和接收字符数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆