如何在接收到SIGHUP信号后在Linux中重新启动C守护程序

任何人都可以张贴一些示例代码,以了解如何重新读取configuration文件,并在守护程序收到SIGHUP信号后重新启动守护程序。 守护进程是Linux上用C语言编写的用户空间程序,不是由inetd启动的。

根据程序编写的干净程度,至少有三种方法可以做到这一点:

  1. 接收到信号后,在初始化阶段(可能 – 但不一定 – )通过setjmp()/ longjmp()或sigsetjmp()/ siglongjmp()对)返回到程序的开始,从而重置并重新读取配置文件。

  2. 在收到信号后,让信号处理程序再次执行原始程序。 这具有失去所有状态并将所有全局变量和静态变量重置为其原始状态的优点。 它有失去以前所有状态的缺点。

  3. 第三种选择也许不那么残忍, 它会注意到信号已经被接收,并且在主处理循环的下一个方便的位置,将返回并重新读取配置文件。

什么起作用部分取决于你的守护进程要做什么。 如果花费时间与客户交谈,则可能不想使用选项1或2中的任何一个 – 您更愿意使用选项3.如果您对简单问题进行一次性回答,那么残酷的方法可能是有效(可能更简单的编程)。 请注意,选项1需要仔细处理WIP(正在进行中的工作)以及诸如打开的文件之类的东西 – 如果不小心,将丢失资源跟踪,并且守护程序将失败(内存不足,文件描述符不足 – 最有可能是这两个之一)。

我发现这个页面,因为我正在寻找一个自己的例子,以确保我做的正确。 既然没有这个例子,我会发布我的尝试,让别人评论一下:

volatile sig_atomic_t g_eflag = 0; volatile sig_atomic_t g_hupflag = 1; static void signal_handler(int sig) { switch(sig) { case SIGHUP: g_hupflag = 1; break; case SIGINT: case SIGTERM: g_eflag = 1; break; } } int main(int argc, char **argv) { signal(SIGINT, signal_handler); signal(SIGTERM, signal_handler); signal(SIGHUP, signal_handler); signal(SIGPIPE, SIG_IGN); while(!g_eflag) { if(g_hupflag) { g_hupflag = 0; load_config(); } // ... do daemon work ... } return 0; } 

另一个稍微详细的例子就是在这里:

http://man7.org/tlpi/code/online/dist/daemons/daemon_SIGHUP.c.html

取决于你如何构建它; 如果在单个线程/进程中处理多个连接,那么在重新加载配置(或exec本身)之前,您应该以某种方式通知他们退出(如果可以的话;取决于协议)。

如果协议允许你说“离开,然后再回来”,那么显然这是一个很好的胜利。 如果客户端需要保持连接,那么可以将配置更改应用于已连接的客户端(如果是单进程单线程守护进程),这是否合理。

如果是多进程,事情会变得更复杂。 您必须通知有关新配置的流程,或者确保它们继续旧配置,或者在客户端退出时可以选择新的配置。

如果它是多线程的话,那么这些线程将需要安全地读取新配置,这些配置可能需要锁定,或者可以为新的配置结构分配内存并进行切换不知何故,