鸟哥的Linux私房菜 第十八章、认识系统服务 (daemons)

什么是 daemon 与服务 (service)

Linux Daemon (守护进程)是运行在后台的一种特殊进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些事件。它不需要用户输入就能运行并且提供某种服 务,不是对整个系统就是对某个用户程序提供服务。 Linux 系统的大多数服务器就是通过守护进程实现的。常见的守护进程包括系统日志进程 syslogd 、 web 服务器 httpd 、邮件服务器 sendmail 和数据库服务器 mysqld 等。
 
守护进程一般在系统启动时开始运行,除非强行终止,否则直到系统关机都保持运行。守护进程经常以超级用户( root )权限运行,因为它们要使用特殊的端口( 1-1024 )或访问某些特殊的资源。
 
一个守护进程的父进程是 init 进程,因为它真正的父进程在 fork 出子进程后就先于子进程 exit 退出了,所以它是一个由 init 继承的孤儿进程。守护进程是非交互式程序,没有控制终端,所以任何输出,无论是向标准输出设备 stdout 还是标准出错设备 stderr 的输出都需要特殊处理。
 
工作原理
Linux 守护进程的工作模式是服务器 / 客户机( Server/Client ),服务器在一个特定的端口上监听( Listen )等待客户连接,连接成功后服务器和客户端通过端口进行数据通信。守护进程的工作就是打开一个端口,并且监听( Listen )等待客户连接。如果客户端产生一个连接请求,守护进程就创建( Fork )一个子服务器响应这个连接,而主服务器继续监听其他的服务请求。
 
 

注:Linux下可以直接调用damon函数来实现daemon进程,没必要重新实现,理解其原理即可。

在Linux中专门提供了一个函数来完成这个daemon化的过程,这个函数的原型如下

int daemon ( int __nochdir, int __noclose) ;

如果__nochdir的值为0,则将切换工作目录为根目录;如果__noclose为0,则将标准输入,输出和标准错误都重定向到/dev /null。

经过这个函数调用后的程序将运行在后台,成为一个daemon程序,而linux下大多的服务都是以此方式运行的。

我们来看一个简单的例子。例如编写例子程序test.c

#include <unistd.h>
#include <stdio.h>
int do_sth(){
    //Add what u want
    return 0;
}
int main(){
    daemon(0,0);
    while(1){
        do_sth();
        sleep(1);
    }
}

编译并运行

[ leconte@ localhost daemon] $ gcc -o test test.c
 [ leconte@ localhost daemon] $ ./ test 

程序进入了后台,通过ps查看进程情况,可以看到进程的父进程id为1,即init进程

root      3239  0.0  0.0   3920   160 ?        Ss   06:49   0:00 ./test

所谓的父进程是1这个表示怀疑

用lsof查看test进程所打开的文件,可以看到文件描述符0,1,2都被重定向到/dev/null

重定向到/dev/null也表示怀疑

并且能够看到,进程的当前工作目录(cwd)为根目录/,daemon函数已经帮我们完成了daemon化的过程,接下来我们只需要关注于程序功能的实现了。

daemon 的主要分类

依据 daemon 的启动与管理方式可以将 daemon 分为可独立启动的 stand alone , 与透过一支 super daemon 来统一管理两大类:

  • stand_alone:此 daemon 可以自行单独启动服务

stand alone 是『独立的启动』的意思。这种类型的 daemon 可以自行启动而不必透过其他机制的管理; daemon 启动并加载到内存后就一直占用内存与系统资源。最大的优点:因为是一直存在内存内持续的提供服务, 因此对于客户端的请求,stand alone 的 daemon 响应速度较快。常见的 stand alone daemon 有 WWW 的 daemon (httpd)、FTP 的 daemon (vsftpd) 等等。

  • super daemon: 由一支特殊的 daemon 来统一管理

这一种服务的启动方式则是藉由一个统一的 daemon 来负责唤起服务!这个特殊的 daemon 就被称为 super daemon 。 早期的 super daemon 是 inetd,后来被 xinetd 取代了。当没有客户端的请求时,各项服务都是未启动的状态,等到有来自客户端的请求时, super daemon 才唤醒相对应的服务。当客户端的请求结束后,被唤醒的这个服务也会关闭并释放系统资源。

