什么是 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 ;
}
int main(){
daemon(,);
while(){
do_sth();
sleep();
}
}

编译并运行

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

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

root        0.0  0.0       ?        Ss   :   : ./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
      这个文件传输服务。


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

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

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

[root@www ~]# cat /etc/services
....(前面省略)....
ftp /tcp
ftp /udp fsp fspd
ssh /tcp # SSH Remote Login Protocol
ssh /udp # SSH Remote Login Protocol
....(中间省略)....
http /tcp www www-http # WorldWideWeb HTTP
http /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 ) 正在运行...
klogd (pid ) 正在运行...
# 代表 syslog 管理两个 daemon ,这两个 daemon 正在运行中啦! 范例二:重新让 syslog 读取一次配置文件
[root@www ~]# /etc/init.d/syslog restart
正在关闭核心记录器: [ 确定 ]
正在关闭系统记录器: [ 确定 ]
正在启动系统记录器: [ 确定 ]
正在启动核心记录器: [ 确定 ]
[root@www ~]# /etc/init.d/syslog status
syslogd (pid ) 正在运行...
klogd (pid ) 正在运行...
# 因为重新启动过,所以 PID 与第一次观察的值就不一样了!这样了解乎?

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

  1. 鸟哥的Linux私房菜——第十八章:磁盘配额quota

    视频链接:http://www.bilibili.com/video/av10892470/ 磁盘配额quota的意思是给用户进行使用磁盘额度的空间的划分,举个例子,你的百度网盘的使用空间,其他云盘的 ...

  2. 鸟哥的linux私房菜学习记录之认识系统服务(daemons)

  3. 鸟哥的linux私房菜——第十六章学习(程序管理与 SELinux 初探)

    第十六章.程序管理与 SE Linux 初探 在 Linux 系统当中:"触发任何一个事件时,系统都会将他定义成为一个程序,并且给予这个程序一个 ID ,称为 PID,同时依据启发这个程序的 ...

  4. 鸟哥的Linux私房菜——第十九章:例行命令的建立

    视频链接:http://www.bilibili.com/video/av11008859/ 1. 什么是例行性命令 (分为两种,一种是周期性的,一种是突发性的)1.1 Linux 工作排程的种类: ...

  5. 鸟哥的Linux私房菜——第十四章:Bash Shell

    视频链接:http://www.bilibili.com/video/av10094012/ 本章目录: 1. Bash shell1.1 什么是 shell ? (我们通过shell与Kernel核 ...

  6. 鸟哥的Linux私房菜——第十二章:档案的压缩与打包

    视频链接: 土豆:http://www.tudou.com/programs/view/GncwT0FJKsQ B站(推荐):http://www.bilibili.com/video/av98857 ...

  7. 鸟哥的linux私房菜——第十二章学习(Shell Scripts)

    第十二章  Shell Scripts 1.0).什么是shell scripts? script 是"脚本.剧本"的意思.整句话是说, shell script 是针对 shel ...

  8. 鸟哥的Linux私房菜——第十六章:学习Shell Scripts

    视频链接:http://www.bilibili.com/video/av10565321/ 1. 什么是 Shell Script       (shell写的脚本)1.1 干嘛学习 shell s ...

  9. 鸟哥的Linux私房菜——第十五章:正规表示法

    视频链接 B站:http://www.bilibili.com/video/av10364761/ 目录如下 1. 前言:2. 基础正规表示法:2.1 以 grep 撷取字符串 (grep -iv   ...

随机推荐

  1. linux磁盘以及文件系统

    df 查看磁盘总容量 -i 显示inodes号 -h 使用合适的单位显示磁盘大小 -m 以M为单位显示 -k 以K为单位显示 默认K显示 du 用来查看某个目录或者文件所占空间大小 参数:-abckm ...

  2. gentoo下的wpa_supplicant无线网配置

    在linux使用wpa_supplicant获得无线网的最痛苦的是莫过于去配置wpa_supplicant.conf文件了(当然对于linux老手这不算什么), 但是可以用一种简便的方法直接输入命令行 ...

  3. php tpl 模板页面如和给js文件传参数

    有一个参数,服务器传给了php 模板页面,但模板包含的js需要得到这个参数值.如何处理: 一,在引入页面前加一句代码 <script type="text/javascript&quo ...

  4. validate插件的使用

    方法如下: 插件: jquery.validate.js jquery.validate.custom.js bootstrap html代码: <form id="form_name ...

  5. Delphi 我常用的几个下载源码的站点

    盒子.Delphi园地就不说了,介绍几个其它的: 源码爱好者,特别喜欢. http://www.codefans.net/sort/list_10_1.shtml 新兴源码: http://www.n ...

  6. Xcode7 修改bundle identifier

    Xcode 7 与之前的版本在修改bundle identifier的时候一点需要注意: 除了需要在.plist文件中修改, 还需要在 build setting中的 Product Bundle I ...

  7. javascript第二遍基础学习笔记(二)

    一.操作符 1.一元操作符: 自加自减(分前置和后置2种):++.-- 区别:前置的先自加或自减,后进行计算:而后置的是先进行计算,后自加或自减(在其会产生负面影响时才能体现区别): ; i++; / ...

  8. XSS与字符编码的那些事儿

    目录 0x00:基本介绍 0x01:html实体编码 0x02:新增的实体编码 实体编码变异以及浏览器的某些工作原理! 0x03:javascript编码 0x04:base64编码 0x05:闲扯 ...

  9. Java RMI简单例子HelloWorld

    Java RMI 指的是远程方法调用 (Remote Method Invocation).它是一种机制,能够让在某个 Java 虚拟机上的对象调用另一个 Java 虚拟机中的对象上的方法.可以用此方 ...

  10. "NetworkError: 500 Internal Server Error - http://develop.console.aliyun.sinopec.com/ots/ots_queryOtsList.action?state=0"

    项目明明开始好好的,报的这个错,错误提示也很少,啥信息都没有,只是明白是服务器报了500,知道是服务器内部错误,但是却没法找不到问题所在.后来突然想到把下面报错的action直接在浏览器运行: htt ...