Как можно использовать каналы Unix между основным процессом и потоком?

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

Возможно ли это?
Как это можно сделать?


Эта проблема:

  1. Дочерний поток считывает данные и помещает их в очередь.
  2. Основное приложение выполняет свои собственные функции, однако, когда данные доступны в очереди, оно должно быть уведомлено потоком и начать обработку данных (основной поток имеет доступ к очереди).

Как должен быть реализован этот сценарий?


person Community    schedule 08.06.2009    source источник


Ответы (5)


Да, через трубы можно.

Шаг первый вызовите pipe, чтобы получить канал:

  #include <unistd.h>


  int main(...)
  {

    int fileDescriptors[2];
    pipe(fileDescriptors);

Шаг 2: передать fileDescriptors[0] в основной процесс, а fileDescriptors1 в поток . В Main вы ожидаете записи в канал, читая из fileDescriptors[0]

    ...
    char msg[100];
    read(fileDescriptors[0], msg, 100);  // block until pipe is read
  }

Шаг 3, из вашего потока напишите в fileDescritpors1, когда появится сигнал

 void signal_handler( int sig )
 {
     // Write to the file descriptor
     if (sig == SIGKILL)
     {
         const char* msg = "Hello Mama!";
         write(fileDescriptors[1], msg, strlen(msg));
     }
 }
person Doug T.    schedule 08.06.2009

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

person Emil H    schedule 08.06.2009
comment
Я бы сказал, что каналы или условная переменная предпочтительнее разделяемой памяти, потому что вам нужно беспокоиться обо всех проблемах с блокировками, разделяемой памятью и т. д. - person Doug T.; 08.06.2009
comment
Да, это может быть так. Однако зависит от приложения, поэтому я подумал, что упомяну об этом. - person Emil H; 08.06.2009
comment
Основное преимущество использования каналов заключается в том, что один поток может ожидать и читать из нескольких каналов, а не только из одной очереди, сигнализируемой семафором. - person Greg Rogers; 08.06.2009
comment
Кстати, у меня только один поток. Интересно, будет ли общая память лучшим/более простым решением? - person ; 08.06.2009
comment
Саша, тебя устраивают мьютексы и блокировки? Приходилось ли вам сталкиваться с тупиками или условиями гонки в прошлом? Вы знакомы с тем, как сложно их отлаживать? Я бы предложил использовать трубы как более простое решение. - person Doug T.; 08.06.2009
comment
чтение/запись в каналы в glibc является атомарным, если данные меньше определенного размера gnu.org/software/libc/manual/html_node/ - person novelistparty; 30.09.2017

Если вы говорите о pipe(), а не |, то да. Обычно каналы можно рассматривать как дескриптор файла. Вам просто нужно открыть канал и очистить ввод в одном потоке и вывод в другом.

person John Weldon    schedule 08.06.2009

Как уже говорили другие, это может быть больше проблем, чем оно того стоит.

Впрочем, если вы настаиваете.

Вероятно, проще всего просто открыть две трубы, используя режимы popen и rw перед созданием потока. Выберите один для main-->thread, а другой для main‹--thread и вперед.

Или вы можете открыть в общей сложности четыре файловых дескриптора после создания, как если бы это были два разных процесса.

person dmckee --- ex-moderator kitten    schedule 08.06.2009

Вы можете сделать это, у apache есть аналогичная опция «изящного перезапуска». (см. здесь). Вы бы использовали что-то вроде:

#include <sys/types.h>
#include <signal.h>

kill(getppid(), SIGUSR1);

Послать сигнал родителю. У других есть приведенный выше код для создания файловых дескрипторов и их перехвата на родительской стороне.

Однако я стараюсь избегать сигналов для межпроцессного взаимодействия по сценарию, вместо этого использую их только для сообщений, отправленных пользователем, таких как запуск/остановка/перезапуск/обновление. То, чем вы их замените, зависит от вашего варианта использования: вы можете использовать переменную обмена сообщениями или, если ваш основной процесс находится в цикле сервера, вы можете "select" в канале в верхней части цикла, чтобы узнать, отправил ли дочерний элемент сообщение обновления. Есть, вероятно, много других, которых мне не хватает.

person Todd Gardner    schedule 08.06.2009