Linux 守护进程Linux 守护进程概述Linux Daemon(守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。它不需要用户输入就能运行而且提供某种服务,不是对整个系统就是对某个用户程序提供服务。Linux系统的大多数服务器就是通过守护进程实现的。常见的守护进程包括系统日志进程syslogd、 web服务器httpd、邮件服务器sendmail和数据库服务器mysqld等。

  守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行。守护进程经常以超级用户(root)权限运行,因为它们要使用特殊的端口(1-1024)或访问某些特殊的资源。

  一个守护进程的父进程是init进程,因为它真正的父进程在fork出子进程后就先于子进程exit退出了,所以它是一个由init继承的孤儿进程。守护进程是非交互式程序,没有控制终端,所以任何输出,无论是向标准输出设备stdout还是标准出错设备stderr的输出都需要特殊处理。

  工作原理

  Linux 守护进程的工作模式是服务器/客户机(Server/Client),服务器在一个特定的端口上监听(Listen)等待客户连接,连接成功后服务器和客户端通过端口进行数据通信。守护进程的工作就是打开一个端口,并且监听(Listen)等待客户连接。如果客户端产生一个连接请求,守护进程就创建(Fork)一个子服务器响应这个连接,而主服务器继续监听其他的服务请求。

  工作模式

  Linux 守护进程有两种工作模式:stand-alone模式和xinetd模式。

  (1)stand-alone模式

  独立运行的守护进程由init负责管理,所有独立运行守护进程的脚本在/etc/rc.d/init.d/目录下。独立运行的守护进程工作方式称作stand-alone,是Unix传统的C/S模式的访问模式。服务器监听(Listen)在一个特点的端口上等待客户端的联机。如果客户端产生一个连接请求,守护进程就创建(Fork)一个子服务器响应这个连接,而主服务器继续监听。工作在stand-alone模式下的网络服务有route、gated、web服务器等。在Linux系统中通过stand-alone工作模式启动的服务由/etc/rc.d/下面对应的运行级别当中的符号链接启动。

  (2)xinetd模式

  从守护进程的概念可以看出,对于系统所要求的每一种服务,都必须运行一个监听某个端口连接所发生的守护进程,这意味着资源浪费。为了解决这个问题,Linux引进了"网络守护进程服务程序"的概念。Redhat Linux使用的网络守护进程是xinted(eXtended InterNET Daemon)。和stand-alone模式相比xinetd模式也称 Internet Super-Server(超级服务器)。xinetd能够同时监听多个指定的端口,在接受用户请求时,他能够根据用户请求的端口不同,启动不同的网络服务进程来处理这些用户请求。可以把xinetd看做一个管理启动服务的管理服务器,它决定把一个客户请求交给那个程序处理,然后启动相应的守护进程。

  和stand-alone工作模式相比,系统不必为每一个网络服务进程监听其服务端口,运行xinetd守护进程就可以同时监听所有服务端口,这样就降低了系统开销,保护系统资源。但是对于访问量大、经常出现并发访问时,xinetd想要频繁启动对应的网络服务进程,反而会导致系统性能下降。一般来说系统一些负载高的服务,比如Apache、sendmail等服务是单独启动的。而其他服务类型都可以使用xinetd超级服务器管理。

  查看系统为Linux服务提供那种模式方法在Linux命令行可以使用pstree命令可以看到两种不同方式启动的网络服务。

  Linux 守护进程管理Linux提供了几种不同的守护进程管理工具: ntsysv、chkconfig等,可以根据具体需要灵活运用。

  (1)ntsysv

  ntsysv 工具为启动或关闭由xinetd管理的服务提供了简单的界面,也可以使用 ntsysv 来配置运行级别。按照默认设置,只有当前运行级别会被配置。要配置不同的运行级别,使用 --level 选项来指定一个或多个运行级别。比如,命令 ntsysv --level 345 配置运行级别3、4、和5。使用上下箭头来上下查看列表。使用空格键来选择或取消选择服务,或用来"按"「确定」和「取消」按钮。要在服务列表和「确定」、「取消」按钮中切换,使用 [Tab]键。* 标明某服务被设为启动。[F1] 键会弹出每项服务的简短描述。

  (3)chkconfig

  Chkconfig工具可以用来启动或停止服务。

  chkconfig --list 命令显示系统服务列表,以及这些服务在运行级别0到6中已被启动(on)还是停止(off),还显示xinetd管理的系统服务。

  chkconfig 还能用来设置某一服务在某一指定的运行级别内被启动还是被停运。比如,要在运行级别3、4、5中停运 nfs 服务,使用下面的命令: chkconfig --level 345 nfs off

  查看系统为Linux服务提供那种模式方法在Linux命令行可以使用pstree命令可以看到两种不同方式启动的网络服务。

  Linux 守护进程列表

  守护进程

  含义

  alsasound

  Alsa声卡驱动的守护程序

  acpid

  替代传统APM电源管理标准的新型电源管理标准(Advanced Configuration and Power Interface Daemon)的守护进程

  atalk

  AppleTalk网络的守护进程

  amd

  自动安装NFS的守护进程

  anacron

  自动运行任务的守护进程

  apmd

  高级电源管理(Advanced Power Management)的守护进程

  arpwatch

  记录日志并构建一个在LAN接口上看到的以太网地址和IP地址的进程

  atd

  at和batch命令的守护进程

  autofs

  自动安装管理进程的守护进程,与NFS相关,依赖于NIS服务器

  bootparamd

  引导参数服务器,为LAN上的无盘工作站提供引导所需的相关信息

  bluetooch

  蓝牙服务的守护进程

  crond

  Cron服务的守护进程,该程序周期地运行用户调度的任务

 .Linux 守护进程 Daemon . chargen

  使用tcp协议的chargen server,(Character Generator Protocol)是一种网络服务,主要功能是提供类似远程打字的功能

  chargen-udp

  使用udp协议的chargen server的守护进程

  cpuspeed

  监测系统空闲百分比,降低或加快CPU时钟速度和电压的守护进程

  dhcpd

  动态主机控制协议(Dynamic Host Control Protocol)服务的守护进程

  cups

  提供第三代打印功能的守护进程(Common UNIX Printing System)

  daytime

  使用tcp 协议日期时间的守护进程,该协议为客户机实现从远程服务器获取日期和时间的功能

  daytime-udp

  使用udp协议日期时间的守护进程

  dc_server

  使用SSL安全套接字代理服务器的守护进程

  dc_client

  使用SSL安全套接字客户端的守护进程

  diskdump

  服务器磁盘备份的守护进程

  echo

  服务器回显客户数据服务的守护进程

  echo-udp

  使用udp协议的服务器回显客户数据服务守护进程

  gated

  网关路由的守护进程

  gpm

  为文本模式下的Linux程序如mc(Midnight Commander)提供鼠标的支持的守护进程(General Purpose Mouse Daemon)

  httpd

  Web服务器Apache的守护进程

  inetd

  网络管理的守护进程

  innd

  Usenet新闻服务器的守护进程

  iiim

  中文输入法服务器的守护进程

  iptables

  防火墙功能的守护进程

  irda

  红外功能的守护进程

  isdn

  isdn启动和中止服务的守护进程

  krb5-telnet

  使用kerberos 5认证的telnet守护进程

  klogin

  远程登陆的守护进程

  irqbalance

  对多个系统处理器环境下的系统中断请求进行负载平衡的守护进程

  kshell

  Kshell服务器的守护进程

  kudzu

  硬件自动检测的守护进程,自动检测硬件的添加、删除等

  ldap

  目录访问协议服务器的守护进程(Lightweight Directory Access Protocol)

  lm_seroems

  检测主板工作情况的守护进程

  lpd

  老式打印服务的守护进程

  mdmonitor

  RAID相关设备的守护程序

  mysqld

  Mysql数据库的守护进程

  named

  名称服务器的守护进程

  netplugd

  网络接口管理的守护进程(Network Cable Hot Plug Management Daemon)

  netdump

  远程网络备份服务器的守护进程

  netfs

  安装和卸载NFS、SAMBA和NCP网络文件系统的守护进程(Network Filesystem Mounter)

  ntpd

  使系统和一个精确的时间源保持时间同步的协议守护进程(Network Time Protocol Daemon)

  network

  激活、关闭网络接口的守护进程

  pcmcia

  支持笔记本PCMCIA服务的守护进程

  portmap

  支持RPC连接的守护进程,RPC被用于NFS以及NIS 等服务

  postgresql

  PostgreSQL数据库的守护进程

  random

  随机数生成器的守护进程

  rawdevices

  使用集群文件系统时用于加载raw设备的守护进程

  routed

  支持RIP协议的自动IP路由表维护的守护进程

  rsync

  远程数据备份(Remote Sync)的守护进程

  rsh

  Shell服务器的守护进程

  sendmail

  邮件服务器的守护进程

  smb

  Samba文件共享/打印服务的守护进程

  snmpd

  本地简单网络管理的守护进程

  squid

  代理服务器squid守护进程

  sshd

  OpenSSH(Secure Shell Protocol)服务器的守护进程

  smartd

  监控硬盘的守护进程(Self Monitor Analysis and Reporting Technology System)

  syslog

  系统引导时启动syslog和klogd系统日志守护进程的程序

  time

  使用tcp协议从远程主机获取时间和日期的守护进程

  time-udp

  使用udp协议从远程主机获取时间和日期的守护进程

  tux

  在Linux内核中运行apache服务器的守护进程

  vsftpd

  vsftp服务器的守护进程

  vncserver

  VNC服务(Virtual Network Computing虚拟网络计算)的守护进程

  xfs

  X Window字型服务器的守护进程,为本地和远程X服务器提供字型集

  xinetd

  支持多种网络服务的核心守护进程

  ypbind

  使客户进程能绑定或连接到网络信息系统(Network Information System)服务器的守护进程

  yppasswdd

  网络信息系统NIS口令服务器的守护进程

  ypserv

  网络信息系统NIS主服务器的守护进程

  yum

  自动升级和软件包管理的守护进程

  运行不必要或有漏洞的守护进程会给操作系统带来安全和性能上的影响。如果操作系统中的任何一个漏洞,都可能使整个系统受到攻击。所以,增加系统安全的最佳办法就是尽量监视系统的功能。对于一些重要的守护进程,比如crond、syslog、keytable、xinetd、kudzu、iptables等是需要运行的;echo、echo-udp、daytime、daytime-udp、chargen、chargen-udp主要是做调试用,普通用户基本用不到,可以关闭。

  r字开头的守护进程:rsh、rstatd、rsync、rusersd、rwalld这些命令都是Berkley远程命令,因为都以字母r开头,故称r*命令。主要使用来使一台计算机上的某个用户以相同的帐户远程执行另一台计算机的一个程序。但是,r命令已经被证实存在安全风险。对于确实需要的守护进程,应该尽量选用最新的版本程序,并增加其安全防范。 另外我们还要合理选择守护进程例如innd是运行新闻组服务的进程,如果用户不做Usenet服务器,应该关掉。

  Linux 守护进程编程守护进程最重要的特性是后台运行;其次守护进程必须与其运行前的环境隔离开来,这些环境包括未关闭的文件描述符,控制终端,会话和进程组,工作目录以及文件创建模式等。这些环境通常是守护进程从执行它的父进程(特别是shell)中继承下来的;最后守护进程的启动方式有其特殊之处。它可以在Linux系统启动时从启动脚本/etc/rc.d中启动,可以由作业规划进程crond启动,还可以由用户终端(通常是shell)执行。

  总之,除开这些特殊性以外,守护进程与普通进程基本上没有什么区别。因此,编写守护进程实际上是把一个普通进程按照上述的守护进程的特性改造成为守护进程。

  编写守护进程的步骤:

  (1)在父进程中执行fork并exit推出;

  (2)在子进程中调用setsid函数创建新的会话;

  (3)在子进程中调用chdir函数,让根目录 ”/” 成为子进程的工作目录;

  (4)在子进程中调用umask函数,设置进程的umask为0;

  (5)在子进程中关闭任何不需要的文件描述符

  Setsid函数

  #include <unistd.h>

  pid_t setsid(void);

  返回值:成功返回新会话的ID;失败返回-1

  setsid函数创建一个新会话和新进程组,setsid调用保证新会话没有控制终端。

  守护进程调用该函数将成为新会话的会话领导和新进程组的进程组领导。

  chdir函数

  #include <unistd.h>

  int chdir(const char *path);

  chdir函数改变当前的工作目录为path所包含的新目录

  umask函数

  #include

  void umask(int mask); // r-4; w-2; x-1

  umask函数改变目录和文件的创建模式。

  第一个守护进程

  $ vi mydaemon1.c

  /* mydaemon1.c */

  #include <stdio.h>

  #include <stdlib.h>

  #include <string.h>

  #include <unistd.h>

  #include <time.h>

  #include <errno.h>

  #include <syslog.h>

  #include <fcntl.h>

  #include <sys/stat.h>

  #include <sys/types.h>

  int main(void)

  {

  pid_t pid, sid;

  time_t timebuf;

  int fd, len;

  char *buf;

  // 创建子进程,然后父进程退出

  pid = fork();

  if(pid < 0){

  perror("fork");

  exit(EXIT_FAILURE);

  }else if(pid > 0){ // 父进程

  exit(EXIT_SUCCESS);

  }

  // 子进程

  // 创建新会话和新进程组

  if((sid = setsid()) < 0){

  perror("setsid");

  exit(EXIT_FAILURE);

  }

  // 改变当前的工作目录到根目录

  if((chdir("/")) < 0){

  perror("chdir");

  exit(EXIT_FAILURE);

  }

  // 改变目录文件的创建模式

  umask(0);

  // 关闭不必要的文件描述符

  close(STDIN_FILENO);

  close(STDOUT_FILENO);

  close(STDERR_FILENO);

  // malloc buf

  len = strlen(ctime(&timebuf));

  buf = malloc(len+1);

  // 子进程主要工作,每10秒钟向日志文件写入当前的时间

  while(1)

  {

  if((fd = open("/var/log/mydaemon.log", \

  O_CREAT | O_WRONLY | O_APPEND, 0600)) < 0){

  perror("open file");

  exit(EXIT_FAILURE);

  }

  time(&timebuf);

  bzero(buf, len+1);

  strncpy(buf, ctime(&timebuf),len+1);

  write(fd, buf, len+1);

  close(fd);

  sleep(10);

  }

  free(buf);

  exit(EXIT_SUCCESS);

  }