写一个linux守护进程的最佳方式

为了工作,我需要编写一个tcp守护进程来响应我们的客户端软件,并想知道是否有任何提示最好的方法去做这件事。

我应该为每一个新的连接fork通常我会使用线程?

这取决于你的应用程序。 线程和分支都是完全有效的方法,也是单线程事件驱动模型的第三种选择。 如果你可以更详细地解释你正在写什么,那么在提供建议的时候会有所帮助。

值得一提的是,这里有一些一般的指导原则:

  • 如果你没有共享状态,使用分叉。
  • 如果您有共享状态,请使用线程或事件驱动的系统。
  • 如果在大量连接的情况下需要高性能,请避免分叉,因为它具有较高的开销(特别是内存使用)。 而是使用线程,事件循环或多个事件循环线程(通常每个CPU一个)。

通常分叉将是最容易实现的,因为一旦你分叉,你基本上可以忽略所有其他的连接。 由于额外的同步要求,线程下一个最困难; 事件循环由于需要把你的处理变成状态机而变得更加困难; 并且多个线程运行事件循环最困难(由于结合其他因素)。

我建议任何一天都要通过线程来获取连接。 线程的问题是共享内存空间,操纵另一个线程的内存是多么容易。 对于分叉的进程,进程之间的任何通信都必须由您来有意地完成。

刚刚搜索,发现这个答案: 什么是叉的目的? 。 你显然知道这个答案,但是该线程中的#1答案在fork()的优点上有很好的意义。

除了@ hobodave的很好的答案之外,“每连接分叉”的另一个好处是你可以很简单地使用inetd或者tcpserver等实现你的服务器:然后你可以使用标准输入和标准输出来与套接字进行通信,不必进行任何监听套接字管理(监听连接等)等。

另一个选项当然是预分配守护进程的几个副本,让每个守护进程保持生命并继续回答请求。 这一切都取决于您的应用程序,预期的负载和性能要求,等等。

最简单最简单的方法是编写一个基于inetd的守护进程; 你的软件可以忽略它通过TCP连接运行的事实,只需通过stdin / stdout处理输入/输出。 这在绝大多数情况下运作良好。

如果你不打算每秒钟都有很多新的连接,可以考虑从inetd运行。 除此以外…

下载OpenSSH源码。 他们已经把许多工作放在了特权分离的恰到好处之中,它是可移植的,而且为了安全而进行的审查不仅仅是其他任何事情。

适应你的需求,你可能会扔掉它的大部分。 遵守当然的许可协议。 遵循未来的补丁与良好的SCC。

不要担心分叉进程vs线程的性能,除非你有充分的证据,这是一个真正的问题。 Apache只用简单的每个客户端模式运行了多年,最繁忙的站点。

如果你真的有野心,你可以使用某种非阻塞的异步IO模型。 我喜欢Boost.Asio,但是我很沉迷于C ++。

确保您的代码正确处理信号。 HUP重新加载配置。 TERM正常关机。

不要试图写自己的日志文件。 只能使用系统日志,或只写入可以重定向到syslog的stderr。 试图在home-rolled服务器上设置logrotate是一个真正的痛苦,所有的日志记录都略有不同。

如果你想避免所有的线程/分叉,我会建议使用所有非阻塞的I / O和libevent 。 Libevent作为事件驱动编程的高性能解决方案而广为人知。

看看ACE(C ++ / Java) 。 它有许多线程,事件和分叉TCP反应器,可以满足您的通信需求。 你也可以看看Boost ASIO做些类似的事情