2013-10-06 55 views
1

我正尝试使用Internet域套接字为聊天应用程序创建一个小型服务器。服务器由调度程序和主服务器组成。C - 通过FIFO将在线程中创建的PIPE FD发送到父进程

调度员负责检测新的连接请求并在新线程中处理它们。该线程通过FIFO将信息发送到主服务器。线程发送的包具有它创建的管道FD,以便主服务器可以与响应进行通信。调度程序由主服务器用叉子初始化,然后使用execve()

问题是我无法将数据写入服务器的管道。我得到[EBADF错误文件描述符]错误。

据我所知,我应该将管道FD从父进程传递给子进程,但这种解决方案对我来说并不起作用,因为我不知道我将需要多少管道同一时间。此外,我不想为每个线程创建一个FIFO,这意味着我需要为每个活动的线程创建一个新文件,我认为这不是一个非常优雅的解决方案。

所以总结:

  • 是否有可能使用管道以这种方式?
  • 如果问题出在 使用管道,为什么我不能通过FIFO传递管道FD,并在另一个进程中使用 ?我读过可以通过使用UNIX域套接字 传递FD来在无关进程与管道之间通信 。这些方法有什么区别?
  • 你会推荐什么解决方案?
+2

有一种机制可以通过套接字连接传递文件描述符;它不适用于其他通信机制,如FIFO。 –

+0

我已经添加了“unix”标签,因为这似乎是关于unix编程的。 – Joni

回答

2

如果您创建从fork主服务器的调度员也不会共享该文件描述符表:调度员将首先得到的文件描述符的副本,但是任何文件或套接字调度员打开之后会只在调度员中打开。

要创建调度程序,您应该使用共享文件描述符表的方法。例如,您可以使用pthreads线程。如果您使用Linux,则可以将fork替换为低位clone函数,其中包括CLONE_FILES

+0

谢谢你的回答乔尼。我现在明白,问题在于每个进程都有不同的文件描述符表,因此每个进程的相同fd描述符编号引用不同的资源,因此不能以这种方式使用管道,除非修改了底层fd表。我使用的是OSX,因此我认为clone()不可用。是否有可能从一个线程产生新的线程? – enzo

+0

在OS X上,您可以使用pthreads或Cocoa线程,请参阅https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/AboutThreads/AboutThreads.html – Joni

1

您只能通过'Unix域'(本地域,而不是IPv4或IPv6)套接字在同一台计算机上的两个进程之间传输打开的文件描述符。传输的文件描述符的类型可以是任何有效的文件描述符,但传输机制必须是在已经具有文件描述符打开的进程中使用sendmsg()的Unix域套接字文件描述符,并且在正在获取访问的进程中使用 recvmsg()到一个描述符(尽管大部分所需的信息都被隐藏在<sys/socket.h>的描述中)。