Множество IPC предлагаются Unix/Linux: каналы, сокеты, разделяемая память, dbus, очереди сообщений...
Каковы наиболее подходящие приложения для каждого и как они выполняются?
Множество IPC предлагаются Unix/Linux: каналы, сокеты, разделяемая память, dbus, очереди сообщений...
Каковы наиболее подходящие приложения для каждого и как они выполняются?
Вот большая семерка:
Полезно только для процессов, связанных с родительским/дочерним. Вызовите pipe(2)
и fork(2)
. Однонаправленный.
FIFO или named pipe
Два несвязанных процесса могут использовать FIFO в отличие от простой трубы. Вызовите mkfifo(3)
. Однонаправленный.
двунаправленный. Предназначен для сетевого общения, но может использоваться и локально. Может использоваться для разных протоколов. Там нет границ сообщений для TCP. Вызовите socket(2)
.
ОС поддерживает дискретное сообщение. См. sys/msg.h.
Сигнал отправляет целое число в другой процесс. Не мешает хорошо с несколькими потоками. Вызовите kill(2)
.
Механизм синхронизации для нескольких процессов или потоков, похожих на очередь людей, ожидающих ванную. См. sys/sem.h.
Сделайте свой собственный concurrency элемент управления. Вызовите shmget(2)
.
Одним из определяющих факторов при выборе одного метода над другим является проблема границы сообщения. Вы можете ожидать, что "сообщения" будут дискретными друг от друга, но это не для потоков байтов, таких как TCP или Pipe.
Рассмотрим пару эхо-клиента и сервера. Клиент отправляет строку, сервер ее получает и отправляет обратно. Предположим, что клиент отправляет "Hello", "Hello" и "Как насчет ответа?".
В протоколах байтового потока сервер может получать как "Ад", "oHelloHow", так и "об ответе?"; или более реалистично "HelloHelloHow об ответе?". Сервер не знает, где находится граница сообщения.
Старый трюк заключается в том, чтобы ограничить длину сообщения CHAR_MAX
или UINT_MAX
и согласиться на отправку длины сообщения сначала в char
или uint
. Итак, если вы находитесь на стороне приема, вам сначала нужно прочитать длину сообщения. Это также подразумевает, что только один поток должен делать чтение сообщения за раз.
С дискретными протоколами, такими как UDP или очереди сообщений, вам не нужно беспокоиться об этой проблеме, но программные потоки байтов легче справляться, потому что они ведут себя как файлы и stdin/out.
Общая память может быть наиболее эффективной, поскольку вы строите свою собственную схему связи поверх нее, но для этого требуется много внимания и синхронизации. Решения доступны для распространения разделяемой памяти на другие машины.
В наши дни сокеты являются наиболее переносимыми, но требуют больше накладных расходов, чем трубы. Возможность прозрачного использования сокетов локально или по сети - отличный бонус.
Очереди сообщений и сигналы могут быть полезны для жестких приложений реального времени, но они не так гибки.
Эти методы были естественным образом созданы для связи между процессами, а использование нескольких потоков внутри процесса может усложнить ситуацию - особенно с помощью сигналов.
Вот веб-страница с простым эталоном: https://sites.google.com/site/rikkus/sysv-ipc-vs-unix-pipes-vs-unix-sockets
Насколько я могу судить, каждый имеет свои преимущества:
Стоит отметить, что множество библиотек реализуют один тип вещей поверх другого.
В общей памяти не нужно использовать ужасные функции общей памяти sysv - гораздо более элегантно использовать mmap() (mmap файл на tmpfs/dev/shm, если вы хотите, чтобы он был назван; mmap/dev/zero если вы хотите, чтобы не выполнялись процессы exec'd, чтобы наследовать его анонимно). Сказав это, он по-прежнему оставляет ваши процессы с некоторой необходимостью синхронизации, чтобы избежать проблем - обычно, используя некоторые из других механизмов IPC для синхронизации доступа к области общей памяти.