Chinaunix首页 | 论坛 | 博客
  • 博客访问: 345770
  • 博文数量: 46
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 562
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-14 13:32
个人简介

先知者为师

文章分类

全部博文(46)

文章存档

2016年(1)

2015年(6)

2014年(20)

2013年(19)

我的朋友

分类: LINUX

2014-07-02 22:15:33

ubuntu下找不到inetd.conf这个配置文件,原因是ubuntu默认没安装,
需要:  sudo apt-get install openbsd-inetd

inetd超级服务员

       在典型的Unix/Linux系统中有很多服务器运行,等待用户的请求并进行相应的服务。在4.3BSD版本前的Unix系统中,这些服务都有一个与之对应的进程。这些进程在系统启动时从/etc/rc文件里启动,它们启动时所做的工作基本相同:创建套接口,给它捆绑到服务器的众所周知端口,等待连接(如果是TCP协议)或数据报(如果是 UDP协议),然后执行fork。由fork产生的子进程为用户服务,父进程继续等待下一个用户请求。该模型有两个问题:

1.这些守护进程都以几乎相同的启动代码工作,首先是创建套接口,还要考虑变成守护进程(与daemon_init函数类似)。

2.每个守护进程在进程表中占有一项,但它们大部分时间处于睡眠状态,消耗了许多系统内存资源。

     4.3BSD版本的Unix系统通过提供一个因特网超级服务器:inetd守护进程使这些问题得到简化。之所以称为超级服务器。是因为它能够处理多种网络服务。典型的FTP、Telnet、TFTP、Rlogin等服务都是由这个超级服务器来间接提供的。基于TCP或者UDP的服务器都可以使用这个守护进程。但它不处理其它的协议,如Unix域套接口。该守护进程解决了上面提到的两个问题。

 

1.因为大部分启动时要做的工作由inetd处理,所以守护进程的编写得到简化。这避免了每个服务器程序都要调用daemon_init函数。

2.单个进程(inetd)能为多种服务等待用户的请求,取代了每种服务一个进程的方式。这样减少了系统中的进程总数,并缩小了资源开销。

 

     inetd进程使用daemon_init函数中的技术将自己变成一个守护进程,然后读入并处理它的配置文件,通常为/etc/inetd.conf。这个文本文件规定了这个超级服务员要接收哪些请求,收到这些请求后又要提供哪些服务。这个文件每一行所包括的字段列在图4-12中。可以列出几行作为例子:

    ftp       stream     tcp    nowait    root      /etc/ftpd       ftpd

    telnet    stream     tcp    nowait    root      /etc/telnetd    telnetd

    login     stream     tcp    nowait    root      /etc/rlogind    rlogind

    tftp      dgram      udp    wait      nobody    /etc/tftpd      tftpd

 

字     段

描       述

service_name

必须在/etc/services中

socket_type

stream或dgram

protocol

必须在/etc/protocol(TCP或UDP)中

wait_flag

Wait或nowait

login_name

取自/etc/passwd文件中,通常为root

server_program

至exec的完整路径名

server_program_arguments

最多五个变元

图4-12 inetd结构文件中的字段

       /etc/inetd.conf文本文件中各行的含义如下:

1.服务名称(service_name):这个服务名称必须在/etc/services中定义。

2.套接字类型(socket_type):套接字是流套接字还是倾听套接字类型。

3.使用的协议类型(protocol):即TCP协议或者UDP协议。有的服务可能同时支持两种协议。

4.等待状态(wait_flag):如果指定为nowait,超级服务器将允许指定的服务并发,它将在本次服务未完成时,启动下一次服务。否则,该项服务将不能并发执行,一次只能服务于一个用户进程,下一个用户进程只能等到本次服务结束后才能得到服务。

5.用户名(login_name):服务器将以该用户名对应的权限运行进程。由于inetd是具有超级权限的进程,而有些服务可能是某个用户自己编写的,不应当或没有必要以超级用户的权限运行。inetd将根据这个记录在exec加载子进程时修改进程的运行权限。

6.服务器的可执行文件的位置(server_program):inetd使用这个项目定位服务器程序的位置(使用绝对路径名)。

7.程序的参数(server_program_arguments):inetd将在exec函数中使用这行参数。

                                         

                 

图4-13 inetd的执行步骤

