与分叉流程相关的问题

时间:2012-01-11 17:19:35

标签: c++ c sockets fork

我正在制作服务器而我使用fork()来创建子进程,但我对此有疑问。以下是一些:

  1. 为什么需要在子进程中关闭主套接字并在父进程中接受新连接接受套接字? (在接受新连接之后)我认为套接字只是带有一些id的整数,用于访问某些系统范围对象中打开的套接字,这只能通过系统函数调用来接受。在这种情况下,fork只会复制整数,但对打开的套接字没有影响。
  2. 我检查过并发现如果我在一个类方法中分叉一个进程,那么所有成员都会被复制。好吧,我发现它是copy-on-edit所以它是否意味着我的服务器类将被复制到每个使用非常量函数的子节点中?如何在所有这些进程之间共享一些内存(比如任务列表和每个孩子在父进程中读取内容时将某些内容放入其中)?我认为fork不是正确的功能。什么是最好的方式?
  3. P.S。我很确定我知道第二个问题的答案,即clone(),但只是想确保它是正确的函数。

4 个答案:

答案 0 :(得分:1)

  1. int是句柄,但套接字本身仍然与进程相关联。孩子关闭监听套接字主要是出于安全原因(它不需要它,如果孩子产生另一个进程,该进程也会继承套接字);服务器进程关闭新连接的套接字,否则连接将保持打开状态,直到服务器进程退出(只要至少有一个进程仍有句柄,就会存在套接字。)

  2. 您要么需要多线程,要么需要适当的共享内存方法。这就是乐趣的开始。

  3. 独立进程之间的共享内存带来了有趣的问题,但也提供了其他不可能的功能(例如,您可以重新启动主服务器进程并让运行开放连接的进程保持运行,这很难在两个不同的版本中运行然后,该服务必须相互通信,但允许无缝升级,无需断开客户端连接或中断服务。)

    在线程之间共享内存相对容易,但线程共享同一组文件描述符,所以你不会在这里赢得太多。

    最后,还有第三种选择:观察多个套接字的事件循环,只有在实际发生某些事情时才会注意每个套接字。查看selectpoll函数的文档。

答案 1 :(得分:1)

  1. Unix中的套接字是文件描述符,它们确实是整数,如用户所见,但它们实际上是内核为每个进程维护的表的索引。在此表中,每个文件描述符(FD)是指打开文件描述(OFD),它们是内核中维护的系统范围对象。执行fork()时,打开的文件描述符会重复,并且子项和父项都指向同一个OFD。有两个引用相同OFD的FD通常不是问题,但特别是对于套接字,它们可能会有细微的问题,因为只有当你关闭所有引用它的FD时才会关闭连接。 / p>

  2. 您应该考虑使用线程(如果使用线程,请不要关闭套接字!)。 clone是一个linux系统调用,不能直接使用。你的另一种选择是使用共享内存,但它更复杂。

答案 2 :(得分:0)

分叉重复文件描述符,因此您必须关闭副本。

分叉也有效地复制了所有内存(虽然实际上它是写时复制的,所以它并不是非常昂贵)。您创建一个新的进程,它与父进程完全分开,除非您明确设置了一些共享内存。

也许你打算产生一个新的线程而不是分支一个新的进程

答案 3 :(得分:0)

我想您可能希望查看this book作为fork()的参考。

  1. 是的,您确实需要关闭绑定的套接字以侦听子进程中的子套接字套接字。整数aka文件句柄指向真实结构see this,因此除非您希望内核在子节点上转储新连接或父节点能够将数据发送到连接的客户端,否则您可能希望完全阻止这种情况。
  2. 要在进程之间共享数据,最好的方法是共享内存。我推荐你的那本书也会有相关的信息。通常,如果您需要共享内存而没有共享内存,那么您可能需要查看线程。
  3. P.S。我不确定你指的是哪种clone()方法。对象复制是通过复制构造函数完成的。