如何编写一个可靠的linux守护进程

如何编写一个可靠的linux守护进程

linux服务端程序都需要提供7 * 24不间断的服务,如何保证工作进程一直不退出或者不被kill掉,常见的方法就是启动一个守护进程来检测工作进程的状态,如果发现工作进程退出,就再fork一个出来。一般的实现见下面一段代码:

// 守护进程(父进程)
int status;
for ( ; ; ) {
  if ( 0 == ( pid = fork()) ) {
  // 工作进程(子进程)
  run();
  }
  waitpid(-1, &status, 0);
  if (WIFEXITED(status))
  if (WEXITSTATUS(status) == 0)
    exit(0);
  if (WIFSIGNALED(status)) {
    switch (WTERMSIG(status)) {
      case SIGKILL:
        exit(0);
        break;
      case SIGINT:
      case SIGTERM:
        exit(1);
      default:
        break;
    }
  }
}

守护进程fork出工作进程之后,就阻塞在waitpid系统调用,等待工作进程的退出,waitpid返回之后,根据status选择继续fork工作进程还是退出守护进程。status为int型变量,但只用到了低16位(见struct wait),0-6位表示使子进程退出的信号(可以通过 $kill -l 查看信号的值),8-15位表示子进程退出时的返回码(exit或者return的值)。

struct wait{
  # if __BYTE_ORDER == __LITTLE_ENDIAN
  unsigned int __w_termsig:7; /* Terminating signal. */
  unsigned int __w_coredump:1; /* Set if dumped core. */
  unsigned int __w_retcode:8; /* Return code if exited normally. */
  unsigned int:16;
  # endif /* Little endian. */
};

判断status的状态可以通过下面的宏完成:

WIFEXITED(status) //子进程调用exit()或者从main return退出时为true;
WEXITSTATUS(status) //在WIFEXITED为true时,表示exit()或return的返回码;
WIFSIGNALED(status) //子进程被信号终止时为true;
WTERMSIG(status) //在WIFSIGNALED为true时,表示终止子进程信号的值;

宏的定义如下:

/* If WIFEXITED(STATUS), the low-order 8 bits of the status. */
#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
/* If WIFSIGNALED(STATUS), the terminating signal. */
#define __WTERMSIG(status) ((status) & 0x7f)
/* Nonzero if STATUS indicates normal termination. */
#define __WIFEXITED(status) (__WTERMSIG(status) == 0)
/* Nonzero if STATUS indicates termination by a signal. */
#define __WIFSIGNALED(status) \
(((signed char) (((status) & 0x7f) + 1) >> 1) > 0)

所以根据waitpid返回的status,守护进程可以清楚地知道工作进程的死因,但上面的程序有两个问题:
1. 对SIGKILL, SIGINT, SIGTERM信号,守护进程直接退出了,没有fork工作进程出来;
2. 守护进程被kill掉了,工作进程就只能裸奔了。
对于第一个问题:SIGKILL有可能是人为($kill -9 pid)发出的,也有可能是工作进程占用内存过多,被OOM掉了(关于OOM参见这里),都不是我们想要的结果,所以工作进程被SIGKILL掉,守护进程一定要将其重启。SIGINT是 CTRL+C 发出的(非daemon模式下),SIGTERM是 $killall servicename(或者 $kill pid)发出的,这两个信号都是在结束进程的时候用到,这个时候工作进程应该捕获被处理这两个信号,正常地退出(return 0;)。而守护进程只有在工作进程正常退出的情况下才完成自己的使命,否则(工作进程被其他信号结束掉,如SIGABRT, SIGKILL, SIGSEGV)重启工作进程。所以守护进程和工作进程的实现应该是下面的代码逻辑:

// 守护进程(父进程)
int status;
for ( ; ; ) {
  if ( 0 == ( pid = fork()) ) {
    // 工作进程(子进程)
    run();
    //信号处理函数signal_handler
    if (sig == SIGTERM || sig == SIGINT) {
      destroy();
      return 0;
    }
  }
  waitpid(-1, &status, 0);
  if (WIFEXITED(status) && (WEXITSTATUS(status) == 0)) exit(0);
}