图4-13画出了这个守护程序的流程,有代表性的步骤有:

    (1)启动时读入/etc/inetd.conf文件,并且为该文件中每一个服务员生成一个类型适当的(流/数据报)管座(可以理解为是一个套接字,或者说是一个用于收发数据的管道)。由于inetd所用的文件描述符总数不能超过系统规定的上限值,所以inetd可以等候的服务员的数量也有一定限制。在大多数BSD系统中,这个上限值为64,不过重新构造内核也可以改变这个值。

    (2)生成每一个管座后要执行bind,为该服务员指定一个众所周知的地址。查找/etc/services文件中的构造文件的service_name字段可以得到TCP/UDP端口号。对应于上面所列的结构文件中的4行,在这个文件中有如下4行:

        ftp       21/tcp

        telnet    23/tcp

        tftp      69/udp

        login     513/tcp

    /etc/inetd.conf文件中的每个服务员都要执行这几步。在inetd结构文件中的service_name(如telnet)和protocol都作为变元传送给库函数getservbyname,用来为bind确定正确的端口号的位置。   

    (3)对于流管座要执行listen,表示希望在该管道上接收连接,并指定用于输入连接的队列的长度。对于数据报管座不必执行这一步。

    (4)执行select,等待第一个管座变为可读入。当一个连接请求到达流管座时就认为它变为可读;对于数据报管座来说,当数据报到达时就变为可读。在这一步,inetd守护程序只是等待select系统调用返回。

    (5)当一个管座变为可读时,若它是流管座,则执行accept系统调用接受该连接。

    (6)fork,并且由子进程来处理这个服务请求。这个子进程首先把除了正在处理的这个管座描述符之外的所有文件描述符全部关闭,然后调用dup2(复制文件句柄),把该管套复制到文件描述符0、l、2上,原来的管套描述符关闭。这样,在子进程上只打开文件描述符0、l、2,然后它调用getpwnam,获得在/etc/inetd.conf文件中指定的login_name在口令字文件中所对应的入口。如果这个入口的用户ID不为“0”(不是特权用户),那么执行setgid和setuid系统调用,使子进程变为指定的用户(由于inetd进程是以用户ID为“0”来执行的,它的子进程通过fork也继承了这个用户ID,所以它可以变成任何选定的用户)。现在,子进程用exec执行适当的服务员程序来处理服务请求,传送在结构文件中的指定的一些变元。

(7)如果这个管座是一个流管座,那么父进程必须把这个连接的管座关闭。父进程再一次执行select系统调用,等待下一个管座变为可读。

 

 

 

上面所讨论的方案是在结构文件中指定服务员为nowait的情况,典型例子是所有TCP服务员。如果对于同一个服务员又有另一个连接请求到达,它执行select之后立即回到父进程,上面所列的步骤又重做一遍,由另一个子进程来处理这个新的服务请求。

    许多厂商都在inetd实现中加入了一些自己的功能。例如,在 TCP和UDP服务器之外,加入处理远程过程调用(RPC)服务器的能力。以及处理除TCP和UDP外其它协议的能力。当然,exec服务器程序使用的路径名和命令行参数也依赖于具体的实现。

    IPv6与/etc/inetd.conf的交互依赖于厂商的实现。一些厂商用名为tcp6和udp6的protocol表示应为该服务创建一个IPv6套接口。

    守护进程是在后台运行的,独立于所有终端控制的进程。大多数网络服务器是以守护进程的方式运行。守护进程的所有输出通常是调用syslog函数发送给syslogd守护进程。管理员可以根据发送消息的守护进程以及消息的紧急程度,完全控制如何处理这些消息。

    多数Unix服务器是由inetd守护进程启动的。它处理了所有转变成守护进程所需要的步骤,在启动真正的服务器时套接口已在标准输入、标准输出、标准错误输出上打开。这样就不必在调用socket、bind、listen 和accept了,因为这些操作inetd已经完成。



关于守护进程输出日志文件的方法

今天在学习守护进程时,看到一个实验,却无法得到结果。发现可能是Linux版本不同,结果配置文件也不同

首先,ubuntu的配置文件为/etc/rsyslog.conf,不再是/etc/syslog.conf。

其次,编辑/etc/rsyslog.conf,在其中添加配置文件
local2.debug         /var/log/cisco.log
local2.info              /var/log/test.log
然后重新启动一下syslog服务,sudo /etc/init.d/rsyslog restart,就回看见var/log中多出了cisco.log和test.log两个文件

最后    编译运行下列代码:
#include
#include
int main()
{
openlog("here",LOG_PID,LOG_USER);
syslog(LOG_INFO|LOG_LOCAL2,"OK");
closelog();
}

再查看/var/log/test.log的内容,就会发现有下列内容:
Apr 18 11:02:05 ubuntu here[3574]: OK

阅读(2278) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~