Отправка и получение массива символов с использованием конвейера через argv в C

Итак, я пытаюсь создать канал, который отправляет массивы символов назад и вперед через каналы, которые соединяются через argv[]. Прямо сейчас я застрял при получении массива (param, который отправляется в c_param от родителя к потомку.) В interface.c для получения символов 3 и 5 в db.c. Я знаю, что 3 и 5 являются индексом для argv[], в котором находятся мои каналы, но я не уверен, как взять это и распечатать мое сообщение в db.c.

interface.c создает каналы, разветвляется на родительский процесс и дочерний процесс. Параметр массива char передается дочернему процессу в массив 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

Я надеюсь, что дал вам достаточно информации, я ценю любую помощь, которую вы готовы оказать мне. Заранее спасибо!

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]

Обратите внимание, что код сообщает об ошибках к стандартной ошибке (вот для чего она нужна). Он также ограничивает печатные данные, которые могут помочь обнаружить неожиданные проблемы. Это не предполагает, что данные дополняются нулями; он ограничивает длину печати до длины чтения, хотя на самом деле данные имеют множество нулей в конце.

Другие вопросы по тегам