这种机制的好处是: (1)由于 super daemon 负责唤醒各项服务,因此 super daemon 可以具有安全控管的机制,类似网络防火墙! (2)由于服务在客户端的联机结束后就关闭,因此不会一直占用系统资源。但是 因为有客户端的联机才会唤醒该服务,而该服务加载到内存的时间需要考虑进去,因此服务的反应时间会比较慢一些! 常见的 super daemon 所管理的服务有 telnet !

如上所示,Super daemon 是常驻在内存中的, Program 1, 2, 3 则是启动某些服务的程序 (未被启动状态)。当有客户端的请求时, Super daemon 才会去触发相关的程序加载成为 daemon 而存在于内存中,此时,客户端的请求才会被 Super daemon 导向 Daemon 1 去完成服务!当客户端的请求结束时,Daemon 1 将会被移除,图中实线的联机就会中断!

    • super daemon 的处理模式有两种,分别是这样:

      • multi-threaded (多线程):

      • single-threaded (单线程):
         

    • 如上所示,左侧为多线程的运行方式, daemon 会触发多支程序来给不同 client提供的服务,所以不论你是第几个请求者, 都可以享用 daemon 的服务。至于右侧则是单线程的方式,仅会有一支 daemon 被唤醒,第一个用户完成服务之前, 后续请求的用户就得要等待,因此它们的联机是不会成功的。
      • daemon 工作形态的类型
      • signal-control
        这种 daemon 是透过讯号来管理的,只要有任何客户端的请求进来,它就会立即启动去处理!例如打印机的服务 (cupsd)。

      • interval-control
        这种 daemon 则主要是『每隔一段时间就主动的去运行某项工作』,所以,你要作的是在配置文件指定服务要进行的时间与工作, 该服务在指定的时间才会去完成工作。atd 与 crond 就属于这种类型的 daemon  (每分钟侦测一次配置文件)




      • daemon 的命名守则

      通常会在服务的名称之后会加上一个 d ,例如例行性命令的创建的 at, 与 cron 这两个服务, 他的程序文件名会被取为 atd 与 crond,这个 d 代表的就是 daemon 的意思。


      服务与端口的对应

      系统所有的功能都是某些程序所提供的,而程序则是透过触发程序而产生的。同样的,系统提供的网络服务当然也是这样的!

      当客户端联机过来我们的主机时, 我们主机是透过埠号 (port number)区分不同的服务

      两个网址都是指向 ftp.isu.edu.tw 义守大学的 FTP 网站,但是浏览器上面显示的结果却是不一样的!这是因为我们指向不同的服务!一个是 http 这个 WWW 的服务,一个则是 ftp 这个文件传输服务。

      port 与 daemon 的对应
      图 1.2.1、 port 与 daemon 的对应,客户端连接协议不同,服务导向端口号亦不同

      事实上,为了统一整个因特网的端口号对应服务的功能,好让所有的主机都能够使用相同的机制来提供服务与要求服务, 所以就有了『通讯协议』这玩意儿。也就是说,有些约定俗成的服务都放置在同一个埠号上面啦!举例来说, 网址列上面的 http 会让浏览器向 WWW 服务器的 80 埠号进行联机的要求!而 WWW 服务器也会将 httpd 这个软件激活在 port 80, 这样两者才能够达成联机的!

      系统上有提供服务跟端口对应的配置文件: /etc/services!

[root@www ~]# cat /etc/services
....(前面省略)....
ftp             21/tcp
ftp             21/udp          fsp fspd
ssh             22/tcp                          # SSH Remote Login Protocol
ssh             22/udp                          # SSH Remote Login Protocol
....(中间省略)....
http            80/tcp          www www-http    # WorldWideWeb HTTP
http            80/udp          www www-http    # HyperText Transfer Protocol
....(底下省略)....
# <daemon name>   <port/封包协议>   <该服务的说明>

daemon 的启动脚本与启动方式

提供某个服务的 daemon 虽然只是一支程序而已,但是这支 daemon 的启动还是需要运行档、配置文件、运行环境等等, 举例来说,你可以查阅一下 httpd 这个程序 (man httpd) ,里面可谈到不少的选项与参数!此外,为了管理上面的方便, 所以通常 distribution 都会记录每一支 daemon 启动后所取得程序的 PID 在 /var/run/ 这个目录下! 在启动这些服务之前,你可能也要自行处理一下 daemon 能够顺利运行的环境是否正确等等。鸟哥这里要讲的是, 要启动一支 daemon 考虑的事情很多,并非单纯运行一支程序就够了。

