13.守护进程

因为没有控制终端,在后台运行,所以需要了解出现问题时如何报告出错情况。


1.守护进程的特征

  • 1.1 父进程ID为0的通常是内核进程(系统引导装入过程的一部分而启动)
    • kswapd:内存换页守护进程
    • flush:内存达到最小阈值时(也定期)将脏页面冲洗至磁盘
    • sync_supers:定期将文件系统元数据冲洗至磁盘
    • jbd:ext4文件系统中的日志功能
  • 1.2 进程1通常是init,是系统守护进程,负责启动各层次特定的系统服务。
    • rpcbind:提供远程过程调用
    • rsyslogd:将系统消息记入日志(管理员启用的任何程序使用)
    • inetd:侦听系统网络接口
    • cron:在定期安排的日期和时间执行
    • atd:允许用户在指定的时间执行任务
    • cpusd:打印假脱机进程,处理对系统提出的各个打印请求
    • sshd:安全远程登录和执行设施

2.编程规则

  • 1.umask设置文件屏蔽字为一个已知值
  • 2.调用fork,然后父进程exit
    • 如果是作为一条简单的shell命令,让shell认为该命令已执行完毕
    • 获得了新的PID,保证了子进程不是一个进程组的组长进程
  • 3.setsid创建新会话
    • 称为新会话的首进程
    • 成为新进程组的组长进程
    • 没有控制终端
  • 3.5.设置屏蔽信号重复步骤2
  • 4.更改工作目录为根(或其他特定位置)
    • 如果工作在挂载的文件系统中,那该文件系统就不能被卸载
  • 5.关闭不再需要的文件描述符
  • 6.某些守护进程打开/dev/null,不与终端设备关联

3.出错记录

  • 一般有一个集中的守护进程出错记录设施
  • 有三种产生日志消息的方法(rsyslogd读取):
    • 内核例程调用log函数
    • 大多数用户进程调用syslog产生
    • 可以将日志消息发向UDP514端口(UNIX域套接字)
      #include <syslog.h>
      void openlog(const char *ident, int option, int facility);
      void syslog(int priority, const char *format, ...);
      void closelog(void);
      #include <stdarg.h>
      void vsyslog(int priority, const char *format, va_list ap);
      
    • 如:
      openlog("hzq test:", LOG_CONS|LOG_PID|LOG_PERROR, LOG_USER);
      syslog(LOG_ERR, "this is test string \n");
      

4.单实例守护进程

某些进程可能需要排它的访问一个设备

  • 文件和记录锁机制为一种方法提供了基础
    • 一个文件只允许被加一次锁-lockfd(fd)
    • 守护进程终止时锁会被自动删除

5.守护进程的惯例

  • 1.使用锁则文件通常放在/var/run,名字通常是name.pid
  • 2.若支持配置选项,则通常放在/etc目录中,名字通常是name.conf
  • 3.守护进程可用命令启动,但通常是系统初始化脚本之一
  • 4.若有配置文件,启动时读取,或者接受到SIGHUP时重新读取配置文件:
    struct sigaction	sa;
    sa.sa_handler = sighup;
    sigemptyset(&sa.sa_mask);
    sigaddset(&sa.sa_mask, SIGTERM);
    sa.sa_flags = 0;
    if (sigaction(SIGHUP, &sa, NULL) < 0) {
        syslog(LOG_ERR, "can't catch SIGHUP: %s", strerror(errno));
        exit(1);
    }
    void sighup(int signo)
    {
        syslog(LOG_INFO, "Re-reading configuration file");
        reread();
    }
    

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

  • 守护进程常常用作服务器进程,服务器通常管理着多个多个文件描述符:通信端点、配置文件、日志文件等,fork后在子进程中的恶意行为(更改服务器配置文件或欺骗客户端程序使认为正在与服务器通信而获得未授权的信息),所以打开的文件描述符最好设置FD_CLOEXEC选项
    val = fcntl(fd, F_GETFD);
    val |= FD_CLOEXEC;
    fcntl(fd, F_SETFD, val);
    
©️2020 CSDN 皮肤主题: 黑客帝国 设计师:上身试试 返回首页