Sending and receiving character array using piping

2019-09-11 12:32发布

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 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:

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 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);

}

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

output(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!

1条回答
\"骚年 ilove
2楼-- · 2019-09-11 13:13

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.

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;
}

Sample run

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.

查看更多
登录 后发表回答