为了解决上面谈到的问题,因此通常 distribution 会给我们一个简单的 shell script 来进行启动的功能。 该 script 可以进行环境的侦测、配置文件的分析、PID 文件的放置,以及相关重要交换文件案的锁住 (lock) 动作, 你只要运行该 script ,上述的动作就一口气连续的进行,最终就能够顺利且简单的启动这个 daemon!

那么这些 daemon 的启动脚本 (shell script) 放在哪里啊?还有, CentOS 5.x 通常将 daemon 相关的文件放在哪里? 以及某些重要的配置文件又是放置到哪里?基本上是放在这些地方:

  • /etc/init.d/* :启动脚本放置处
    系统上几乎所有的服务启动脚本都放置在这里!事实上这是公认的目录,我们的 CentOS 实际上放置在 /etc/rc.d/init.d/ 啦! 不过还是有配置连:结档到 /etc/init.d/ 的!既然这是公认的目录,因此建议您记忆这个目录即可!

  • /etc/sysconfig/* :各服务的初始化环境配置文件
    几乎所有的服务都会将初始化的一些选项配置写入到这个目录下,举例来说,登录档的 syslog 这支 daemon 的初始化配置就写入在 /etc/sysconfig/syslog 这里呢!而网络的配置则写在 /etc/sysconfig/network 这个文件中。 所以,这个目录内的文件也是挺重要的;

  • /etc/xinetd.conf, /etc/xinetd.d/* :super daemon 配置文件
    super daemon 的主要配置文件 (其实是默认值) 为 /etc/xinetd.conf ,不过我们上面就谈到了, super daemon 只是一个统一管理的机制,他所管理的其他 daemon 的配置则写在 /etc/xinetd.d/* 里头喔!

  • /etc/* :各服务各自的配置文件


  • /var/lib/* :各服务产生的数据库
    一些会产生数据的服务都会将他的数据写入到 /var/lib/ 目录中。举例来说,数据库管理系统 MySQL 的数据库默认就是写入 /var/lib/mysql/ 这个目录下啦!

  • /var/run/* :各服务的程序之 PID 记录处
    我们在第十七章谈到可以使用讯号 (signal) 来管理程序, 既然 daemon 是程序,所以当然也可以利用 kill 或 killall 来管理啦!不过为了担心管理时影响到其他的程序, 因此 daemon 通常会将自己的 PID 记录一份到 /var/run/ 当中!例如登录文件的 PID 就记录在 /var/run/syslogd.pid 这个文件中。如此一来, /etc/init.d/syslog 就能够简单的管理自己的程序啰。

上面谈到的部分是配置文件,那么 stand alone 与 super daemon 所管理的服务启动方式怎么作呢?他是这样做的喔:

  • Stand alone 的 /etc/init.d/* 启动

刚刚谈到了几乎系统上面所有服务的启动脚本都在 /etc/init.d/ 底下,这里面的脚本会去侦测环境、搜寻配置文件、 加载 distribution 提供的函数功能、判断环境是否可以运行此 daemon 等等,等到一切都侦测完毕且确定可以运行后, 再以 shell script 的 case....esac 语法来启动、关闭、 观察此 daemon 喔!我们可以简单的以 /etc/init.d/syslog 这个登录档启动脚本来进行说明:

[root@www ~]# /etc/init.d/syslog
用法: /etc/init.d/syslog {start|stop|status|restart|condrestart}
# 什么参数都不加的时候,系统会告诉你可以用的参数有哪些,如上所示。

范例一:观察 syslog 这个 daemon 目前的状态
[root@www ~]# /etc/init.d/syslog status
syslogd (pid 4264) 正在运行...
klogd (pid 4267) 正在运行...
# 代表 syslog 管理两个 daemon ,这两个 daemon 正在运行中啦!

范例二:重新让 syslog 读取一次配置文件
[root@www ~]# /etc/init.d/syslog restart
正在关闭核心记录器:          [  确定  ]
正在关闭系统记录器:          [  确定  ]
正在启动系统记录器:          [  确定  ]
正在启动核心记录器:          [  确定  ]
[root@www ~]# /etc/init.d/syslog status
syslogd (pid 4793) 正在运行...
klogd (pid 4796) 正在运行...
# 因为重新启动过,所以 PID 与第一次观察的值就不一样了!这样了解乎?
原文地址:https://www.cnblogs.com/ghgyj/p/4023383.html