热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

《Unix环境高级编程》读书笔记第13章守护进程

1.引言守护进程是生存期长的一种进程。它们常常在系统引导装入时启动,仅在系统关闭时才终止。它们没有控制终端,在后台运行。本章说明守护进程结构、如何编写守护进程程序、守护进程如何报告

1. 引言

  • 守护进程是生存期长的一种进程。它们常常在系统引导装入时启动,仅在系统关闭时才终止。它们没有控制终端,在后台运行。
  • 本章说明守护进程结构、如何编写守护进程程序、守护进程如何报告出错情况。

2. 守护进程的特征

  • 基于BSD的系统下执行:ps -axj

    -a 显示由其他用户所拥有的进程的状态;-x 显示没有控制终端的进程状态;-j 显示与作业有关的信息

  • 基于System V的系统下执行:ps -efj
  • Linux下执行以上两个命令输出一致
  • 常见的守护进程:
  • kswapd,内存换页守护进程。
  • flush守护进程在可用内存达到设置的最小阀值时将脏页面冲洗至磁盘。
  • sync_supers守护进程定期将文件系统元数据冲洗至磁盘。
  • jbd守护进程帮助实现了ext4文件系统中的日志功能。
  • rpcbind守护进程提供了将远程过程调用程序号映射为网络端口号的服务。
  • rsyslogd守护进程可以被由管理员启用的将系统消息记入日志的任何程序使用。
  • inetd守护进程。超级因特网服务进程。
  • crond守护进程在定期安排的日期和时间执行命令。
  • atd守护进程,允许用户在指定的时间执行任务,但是每个任务只执行一次。
  • sshd守护进程提供了安全的远程登录和执行设施。
  • cupsd守护进程,打印假脱机进程,处理对系统提出的各个打印请求。

3. 编程规则

  • 在编写守护进程程序时需遵循一些基本规则,以防止产生不必要的交互作用。
    1. 调用umask将文件模式创建屏蔽字设置为一个已知值(通常为0)。
    2. 调用fork,然后使父进程exit。因为:第一,如果守护进程是通过shell启动的,这可以让shell认为这条命令已经执行完毕;第二,子进程继承了父进程的进程组ID,但获得一个新的进程ID,这保证了子进程不是一个进程组的组长进程。这是setsid的先决条件。
    3. 调用setsid创建一个新会话。使调用进程:a. 成为新会话的首进程;b. 成为一个新进程组的组长进程;c. 没有控制终端
    4. 将当期工作目录更改为根目录,以免占有某文件系统,使得其不能被卸载。或者,某写守护进程还可能把当前工作目录更改到某个指定位置。
    5. 关闭不再需要的文件描述符。使守护进程不再持有从其父进程继承来的任何文件描述符。可以使用open_max函数或getrlimit函数来判定最高文件描述符的值,并关闭直到该值的所有描述符。
    6. 某些守护进程打开/dev/null使其具有文件描述符0、1、2 。这样,任何一个试图读标准输入、写标准输出或标准错误的库例程都不会产生任何效果。
