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

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

Это возможно?
Как это может быть сделано?


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

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

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

5 ответов

Решение

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

Шаг один вызов канала, чтобы получить канал:

  #include <unistd.h>


  int main(...)
  {

    int fileDescriptors[2];
    pipe(fileDescriptors);

Шаг 2 передает fileDescriptors[0] основному процессу, а fileDescriptors 1 - потоку. В Main вы ожидаете записи канала, читая из fileDescriptors[0]

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

Шаг 3, из вашего потока записать в fileDescritpors 1 при появлении сигнала

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

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

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

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

Однако, если вы настаиваете.

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

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

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

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

kill(getppid(), SIGUSR1);

Чтобы отправить сигнал родителю. Другие имеют код выше, чтобы порождать файловые дескрипторы и ловить его на родительской стороне.

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

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