File 跨进程共享文件描述符

File 跨进程共享文件描述符,file,shared-memory,File,Shared Memory,我想为多个独立进程设置一个共享内存环境。在我想要共享的数据结构中,还有每个进程的连接FD 我想知道我们是否有办法分享这些FD?或者使用全球fds或类似的东西 提前谢谢 在Unix主机上共享文件描述符有两种方法。一种是让子进程跨fork继承它们 另一种方法是使用sendmsg通过Unix域套接字发送文件描述符;请参阅此示例程序,函数(已存档)。请注意,文件描述符在接收过程中可能有不同的编号,因此您可能需要执行一些dup2魔术,使它们正好出现在共享内存中 如果不这样做,共享内存区域中的文件描述符将只

我想为多个独立进程设置一个共享内存环境。在我想要共享的数据结构中,还有每个进程的连接FD

我想知道我们是否有办法分享这些FD?或者使用全球fds或类似的东西


提前谢谢

在Unix主机上共享文件描述符有两种方法。一种是让子进程跨
fork
继承它们

另一种方法是使用
sendmsg
通过Unix域套接字发送文件描述符;请参阅此示例程序,函数(已存档)。请注意,文件描述符在接收过程中可能有不同的编号,因此您可能需要执行一些
dup2
魔术,使它们正好出现在共享内存中


如果不这样做,共享内存区域中的文件描述符将只是整数。

最近,我不得不解决一个类似于OP描述的问题。为此,我提出了一个专门的系统调用(我可能会添加一个非常简单的调用),将文件描述符直接发送到协作进程地址,并依赖Posix.1b信号队列作为传递介质(另外一个好处是,这种方法天生不受“fd递归”的影响)攻击,这在某种程度上困扰着所有基于VFS的机制)

以下是建议的修补程序:

(目前,该补丁只为x86/x86_64体系结构添加了新的系统调用,但将其连接到其他体系结构并不重要,没有使用依赖于平台的功能)

操作理论如下。发送方和接收方都需要商定一个或多个用于描述符传递的信号号。这些信号必须是Posix.1b信号,保证可靠传输,因此
SIGRTMIN
offset。此外,如果需要优先级管理,较小的信号号具有较高的传输优先级:

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()
收集信号信息:


成功返回
sigwaitinfo()
后,
sig_info.si_int
将包含新的文件描述符,指向与原始进程发送的文件描述符相同的IO对象
sig_info.si_pid
将包含发起进程的pid,
sig_info.si_uid
将包含发起进程的uid。如果
sig\u info.si\u int
小于零(表示无效的文件描述符),
sig\u info.si\u errno
将包含fd复制过程中遇到的实际错误的
errno

dup是否跨进程工作?也就是说,一个进程可以复制另一个进程的fd(指向它想要指向的同一个文件),然后开始使用新的fd吗?@SunandaSharma:no,
dup
在单个进程内克隆fd。我的意思是,您必须同步FD在各个进程中的实际数字,然后使用
dup2
将它们设置为跨进程相同。哦,好的。很遗憾,这个设置将无法为我工作。非常感谢您的投入:)
/* 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);