Как мне объявить канал в заголовочном файле? (В С) - PullRequest
2 голосов
/ 17 марта 2010

У меня есть задание, в котором мне нужно объявить канал в заголовочном файле. Я действительно понятия не имею, как это сделать. Это может быть действительно глупый вопрос, и я могу упустить что-то очевидное. Если бы вы могли указать мне правильное направление, я был бы очень признателен.

Спасибо за ваше время.

EDIT:

Извините за столь расплывчатый вопрос. Может быть, мне нужно укрепить мое понимание труб.

Я пытаюсь создать канал между двумя дочерними процессами. Один дочерний элемент будет писать случайные символы в канал, а другой дочерний элемент будет читать символы из канала.

Полагаю, я не совсем понимаю, что происходит, когда я пишу что-то вроде:

int fd[2];
pipe = pipe(fd);

Прав ли я, говоря, что дескрипторы файлов записи и чтения для канала помещены в fd[0] и fd[1] соответственно? Если в одном из дочерних процессов я закрою fd[1], этот ребенок может считаться моим автором, правильно?

РЕДАКТИРОВАТЬ 2:

Ладно, похоже, что я почти все выяснил и сделал, за исключением того, что я получаю сообщение об ошибке, касающееся файловых дескрипторов.

Мой код выглядит так: (Это только код, относящийся к трубе)

proj2.h

extern int fd[2];

proj2.c

int fd[2];
pipe(fd);

writer.c

close(fd[0]);
result = write(fd[1], &writeBuffer, sizeof(writeBuffer));
if(result < 0){
    perror("Write");
}

reader.c

close(fd[1]);
result = read(fd[0], &readBuffer, sizeof(readBuffer))
if(result < 0){
    perror("Read");
}

После выполнения кода я получаю сообщение об ошибке для каждой итерации read () и write () с ошибкой «Bad file descriptor». Я пытался найти в Интернете, чтобы решить это сам, но я не думаю, что знаю достаточно об этом материале, чтобы сделать это. Любое направление будет с благодарностью еще раз. Все, кто внес свой вклад, проделали замечательную работу до сих пор, большое спасибо. Кроме того, если мне кажется, что я просто делаю свою домашнюю работу для меня, я прилагаю честные усилия, и это еще не все.

РЕДАКТИРОВАТЬ 3:

Запись системного вызова write () в стандартный вывод? Что если я хочу, чтобы содержимое было напечатано только после того, как читатель прочитает его из канала? Как мне записать их в канал без записи в стандартный вывод?

РЕДАКТИРОВАТЬ 4: Я понял все сейчас. Спасибо всем за помощь всем. Единственное, что мне все еще интересно, так это то, могу ли я каким-то образом получить статус родительского процесса. Я собрал статусы из дочернего процесса с помощью системного вызова wait (), и мне было интересно, как получить статус родительского процесса.

Ответы [ 4 ]

3 голосов
/ 17 марта 2010

Вот пример программы, которая создает канал, затем разветвляет процесс и вызывает функцию отправителя в родительском элементе и получателя в дочернем. Дескрипторы создания канала и файла находятся в одном файле исходного кода со связанным файлом заголовка, как отправитель и получатель. Файл main запрашивает создание канала, затем выполняет fork() и вызывает функции sender и receiver.

pipe.h - содержит объявление extern для дескрипторов файла канала, а также объявление функции, которая создает канал: -

#ifndef PIPE_H
#define PIPE_H

extern int pipe_fd[2];

void create_pipe(void);

#endif

pipe.c - содержит фактическое определение массива pipe_fd: -

#include "pipe.h"
#include <unistd.c>

int pipe_fd[2];

void create_pipe(void)
   {
   pipe(pipe_fd);
   }

sender.h - объявляет прототип для функции sender ()

#ifndef SENDER_H
#define SENDER_H

void sender(void);

#endif

sender.c: -

#include "sender.h"
#include "pipe.h"
#include <unistd.h>
#include <stdio.h>

void sender(void)
   {
   char buf[]="Hello world";

   printf("Sender: PID = %d\n", getpid());
   close(pipe_fd[0]);
   write(pipe_fd[1], buf, sizeof(buf));
   }

receiver.h: -

#ifndef RECEIVER_H
#define RECEIVER_H

void receiver(void);

#endif

receive.c - зеркальное отображение отправителя

#include <stdio.h>
#include <unistd.h>
#include "receiver.h"
#include "pipe.h"

void receiver(void)
   {
   int bytes;
   char buf[101];

   printf("Receiver: PID = %d\n", getpid());

   close(pipe_fd[1]);
   bytes = read(pipe_fd[0], buf, 100);
   buf[bytes]='\0';
   printf("Receiver got: %s\n", buf);
   }

main.c - связывает все вместе

#include "pipe.h"
#include "sender.h"
#include "receiver.h"
#include <sys/types.h>
#include <unistd.h>

void launch_sender_receiver(void)
   {
   pid_t forkpid;

   forkpid = fork();
   if (forkpid == 0)
      receiver(); /* child */
   else
      sender();
   }

int main(int argc, char* argv[])
   {
   create_pipe();
   launch_sender_receiver();
   return 0;
   }

Надеюсь, вы можете следовать всему этому из кода, но если нет, то здесь есть небольшое дополнительное объяснение.

Функция create_pipe () в pipe.c создает канал и помещает два файловых дескриптора в file_fd. Файл pipe.h предоставляет объявление extern для файловых дескрипторов, чтобы к ним могли обращаться файлы отправителя и получателя (лучше бы при программировании обеспечить функции «получателя» для этих файловых дескрипторов в pipe.h так, чтобы sender() и receiver() не имеют доступа к глобальным переменным).

Отправитель и Получатель используют массив pipe_fd для записи или чтения из канала после закрытия дескриптора файла, который им не нужен. Функция main() связывает все это вместе, вызывая функцию создания канала, а затем выполняет разветвление и вызывая отправителя или получателя в зависимости от того, является ли он родительским или дочерним, соответственно.

Запуск полной программы должен дать вам следующий результат (хотя, конечно, PID, которые вы получите, будут другими): -

Receiver: PID = 3285
Sender: PID = 3284
Receiver got: Hello world

Имеет ли все это смысл?

1 голос
/ 17 марта 2010

Ваш вопрос почти невозможен, но я собираюсь угадать

extern int myPipe[2];

0 голосов
/ 17 марта 2010

Зачем вам это нужно делать в заголовочном файле? Вы просто вызываете pipe () из вашей программы. Затем вызовите fork (). В результате у вас есть два процесса, обращающихся к одному каналу.

0 голосов
/ 17 марта 2010

Если вы собираетесь использовать fork () для создания двух процессов, тогда ваш "int fd [2]; pipe (fd);"будет работать так, как вы описали.

т.е. используйте fd [0] в одном процессе и fd [1] в другом.

Однако, если вы не собираетесь форкать, то вывозможно, потребуется создать канал в файловой системе и обмениваться данными через него.

Используйте mkfifo для создания канала, а затем откройте его для чтения в одном процессе и откройте для записи в другом.

...