Совместное использование файловых дескрипторов между процессами - PullRequest
1 голос
/ 30 марта 2012

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

Я хотел знать, есть ли способ, которым мы можем поделиться этими FDS? или использовать глобальные FDS или что-то подобное?

Спасибо заранее.

Ответы [ 2 ]

1 голос
/ 30 марта 2012

Существует два способа поделиться дескрипторами файлов на хосте Unix. Один из них - позволить дочернему процессу наследовать их через fork.

Другой отправляет файловые дескрипторы через доменный сокет Unix с sendmsg; см. пример программы, функция send_connection (архив здесь ). Обратите внимание, что дескриптор файла может иметь другой номер в процессе получения, поэтому вам, возможно, придется выполнить какое-то волшебство dup2, чтобы они появились прямо в вашей общей памяти.

Если вы этого не сделаете, дескрипторы файлов в вашей области общей памяти будут просто целыми числами.

0 голосов
/ 05 декабря 2014

Недавно мне пришлось решить проблему, аналогичную описанной ОП.С этой целью я перешел к предложению выделенного системного вызова (очень простого, я мог бы добавить) для отправки файловых дескрипторов непосредственно на адреса взаимодействующих процессов и использования сигнальных очередей Posix.1b в качестве средства доставки (в качестве дополнительного преимущества, такого какэтот подход по своей природе невосприимчив к атаке "fd recursion", которая до некоторой степени поражает все механизмы, основанные на VFS.

Вот предлагаемый патч:

http://permalink.gmane.org/gmane.linux.kernel/1843084

(в настоящее времяпатч добавляет только новый системный вызов для архитектуры x86 / x86_64, но подключение его к другим архитектурам тривиально, функции, зависящие от платформы, не используются).

Теория работы выглядит следующим образом.И отправитель, и получатель должны согласовать один или несколько номеров сигналов для использования при передаче дескриптора.Это должны быть сигналы Posix.1b, которые гарантируют надежную доставку, таким образом, смещение SIGRTMIN.Кроме того, меньшие номера сигналов имеют более высокий приоритет доставки, в случае, если требуется управление приоритетами:

int signo_to_use = SIGRTMIN + my_sig_off;

Затем исходящий процесс вызывает системный вызов:

int err = sendfd(peer_pid, signo_to_use, fd_to_send);

Вот и все, больше ничегонеобходимо на стороне отправителя.Очевидно, что sendfd() будет успешным, только если исходный процесс имеет право сигнализировать о процессе назначения, а процесс назначения не блокирует / игнорирует сигнал.

Следует также отметить, что sendfd() никогда не блокирует;он немедленно вернется, если очередь сигналов целевого процесса заполнена.В хорошо спроектированном приложении это будет указывать на то, что процесс назначения в любом случае находится в затруднительном положении, или слишком много работы, поэтому новые рабочие должны появляться / отбрасываться.Размер очереди сигналов процесса может быть настроен с использованием rlimit(), так же как и количество доступных файловых дескрипторов.

Процесс приема может безопасно игнорировать сигнал (в этом случае ничего не произойдет и почти не будет служебных данныхбудет происходить на стороне ядра).Однако, если принимающий процесс хочет получить дескриптор доставленного файла, все, что ему нужно, это собрать информацию о сигнале, используя sigtimedwait() / sigwaitinfo() или более универсальный signalfd():

/* First, the receiver needs to specify what it is waiting for: */
sigset_t sig_mask;
sigemptyset(&sig_mask);
sigaddset(&sig_mask, signo_to_use);

siginfo_t sig_info;
/* Then all it needs is to wait for the event: */
sigwaitinfo(&sig_mask, sig_info);

Послеуспешное возвращение sigwaitinfo(), sig_info.si_int будет содержать новый файловый дескриптор, указывающий на тот же объект ввода-вывода, что и файловый дескриптор, отправленный исходным процессом.sig_info.si_pid будет содержать PID инициирующего процесса, а sig_info.si_uid будет содержать UID инициирующего процесса.Если sig_info.si_int меньше нуля (представляет неверный дескриптор файла), sig_info.si_errno будет содержать errno для фактической ошибки, возникшей в процессе дублирования fd.

...