- 浏览: 141142 次
文章分类
最新评论
在 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 711在Unix 域套接字概述一节中介绍了什么是 U ... -
Unix 域套接字概述
2019-03-12 22:48 979Unix 域协议并不是一个实际的协议族,而是在 ... -
kqueue 接口
2019-03-06 00:47 691kqueue 接口是 ... -
辅助数据
2019-02-28 00:40 687辅助数据(a ... -
recv/send 和 recvmsg/sendmsg 函数
2019-01-22 00:40 1553recv 和 send ... -
主机名与 IP 地址的转换(续)
2018-12-25 00:37 957在主机名与 IP 地址的转换一节中提到的 ge ... -
主机名与 IP 地址的转换
2018-11-14 00:20 2308在网络编程中,尽管大部分情况下操作的都是 IP ... -
SCTP 事件通知
2018-02-08 03:49 985SCTP 提供了多种可用的通知,用户可经由这些通知追踪 ... -
SCTP 套接字选项
2018-02-04 09:35 1692在获取和设置套接 ... -
SCTP 套接字编程基础函数
2018-02-04 10:08 1056SCTP 服务器可以使 ... -
SCTP 套接字编程基础概念
2018-01-18 00:10 561SCTP 套接字分为一到一套接字和一到多套接字。提供一 ... -
UDP套接字编程基础
2018-01-14 10:37 574下图显示了使用 UDP 套接字编写客户/服务器程序时的 ... -
通用套接字选项
2018-01-02 00:46 551在获取和设置套接 ... -
获取和设置套接字选项
2017-12-29 08:21 441下面几种方法可用 ... -
I/O 复用之 poll 函数
2017-12-27 00:20 423poll 函数提供的功能与 select 类似,不过在 ... -
I/O 复用之select 函数
2017-12-12 00:32 516select 函数允许进 ... -
Unix 5 种 IO 模型概述
2017-11-19 01:44 306Unix 下有 5 种可用 ... -
套接字创建、连接和关闭函数
2017-08-13 17:16 664下图是一对 TCP 客户与服务器进程之间发生的一些典型 ... -
字节转换和填充函数
2017-08-06 01:09 428网络编程中,为保证发送协议栈和接收协议栈就如 32 位 ... -
IPv4 和 IPv6 的套接字地址结构
2017-08-01 21:03 739大多数套接字函数 ...
相关推荐
Linux守护进程是Linux系统中的一种特殊进程,它们在系统启动后独立运行,通常与用户的交互较少,负责执行长期持续的任务,如网络服务、系统监控、定时任务等。这些守护进程在后台持续工作,确保系统的正常运行和服务...
Linux 的大多数服务器进程就是用守护进程实现的,例如 Internet 服务器 inetd、Web 服务器 httpd 等。同时,守护进程完成许多系统任务,比如作业规划进程 crond、打印进程 lpd 等。 守护进程的特点是独立于终端,...
Linux系统中许多重要的服务都是通过守护进程实现的,例如Internet服务器`inetd`、Web服务器`httpd`、作业规划进程`crond`以及打印进程`lpd`等。 守护进程具有以下关键特性: 1. **后台运行**:守护进程不依赖于...
守护进程和inetd超级服务器是Linux/Unix操作系统中重要的后台服务机制。守护进程,又称守护程序,是一种在后台运行并且不与任何终端关联的进程,主要用于提供持续性的系统服务,如网络服务、定时任务等。它们不受...
守护进程在Linux中的应用非常广泛,例如Internet服务器inetd、Web服务器httpd、作业规划进程crond以及打印进程lpd等。这些进程以超级用户权限运行,确保对系统资源的高级访问权限。守护进程的父进程通常是初始化进程...
Linux操作系统下的守护进程编程是非常重要的,因为大多数服务器都是用守护进程来实现的,例如WEB服务器的HTTPD,INTERNET服务器的INETD,系统作业规划进程CROND,系统打印进程LPD等。 守护进程的编程步骤包括:第一...
Linux系统中的许多服务都是通过守护进程实现的,例如网络服务(如inetd)、Web服务(如httpd)、打印服务(如lpd)等。 守护进程具有以下主要特性: 1. **后台运行**:守护进程在系统后台运行,不会占用用户的终端...
- **启动方式**:由inetd守护进程根据`/etc/inetd.conf`配置启动。 - **注意事项**:与TFTP服务配合工作,在大多数场景下被禁用,以减少不必要的网络负载和安全风险。 ##### inetd/chargen - 字符发生器 - **功能**...
守护进程在Linux系统中扮演着服务器的角色,例如inetd、httpd等,用于提供网络服务,还有像crond这样的系统任务调度进程和lpd打印服务进程。 编写Linux守护进程涉及以下几个关键点: 1. **后台运行**:守护进程不...
Linux守护进程,也被称为守护程序,是在后台运行且与任何终端会话无关联的进程,它们通常是系统服务的基础,如网络服务、定时任务等。守护进程的特性使其能够在用户会话结束后仍然持续运行,为系统提供必要的服务。 ...
它可以在系统启动时从启动脚本/etc/rc.d中启动,可以由inetd守护进程启动,也可以有作业规划进程crond启动,还可以由用户终端(通常是shell)执行。 Python有时需要保证只运行一个脚本实例,以避免数据的冲突。 二...
例如,当一个用户请求FTP服务时,`inetd`会根据配置文件启动`FTPd`守护进程来处理该请求。这样可以节省系统资源,因为不是所有服务都需要一直运行。 网络服务器编程技术有多种实现方式,包括并发服务器模型。其中:...
inetd(Internet Daemon)是Linux和Unix系统中的一种基础服务,它作为一个后台守护进程运行,负责监听特定的网络端口,当接收到请求时,启动相应的服务进程来处理这些请求。inetd通常被称为“网络服务的守护进程”,...
常见的守护进程有inetd(Internet服务器)、httpd(Web服务器)、crond(作业规划进程)和lpd(打印进程)。由于Unix家族的不同版本间实现机制的差异,编写守护进程时需要特别注意兼容性问题,尤其是在Linux环境下。...
这些特性使得守护进程适合用于长期运行的服务,如系统初始化进程`init`,以及监听网络服务的`inetd`进程。 在编写守护进程时,遵循以下编程规则至关重要: 1. **设置文件模式创建屏蔽字**:通过调用`umask(0)`确保...
守护进程在Linux系统中扮演着服务器的角色,例如 inetd(Internet服务器)、httpd(Web服务器)、crond(作业调度进程)和lpd(打印服务进程)等。 守护进程的编程涉及以下几个关键步骤: 1. **后台运行**:守护...
注意:如果你的守护进程是由inetd启动的,不要这样做!inetd完成了 所有需要做的事情,包括重定向标准文件描述符,需要做的事情只有 chdir() 和 umask()了 ''' def daemonize(stdin='/dev/null',stdout= '/dev/...
Inetd(Internet服务守护进程)是一种旧式的系统服务,它可以监听网络端口,并在接收到请求时启动相应的服务器进程。在现代系统中,inetd常被xinetd替代,后者提供了更安全和灵活的控制。YADR中的inetd配置可能涉及...
守护进程是一种特殊的进程,它在系统启动时启动,通常在后台运行,例如:inetd 进程。 三、学习 Linux 命令的顺序执行和并发执行 Linux 中的命令可以通过SEQUENTIAL(顺序执行)或CONCURRENT(并发执行)方式来...
然后,文档介绍了xinetd管理模式,这是对stand-alone模式的一种优化,解决了单一守护进程监听每个服务端口可能导致的资源浪费问题。xinetd(扩展超级服务器)是一个网络服务管理程序,它根据网络请求动态调用相应...