- 浏览: 133185 次
文章分类
最新评论
在 4.3 BSD 系统之前,很多网络服务都是单独关联了一个进程,每个进程都占据了一个进程表项,而且这些进程几乎都含有相同的启动代码,并且大部分时间都处于睡眠状态。为了简化这些问题,4.3 BSD 中提供了一个因特网超级服务器(即 inetd 守护进程),使得基于 TCP 或 UDP 的服务器都可以使用这个守护进程。下面就来看一下该进程是如何解决上述问题的。
inetd 进程在演变成守护进程后,会接着读入并处理自己的配置文件。通常是 /etc/inetd.conf 配置文件指定 inetd 处理哪些服务以及如何处理服务请求。该文件每行中一般包含如下图所示的字段(现在很多厂商为 inetd 自行增设了新的特性,比如添加了处理其他协议和处理 RPC 服务器的能力等)。
其中的 wait-flag 字段总地来说,就是指定由 inetd 启动的守护进程是否有意接管与之关联的监听套接字。由于 UDP 服务没有分离的监听套接字和接受套接字,因此几乎总是配置成 wait,而 TCP 服务中则是 nowait 更为常见。另外,当 inetd 调用 exec 执行某个服务器程序时,总是将该服务器的真实名字作为程序的第一个参数。
下面就是 inetd.conf 文件的部分示例内容。
inetd 的工作流程如下图所示。
(1)在启动阶段,为 /etc/inetd.conf 文件中指定的每个服务创建一个适当类型的套接字,并将其加入到某个 select 调用使用的描述符集中。
(2)调用 bind 为每个套接字捆绑服务器端口和通配地址。该 TCP 或 UDP 端口号是通过 getservbyname 函数获得,其参数是相应服务器在配置文件中的 service-name 和 protocol 字段。
(3)对每个 TCP 套接字调用 listen 函数以接收外来的连接请求。
(4)调用 select 等待其中任何一个套接字变为可读。TCP 监听套接字会在有一个新连接准备好时变为可读,UDP 套接字会在有一个数据报到达时变为可读。inetd 的大部分时间都花在该阶段。
(5)在某个套接字变为可读后,如果它是一个 TCP 套接字,并且其服务器的 wait-flag 值为 nowait,那就调用 accept 接受这个新连接。如果它是一个字节流套接字,则必须关闭已连接套接字,然后再次调用 select,等待下一个变为可读的套接字。
(6)inetd 守护进程调用 fork 派生一个子进程来处理服务器请求。子进程会关闭除要处理的套接字描述符之外的所有描述符,并调用 dup2 三次,以将描述符 0、1 和 2 重定向为这个待处理的套接字描述符,然后关闭该套接字描述符。因此子进程打开的描述符于是就只有 0、1 和 2,所以它从标准输入读或是往标准输出和标准错误写实际上都是针对所处理的套接字。此外,子进程还会根据它在配置文件中的 login-name 字段,调用 getpwnam 函数获取对应的保密文件表项。如果该字段值不是 root,子进程将调用 setgid 和 setuid 把自身改为指定的用户(因为 inetd 进程是以用户 ID 0 运行的,其子进程继承了这个 ID,因而能变成任何用户)。最后,子进程会调用 exec 执行由相应的 server-program 字段指定的程序来具体处理请求,相应的 server-program-auguments 字段值则作为命令行参数传递给改程序。
前面提到,典型的 TCP 服务大都指定了 nowait 标志,这意味着 inetd 不必等待某个子进程终止就可以接受该子进程所提供服务的另一个连接。当有一个新的连接在该子进程终止前到达,则父进程再次调用 select 时就可以得到这个新的连接,最终又会派生出另一个子进程来处理该连接。
而给一个数据报服务指定 wait 标志会要求 inetd 必须在这个套接字再次成为 select 的候选套接字之前等待当前服务该套接字的子进程终止,这会使父进程执行的步骤发生如下几点的变化。
(1)父进程 fork 后会保存子进程的进程 ID。这可以让父进程能通过查看 waitpid 函数返回的值来确定该子进程的终止时间。
(2)父进程通过宏 FD_CLR 关闭该套接字在 select 所用描述符集中对应的位,从而达成在之后的 select 调用中禁止该套接字的目的。这表示子进程将接管该套接字,直到自身终止为止。
(3)父进程会在子进程终止时收到一个 SIGCHLD 信号,然后其信号处理函数将取得该子进程的进程 ID,最后再打开相应套接字在 select 所用描述符集中对应的位,使其重新成为 select 的候选套接字。
因为一般每个数据报服务器只有一个套接字,所以数据报服务器通常都需要接管其套接字直至自身终止,以防 inetd 在此期间让 select 检查该套接字的可读性。如果 inetd 不关闭对某个数据报套接字的可读性检查,而且父进程(inetd)先于服务该套接字的子进程执行,则会由于引发本次 fork 的那个数据报仍然在套接字接收缓冲区中,从而导致 select 再次返回可读条件,致使 inetd 再次 fork 一个多余的子进程,所以 inetd 必须在得知子进程已从套接字接收队列中读走该数据报之前忽略这个数据报套接字。
inetd 通常不适用于服务密集型服务器,比如邮件服务器和 Web 服务器等。另外,在 Linux 等系统上,称为 xinetd 的扩展式因特网服务守护进程业已常见,它提供了更多的其他特性,包括根据客户的地址登记、接受或拒绝连接的选项、每个服务一个配置文件的做法等等,但其背后的基本超级服务器概念和 inetd 是一样的。
参考书籍:
1、《UNIX 网络编程卷 1》第 13 章——守护进程和 inetd 超级服务器。
inetd 进程在演变成守护进程后,会接着读入并处理自己的配置文件。通常是 /etc/inetd.conf 配置文件指定 inetd 处理哪些服务以及如何处理服务请求。该文件每行中一般包含如下图所示的字段(现在很多厂商为 inetd 自行增设了新的特性,比如添加了处理其他协议和处理 RPC 服务器的能力等)。
其中的 wait-flag 字段总地来说,就是指定由 inetd 启动的守护进程是否有意接管与之关联的监听套接字。由于 UDP 服务没有分离的监听套接字和接受套接字,因此几乎总是配置成 wait,而 TCP 服务中则是 nowait 更为常见。另外,当 inetd 调用 exec 执行某个服务器程序时,总是将该服务器的真实名字作为程序的第一个参数。
下面就是 inetd.conf 文件的部分示例内容。
$ cat /etc/inetd.conf ftp stream tcp nowait root /usr/bin/ftpd ftpd -l telnet stream tcp nowait root /usr/bin/telnetd telnetd tftp dgram udp wait nobody /usr/bin/tftpd tftpd -s /tftpboot
inetd 的工作流程如下图所示。
(1)在启动阶段,为 /etc/inetd.conf 文件中指定的每个服务创建一个适当类型的套接字,并将其加入到某个 select 调用使用的描述符集中。
(2)调用 bind 为每个套接字捆绑服务器端口和通配地址。该 TCP 或 UDP 端口号是通过 getservbyname 函数获得,其参数是相应服务器在配置文件中的 service-name 和 protocol 字段。
(3)对每个 TCP 套接字调用 listen 函数以接收外来的连接请求。
(4)调用 select 等待其中任何一个套接字变为可读。TCP 监听套接字会在有一个新连接准备好时变为可读,UDP 套接字会在有一个数据报到达时变为可读。inetd 的大部分时间都花在该阶段。
(5)在某个套接字变为可读后,如果它是一个 TCP 套接字,并且其服务器的 wait-flag 值为 nowait,那就调用 accept 接受这个新连接。如果它是一个字节流套接字,则必须关闭已连接套接字,然后再次调用 select,等待下一个变为可读的套接字。
(6)inetd 守护进程调用 fork 派生一个子进程来处理服务器请求。子进程会关闭除要处理的套接字描述符之外的所有描述符,并调用 dup2 三次,以将描述符 0、1 和 2 重定向为这个待处理的套接字描述符,然后关闭该套接字描述符。因此子进程打开的描述符于是就只有 0、1 和 2,所以它从标准输入读或是往标准输出和标准错误写实际上都是针对所处理的套接字。此外,子进程还会根据它在配置文件中的 login-name 字段,调用 getpwnam 函数获取对应的保密文件表项。如果该字段值不是 root,子进程将调用 setgid 和 setuid 把自身改为指定的用户(因为 inetd 进程是以用户 ID 0 运行的,其子进程继承了这个 ID,因而能变成任何用户)。最后,子进程会调用 exec 执行由相应的 server-program 字段指定的程序来具体处理请求,相应的 server-program-auguments 字段值则作为命令行参数传递给改程序。
前面提到,典型的 TCP 服务大都指定了 nowait 标志,这意味着 inetd 不必等待某个子进程终止就可以接受该子进程所提供服务的另一个连接。当有一个新的连接在该子进程终止前到达,则父进程再次调用 select 时就可以得到这个新的连接,最终又会派生出另一个子进程来处理该连接。
而给一个数据报服务指定 wait 标志会要求 inetd 必须在这个套接字再次成为 select 的候选套接字之前等待当前服务该套接字的子进程终止,这会使父进程执行的步骤发生如下几点的变化。
(1)父进程 fork 后会保存子进程的进程 ID。这可以让父进程能通过查看 waitpid 函数返回的值来确定该子进程的终止时间。
(2)父进程通过宏 FD_CLR 关闭该套接字在 select 所用描述符集中对应的位,从而达成在之后的 select 调用中禁止该套接字的目的。这表示子进程将接管该套接字,直到自身终止为止。
(3)父进程会在子进程终止时收到一个 SIGCHLD 信号,然后其信号处理函数将取得该子进程的进程 ID,最后再打开相应套接字在 select 所用描述符集中对应的位,使其重新成为 select 的候选套接字。
因为一般每个数据报服务器只有一个套接字,所以数据报服务器通常都需要接管其套接字直至自身终止,以防 inetd 在此期间让 select 检查该套接字的可读性。如果 inetd 不关闭对某个数据报套接字的可读性检查,而且父进程(inetd)先于服务该套接字的子进程执行,则会由于引发本次 fork 的那个数据报仍然在套接字接收缓冲区中,从而导致 select 再次返回可读条件,致使 inetd 再次 fork 一个多余的子进程,所以 inetd 必须在得知子进程已从套接字接收队列中读走该数据报之前忽略这个数据报套接字。
inetd 通常不适用于服务密集型服务器,比如邮件服务器和 Web 服务器等。另外,在 Linux 等系统上,称为 xinetd 的扩展式因特网服务守护进程业已常见,它提供了更多的其他特性,包括根据客户的地址登记、接受或拒绝连接的选项、每个服务一个配置文件的做法等等,但其背后的基本超级服务器概念和 inetd 是一样的。
参考书籍:
1、《UNIX 网络编程卷 1》第 13 章——守护进程和 inetd 超级服务器。
发表评论
-
Unix 域套接字与描述符的传递
2019-03-27 23:59 682在Unix 域套接字概述一节中介绍了什么是 U ... -
Unix 域套接字概述
2019-03-12 22:48 935Unix 域协议并不是一个实际的协议族,而是在 ... -
kqueue 接口
2019-03-06 00:47 643kqueue 接口是 ... -
辅助数据
2019-02-28 00:40 633辅助数据(a ... -
recv/send 和 recvmsg/sendmsg 函数
2019-01-22 00:40 1418recv 和 send ... -
主机名与 IP 地址的转换(续)
2018-12-25 00:37 920在主机名与 IP 地址的转换一节中提到的 ge ... -
主机名与 IP 地址的转换
2018-11-14 00:20 2206在网络编程中,尽管大部分情况下操作的都是 IP ... -
SCTP 事件通知
2018-02-08 03:49 883SCTP 提供了多种可用的通知,用户可经由这些通知追踪 ... -
SCTP 套接字选项
2018-02-04 09:35 1615在获取和设置套接 ... -
SCTP 套接字编程基础函数
2018-02-04 10:08 1006SCTP 服务器可以使 ... -
SCTP 套接字编程基础概念
2018-01-18 00:10 505SCTP 套接字分为一到一套接字和一到多套接字。提供一 ... -
UDP套接字编程基础
2018-01-14 10:37 525下图显示了使用 UDP 套接字编写客户/服务器程序时的 ... -
通用套接字选项
2018-01-02 00:46 517在获取和设置套接 ... -
获取和设置套接字选项
2017-12-29 08:21 411下面几种方法可用 ... -
I/O 复用之 poll 函数
2017-12-27 00:20 384poll 函数提供的功能与 select 类似,不过在 ... -
I/O 复用之select 函数
2017-12-12 00:32 484select 函数允许进 ... -
Unix 5 种 IO 模型概述
2017-11-19 01:44 275Unix 下有 5 种可用 ... -
套接字创建、连接和关闭函数
2017-08-13 17:16 612下图是一对 TCP 客户与服务器进程之间发生的一些典型 ... -
字节转换和填充函数
2017-08-06 01:09 402网络编程中,为保证发送协议栈和接收协议栈就如 32 位 ... -
IPv4 和 IPv6 的套接字地址结构
2017-08-01 21:03 704大多数套接字函数 ...
相关推荐
Linux 的大多数服务器进程就是用守护进程实现的,例如 Internet 服务器 inetd、Web 服务器 httpd 等。同时,守护进程完成许多系统任务,比如作业规划进程 crond、打印进程 lpd 等。 守护进程的特点是独立于终端,...
守护进程和inetd超级服务器PPT学习教案.pptx
Linux操作系统下的守护进程编程是非常重要的,因为大多数服务器都是用守护进程来实现的,例如WEB服务器的HTTPD,INTERNET服务器的INETD,系统作业规划进程CROND,系统打印进程LPD等。 守护进程的编程步骤包括:第一...
目录守护进程的特点常见的守护进程守护进程的编程规则编程规则设计原理守护进程的编程代码总结参考资料 守护进程的特点 守护进程是脱离终端并在后台运行的进程。守护进程不具有控制终端,我们不会再终端上见到守护...
它可以在系统启动时从启动脚本/etc/rc.d中启动,可以由inetd守护进程启动,也可以有作业规划进程crond启动,还可以由用户终端(通常是shell)执行。 Python有时需要保证只运行一个脚本实例,以避免数据的冲突。 二...
注意:如果你的守护进程是由inetd启动的,不要这样做!inetd完成了 所有需要做的事情,包括重定向标准文件描述符,需要做的事情只有 chdir() 和 umask()了 ''' def daemonize(stdin='/dev/null',stdout= '/dev/...
守护进程(Daemon)是运行在后台的一种非凡进程。它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是一种很有用的进程。Linux的大多数服务器就是用守护进程实现的。比如,Internet...
第10章 创建子进程的服务器和inetd守护进程 第11章 多线程应用程序 第12章 多路复用应用程序 第13章 无阻塞I/O 第14章 安全的服务器 第15章 预创建于进程和预创建线程 第16章 IO:: Poll 第4部分高级话题 ...
第13章 守护进程和inetd超级服务器? 第14章 高级I/O函数 第15章 Unix域协议 第16章 非阻塞I/O 第17章 ioctl操作 第18章 路由套接口 第19章 密钥管理套接口? 第20章 广播 第21章 多播 第22章 高级UDP套接口编程 第23...
Winetd (Windows inetd) - UNIX 的 inetd 守护进程模拟 Windows。
UNIX网络编程 第2卷 进程间通信 ...第13章 守护进程和inetd超级服务器? 第14章 高级I/O函数 第15章 Unix域协议 第16章 非阻塞I/O 第17章 ioctl操作 第18章 路由套接口 第19章 密钥管理套接口? -------
本书是一部UNIX网络API的经典之作!...I/O:复用高级函数,非阻塞和信号驱动 守护进程和inetd UNIX域协议 ioctl操作 广播和组播 线程 流 设计:TCP迭代的、并发的、预先创建的和预先线程化的服务器
1. 首先介绍linux中的守护进程 在Linux系统中有一个特殊的守护进程inetd(InterNET services Daemon),它用于Internet标准服务,通常在系统启动时启动。通过命令行可以给出inetd的配置文件,该配置文件列出了inetd所...
它可用于将 SSL 功能添加到常用的 inetd 守护进程,如 POP2、POP3 和 IMAP 服务器,而无需对程序代码进行任何更改。 Stunnel 使用 OpenSSL 库进行加密,因此它支持编译到库中的任何加密算法。 此映像允许您在完全...
它还旨在使您熟悉inetd超级服务器守护程序,“ exec”功能家族,各种套接字错误情形,某些套接字选项以及一些基本的域名IP地址转换功能。 除了本课程第1至6章中介绍的材料外,您还需要参考以下内容
linux目录架构 / 根目录 /bin 常用的命令 binary file 的目錄 /boot 存放系统启动时必须读取... /etc/inetd.conf 设定系统网络守护进程inetd的配置 /etc/gateways 设定路由器 /etc/protocols 设定系统支持的协议
linux目录架构 / 根目录 /bin 常用的命令 binary file 的目錄 /boot 存放系统启动时必须读取的... /etc/inetd.conf 设定系统网络守护进程inetd的配置 /etc/gateways 设定路由器 /etc/protocols 设定系统支持的协议
第13章 守护进程和inetd超级服务器? 第14章 高级I/O函数 第15章 Unix域协议 第16章 非阻塞I/O 第17章 ioctl操作 第18章 路由套接口 第19章 密钥管理套接口? 第20章 广播 第21章 多播 第22章 高级UDP套接口编程 第23...
第一章 简介 第二章 传输层:TCP UDP ...第十二章 守护进程和inetd超级服务器 第十三章 高级I/O函数 第十四章 Unix域协议 第十五章 非阻塞I/O 第十六章 ioctl操作 第十七章 路由器接口 第十八章 广播 第十九章 多播
第十章 守护进程和超级服务器inetd 10.1 守护进程的原理 10.2 编程实践 10.3 超级服务器inetd的工作原理 10.3.1 超级服务器的概念 10.3.2 超级服务器使用的配置文件 10.3.3 inetd处理...