对于第二个问题:守护进程的监控可以用daemontools工具集中的supervise来监控,也可以自己实现,但是不能只是通过另外一个应用程序去做,因为做守护的进程自身也需要被守护,如此循环解决不了问题。这个时候就要借助于linux系统的init进程了,因为init进程是不能被信号kill掉的(强大到无视SIGKILL)。

The only signals that can be sent task number one, the init process, are those for which init has explicitly installed signal handlers. This is done to assure the system is not brought down accidentally.

所以让init进程来守护我们的应用程序是最可靠的,看看supervise的作法:
在/etc/inittab中添加如下一行:

SV1:23:respawn:/usr/local/bin/svscanboot

每行用“:”分隔开为4个部分:
id - 该行的标识,自定义的名称SV1。
runlevels - 该行为应该发生的运行级的列表,这里在level 2和level 3下运行。
action - 应发生的行为,respawn表示init应该监视这个进程,即使其结束后也应该被重新启动。
process - 应由init启动的程序的路径。
修改完成后,可以通过$kill -HUP 1 来立刻生效。
解决了上面两个问题,守护进程和工作进程提供7 * 24小时的运行才是有保证的。Have fun!

作者:nil-zhang 转载自:http://nil-zhang.iteye.com/blog/1806356

深度学习是机器学习的一个子领域,它基于人工神经网络的研究,特别是利用多层次的神经网络来进行学习和模式识别。深度学习模型能够学习数据的高层次特征,这些特征对于图像和语音识别、自然语言处理、医学图像分析等应用至关重要。以下是深度学习的一些关键概念和组成部分: 1. **神经网络(Neural Networks)**:深度学习的基础是人工神经网络,它是由多个层组成的网络结构,包括输入层、隐藏层和输出层。每个层由多个神经元组成,神经元之间通过权重连接。 2. **前馈神经网络(Feedforward Neural Networks)**:这是最常见的神经网络类型,信息从输入层流向隐藏层,最终到达输出层。 3. **卷积神经网络(Convolutional Neural Networks, CNNs)**:这种网络特别适合处理具有网格结构的数据,如图像。它们使用卷积层来提取图像的特征。 4. **循环神经网络(Recurrent Neural Networks, RNNs)**:这种网络能够处理序列数据,如时间序列或自然语言,因为它们具有记忆功能,能够捕捉数据中的时间依赖性。 5. **长短期记忆网络(Long Short-Term Memory, LSTM)**:LSTM 是一种特殊的 RNN,它能够学习长期依赖关系,非常适合复杂的序列预测任务。 6. **生成对抗网络(Generative Adversarial Networks, GANs)**:由两个网络组成,一个生成器和一个判别器,它们相互竞争,生成器生成数据,判别器评估数据的真实性。 7. **深度学习框架**:如 TensorFlow、Keras、PyTorch 等,这些框架提供了构建、训练和部署深度学习模型的工具和库。 8. **激活函数(Activation Functions)**:如 ReLU、Sigmoid、Tanh 等,它们在神经网络中用于添加非线性,使得网络能够学习复杂的函数。 9. **损失函数(Loss Functions)**:用于评估模型的预测与真实值之间的差异,常见的损失函数包括均方误差(MSE)、交叉熵(Cross-Entropy)等。 10. **优化算法(Optimization Algorithms)**:如梯度下降(Gradient Descent)、随机梯度下降(SGD)、Adam 等,用于更新网络权重,以最小化损失函数。 11. **正则化(Regularization)**:技术如 Dropout、L1/L2 正则化等,用于防止模型过拟合。 12. **迁移学习(Transfer Learning)**:利用在一个任务上训练好的模型来提高另一个相关任务的性能。 深度学习在许多领域都取得了显著的成就,但它也面临着一些挑战,如对大量数据的依赖、模型的解释性差、计算资源消耗大等。研究人员正在不断探索新的方法来解决这些问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值