#include "apue.h"
#include 
#include 
#include 
void daemonize(const char *cmd)
{
  int i, fd0, fd1, fd2;
  pid_t pid;
  struct rlimit rl;
  struct sigaction sa;
 
/*
* Clear file creation mask.
*/
  umask(0);
 
/*
* Get maximum number of file descriptors.
*/
  if (getrlimit(RLIMIT_NOFILE, &rl) <0)
    err_quit("%s: can’t get file limit", cmd);
 
/*
* Become a session leader to lose controlling TTY.
*/
  if ((pid = fork()) <0)
    err_quit("%s: can’t fork", cmd);
  else if (pid != 0) /* parent */
    exit(0);
  setsid();
 
/*
* Ensure future opens won’t allocate controlling TTYs.
*/
  sa.sa_handler = SIG_IGN;
  sigemptyset(&sa.sa_mask);
  sa.sa_flags = 0;
  if (sigaction(SIGHUP, &sa, NULL) <0)
    err_quit("%s: can’t ignore SIGHUP", cmd);
  if ((pid = fork()) <0)
    err_quit("%s: can’t fork", cmd);
  else if (pid != 0) /* parent */
    exit(0);
 
/*
* Change the current working directory to the root so
* we won’t prevent file systems from being unmounted.
*/
  if (chdir("/") <0)
    err_quit("%s: can’t change directory to /", cmd);
 
/*
* Close all open file descriptors.
*/
  if (rl.rlim_max == RLIM_INFINITY)
    rl.rlim_max = 1024;
  for (i = 0; i 

4. 出错记录

     ,

  • 有以下3种产生日志消息的方法:
    1. 内核例程可以调用log函数。
    2. 大多数用户进程(守护进程)调用syslog函数来产生日志消息。
    3. 无论一个用户进程是在此主机上,还是在通过TCP/IP网络连接到此主机的其他主机上,都可将日志消息发送到UDP端口514 。
#include
void openlog(const char *ident, int option, int facility);
void syslog(int priority, const char *format, ...);
void closelog(void);
int setlogmask(int maskpri);
Returns: previous log priority mask value

5. 单实例守护进程

  • 为了正常运作,某些守护进程会实现为,在任一时刻只运行该守护进程的一个副本。
  • 文件和记录锁机制提供了一种保证一个守护进程只有一个副本在运行的方法。
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define LOCKFILE "/var/run/daemon.pid"
#define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
extern int lockfile(int);
 
int already_running(void)
{
  int fd;
  char buf[16];
  fd = open(LOCKFILE, O_RDWR|O_CREAT, LOCKMODE);
  if (fd <0) {
    syslog(LOG_ERR, "can’t open %s: %s", LOCKFILE, strerror(errno));
    exit(1);
  }
  if (lockfile(fd) <0) {
    if (errno == EACCES || errno == EAGAIN) {
      close(fd);
      return(1);
    }
    syslog(LOG_ERR, "can’t lock %s: %s", LOCKFILE, strerror(errno));
    exit(1);
  }
  ftruncate(fd, 0);   sprintf(buf, "%ld", (long)getpid());   write(fd, buf, strlen(buf)+1);   return(0); }

6. 守护进程的惯例

  • 在Unix系统中,守护进程遵循以下通用惯例:
    1. 若守护进程使用锁文件,那么该文件通常存储在/var/run目录中。守护进程可能需要具有超级用户权限才能在此目录中创建文件。锁文件的名字通常是name.pid。
    2. 若守护进程支持配置选项,那么配置文件通常存放在/etc目录中。配置文件的名字通常是name.conf。
    3. 守护进程可用命令行启动,但通常它们是由系统初始化脚本之一启动的。
    4. 某些守护进程捕捉SIGHUP信号,当它们接收到该信号时,重新读配置文件。

7. 客户进程-服务器进程模型

  • 守护进程常常用作服务器进程。
  • 一般而言,服务器进程等待客户进程与其联系,提出某种类型的服务要求。
  • 在服务器进程中调用fork然后exec另一个程序来项客户进程提供服务是很常见的。服务器进程通常管理着多个文件描述符:通信端点、配置文件、日志文件和类似的文件。为保证安全,可设置所有对于被执行程序不需要的文件描述符的执行关闭标志close-on-exec。

    原创文章,转载请声明出处:http://www.cnblogs.com/DayByDay/p/3948402.html

《Unix环境高级编程》读书笔记 第13章-守护进程


推荐阅读
  • 1. 设置用户密码:使用 `slappasswd` 工具生成加密密码,确保账户安全。具体步骤如下:输入命令 `slappasswd -s NewPassword`,系统将提示重新输入新密码,并生成加密后的哈希值 {SSHA}xxxxxxxxxxxxxxxxx。2. 编写配置文件:编辑 `vildapus` 配置文件,添加必要的用户账户信息,以确保新用户能够顺利登录系统。 ... [详细]
  • 微软推出Windows Terminal Preview v0.10
    微软近期发布了Windows Terminal Preview v0.10,用户可以在微软商店或GitHub上获取这一更新。该版本在2月份发布的v0.9基础上,新增了鼠标输入和复制Pane等功能。 ... [详细]
  • Windows环境下详细教程:如何搭建Git服务
    Windows环境下详细教程:如何搭建Git服务 ... [详细]
  • ATL(ActiveTEmplateLibrary)活动模板库RPC(RemoteProcedureCallProtocol)远程过程调用协议DCE(DistributedComp ... [详细]
  • Python 数据可视化实战指南
    本文详细介绍如何使用 Python 进行数据可视化,涵盖从环境搭建到具体实例的全过程。 ... [详细]
  • 解决Bootstrap DataTable Ajax请求重复问题
    在最近的一个项目中,我们使用了JQuery DataTable进行数据展示,虽然使用起来非常方便,但在测试过程中发现了一个问题:当查询条件改变时,有时查询结果的数据不正确。通过FireBug调试发现,点击搜索按钮时,会发送两次Ajax请求,一次是原条件的请求,一次是新条件的请求。 ... [详细]
  • 第二十五天接口、多态
    1.java是面向对象的语言。设计模式:接口接口类是从java里衍生出来的,不是python原生支持的主要用于继承里多继承抽象类是python原生支持的主要用于继承里的单继承但是接 ... [详细]
  • CentOS 7 中 iptables 过滤表实例与 NAT 表应用详解
    在 CentOS 7 系统中,iptables 的过滤表和 NAT 表具有重要的应用价值。本文通过具体实例详细介绍了如何配置 iptables 的过滤表,包括编写脚本文件 `/usr/local/sbin/iptables.sh`,并使用 `iptables -F` 清空现有规则。此外,还深入探讨了 NAT 表的配置方法,帮助读者更好地理解和应用这些网络防火墙技术。 ... [详细]
  • 浏览器作为我们日常不可或缺的软件工具,其背后的运作机制却鲜为人知。本文将深入探讨浏览器内核及其版本的演变历程,帮助读者更好地理解这一关键技术组件,揭示其内部运作的奥秘。 ... [详细]
  • FreeBSD环境下PHP GD库安装问题的详细解决方案
    在 FreeBSD 环境下,安装 PHP GD 库时可能会遇到一些常见的问题。本文详细介绍了从配置到编译的完整步骤,包括解决依赖关系、配置选项以及常见错误的处理方法。通过这些详细的指导,开发者可以顺利地在 FreeBSD 上完成 PHP GD 库的安装,确保其正常运行。此外,本文还提供了一些优化建议,帮助提高安装过程的效率和稳定性。 ... [详细]
  • V8不仅是一款著名的八缸发动机,广泛应用于道奇Charger、宾利Continental GT和BossHoss摩托车中。自2008年以来,作为Chromium项目的一部分,V8 JavaScript引擎在性能优化和技术创新方面取得了显著进展。该引擎通过先进的编译技术和高效的垃圾回收机制,显著提升了JavaScript的执行效率,为现代Web应用提供了强大的支持。持续的优化和创新使得V8在处理复杂计算和大规模数据时表现更加出色,成为众多开发者和企业的首选。 ... [详细]
  • 使用Jsoup解析并遍历HTML文档时,该库能够高效地生成一个清晰、规范的解析树,即使源HTML文档存在格式问题。Jsoup具备强大的容错能力,能够处理多种异常情况,如未闭合的标签等,确保解析结果的准确性和完整性。 ... [详细]
  • 在使用Eclipse进行调试时,如果遇到未解析的断点(unresolved breakpoint)并显示“未加载符号表,请使用‘file’命令加载目标文件以进行调试”的错误提示,这通常是因为调试器未能正确加载符号表。解决此问题的方法是通过GDB的`file`命令手动加载目标文件,以便调试器能够识别和解析断点。具体操作为在GDB命令行中输入 `(gdb) file `。这一步骤确保了调试环境能够正确访问和解析程序中的符号信息,从而实现有效的调试。 ... [详细]
  • 综合实训 201521440015
    Chinesepeople’publicsecurityuniversity网络对抗技术实验报告实验五综合渗透学生姓名常泽远年级15区队4指导教师高见信息技术与网络安全学院2018 ... [详细]
  • Panabit应用层流量管理解决方案
    Panabit是一款国内领先的应用层流量管理解决方案,提供高度开放且免费的专业服务,尤其擅长P2P应用的精准识别与高效控制。截至2009年3月25日,该系统已实现对多种网络应用的全面支持,有效提升了网络资源的利用效率和安全性。 ... [详细]
author-avatar
蒣彬彬
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有