2004年12月30日

简题:利用嗅探器之TcpDump分析网络安全
标题:利用嗅探器(sniffer)之网络数据采集分析工具TcpDump分析网络安全

Author:Phoenix
Homepage:http://www.safechina.net
E-mail:Phoenix@safechina.net
Time:23/01/2003

前言:在如令网络系统中,随着网络重要性、复杂性的不断增长,作为一名网络工程师、监测者、分析者或者是网络性能的评估者,您所扮演的角色对公司的成功是至关重要的。为了更好的完成工作,您需要透视整个网络,识别关键的性能问题——从应用的响应时间到带宽的瓶颈以至于识别网络每一层所出现的问题。在您每天的工作中,常常会着眼于未来用新的技术和应用扩展您的网络。网络探针分布在重要网段,监视该网络线路上各协议,各计算机占用情况,监控网络上各种业务的网络流量及带宽,记录网络操作,实现分布集中的网络分析Sniffer系统。本文将为你介绍如何利用嗅探器(sniffer)之网络数据采集分析工具TcpDump来详细网络及其安全分析。

一 嗅探器技术在网络中的应用

1 Sniffer简介

    Sniffer即嗅探器的英文写法,嗅探器(sniffer)是最常见,也是最重要的技术之一。用过windows平台上的sniffer工具(例如,netxray和sniffer pro软件)的朋友可能都知道,在共享式的局域网中,采用sniffer工具简直可以对网络中的所有流量一览无余!Sniffer工具实际上就是一个网络上的抓包工具,同时还可以对抓到的包进行分析。由于在共享式的网络中,信息包是会广播到网络中所有主机的网络接口,只不过在没有使用sniffer工具之前,主机的网络设备会判断该信息包是否应该接收,这样它就会抛弃不应该接收的信息包,sniffer工具却使主机的网络设备接收所有到达的信息包,这样就达到了网络监听的效果。其实,sniffer工具既可以适合于黑客的使用,也同样有利于网络管理员和网络程序员。对于网络管理人员来说,使用嗅探器可以随时掌握网络的实际情况,在网络性能急剧下降的时候,可以通过sniffer工具来分析原因,找出造成网络阻塞的来源。对于网络程序员来说,通过sniffer工具来调试程序。

    它也可以理解为一个安装在计算机上的窃听设备它可以用来窃听计算机在网络上所产生的众多的信息。简单一点解释:一部电话的窃听装置,可以用来窃听双方通话的内容,而计算机网络嗅探器则可以窃听计算机程序在网络上发送和接收到的数据。可是,计算机直接所传送的数据,事实上是大量的二进制数据。因此,一个网络窃听程序必须也使用特定的网络协议来分解嗅探到的数据,嗅探器也就必须能够识别出那个协议对应于这个数据片断,只有这样才能够进行正确的解码。计算机的嗅探器比起电话窃听器,有他独特的优势:很多的计算机网络采用的是“共享媒体”。就是说,你不必中断他的通讯,并且配置特别的线路,再安装嗅探器,你几乎可以在任何连接着的网络上直接窃听到你同一掩码范围内的计算机网络数据。我们称这种窃听方式为“基于混杂模式的嗅探”(promiscuousmode)。尽管如此,这种“共享”的技术发展的很快,慢慢转向“交换”技术,这种技术会长期内会继续使用下去, 它可以实现有目的选择的收发数据。

2 Sniffer在工作原理

    以太网的数据传输是基于“共享”原理的:所有的同一本地网范围内的计算机共同接收到相同的数据包。这意味着计算机直接的通讯都是透明可见的。正是因为这样的原因,以太网卡都构造了硬件的“过滤器”这个过滤器将忽略掉一切和自己无关的网络信息。事实上是忽略掉了与自身MAC地址不符合的信息。嗅探程序正是利用了这个特点,它主动的关闭了这个嗅探器,也就是前面提到的设置网卡“混杂模式”。因此,嗅探程序就能够接收到整个以太网内的网络数据了信息了。

二 网络数据采集分析工具TcpDump的应用

1 网络数据采集分析工具TcpDump的简介

    顾名思义,TcpDump可以将网络中传送的数据包的“头”完全截获下来提供分析。它支持针对网络层、协议、主机、网络或端口的过滤,并提供and、or、not等逻辑语句来帮助你去掉无用的信息。tcpdump就是一种免费的网络分析工具,尤其其提供了源代码,公开了接口,因此具备很强的可扩展性,对于网络维护和入侵者都是非常有用的工具。tcpdump存在于基本的FreeBSD系统中,由于它需要将网络界面设置为混杂模式,普通用户不能正常执行,但具备root权限的用户可以直接执行它来获取网络上的信息。因此系统中存在网络分析工具主要不是对本机安全的威胁,而是对网络上的其他计算机的安全存在威胁。我们用尽量简单的话来定义tcpdump,就是:dump the traffice on a network.,根据使用者的定义对网络上的数据包进行截获的包分析工具。作为互联网上经典的的系统管理员必备工具,tcpdump以其强大的功能,灵活的截取策略,成为每个高级的系统管理员分析网络,排查问题等所必备的东西之一。tcpdump提供了源代码,公开了接口,因此具备很强的可扩展性,对于网络维护和入侵者都是非常有用的工具。tcpdump存在于基本的FreeBSD系统中,由于它需要将网络界面设置为混杂模式,普通用户不能正常执行,但具备root权限的用户可以直接执行它来获取网络上的信息。因此系统中存在网络分析工具主要不是对本机安全的威胁,而是对网络上的其他计算机的安全存在威胁。

2 网络数据采集分析工具TcpDump的安装

    在linux下tcpdump的安装十分简单,一般由两种安装方式。一种是以rpm包的形式来进行安装。另外一种是以源程序的形式安装。

    rpm包的形式安装:这种形式的安装是最简单的安装方法,rpm包是将软件编译后打包成二进制的格式,通过rpm命令可以直接安装,不需要修改任何东西。以超级用户登录,使用命令如下:
#rpm -ivh tcpdump-3_4a5.rpm

    这样tcpdump就顺利地安装到你的linux系统中。怎么样,很简单吧。

    源程序的安装:既然rpm包的安装很简单,为什么还要采用比较复杂的源程序安装呢?其实,linux一个最大的诱人之处就是在她上面有很多软件是提供源程序的,人们可以修改源程序来满足自己的特殊的需要。所以我特别建议朋友们都采取这种源程序的安装方法。

    第一步 取得源程序 在源程序的安装方式中,我们首先要取得tcpdump的源程序分发包,这种分发包有两种形式,一种是tar压缩包(tcpdump-3_4a5.tar.Z),另一种是rpm的分发包(tcpdump-3_4a5.src.rpm)。这两种形式的内容都是一样的,不同的仅仅是压缩的方式.tar的压缩包可以使用如下命令解开:
#tar xvfz tcpdump-3_4a5.tar.Z
rpm的包可以使用如下命令安装:
#rpm -ivh tcpdump-3_4a5.src.rpm
这样就把tcpdump的源代码解压到/usr/src/redhat/SOURCES目录下.

    第二步 做好编译源程序前的准备活动

    在编译源程序之前,最好已经确定库文件libpcap已经安装完毕,这个库文件是tcpdump软件所需的库文件。同样,你同时还要有一个标准的c语言编译器。在linux下标准的c 语言编译器一般是gcc。 在tcpdump的源程序目录中。有一个文件是Makefile.in,configure命令就是从Makefile.in文件中自动产生Makefile文件。在Makefile.in文件中,可以根据系统的配置来修改BINDEST 和 MANDEST 这两个宏定义,缺省值是
BINDEST = @sbindir@
MANDEST = @mandir@
第一个宏值表明安装tcpdump的二进制文件的路径名,第二个表明tcpdump的man 帮助页的路径名,你可以修改它们来满足系统的需求。

    第三步 编译源程序

    使用源程序目录中的configure脚本,它从系统中读出各种所需的属性。并且根据Makefile.in文件自动生成Makefile文件,以便编译使用.make 命令则根据Makefile文件中的规则编译tcpdump的源程序。使用make install命令安装编译好的tcpdump的二进制文件。
总结一下就是:
# tar xvfz tcpdump-3_4a5.tar.Z
# vi Makefile.in
# . /configure
# make
# make install

3 网络数据采集分析工具TcpDump的使用

    普通情况下,直接启动tcpdump将监视第一个网络界面上所有流过的数据包。
# tcpdump
tcpdump: listening on fxp0
11:58:47.873028 202.102.245.40.netbios-ns > 202.102.245.127.netbios-ns: udp 50
11:58:47.974331 0:10:7b:8:3a:56 > 1:80:c2:0:0:0 802.1d ui/C len=43
                         0000 0000 0080 0000 1007 cf08 0900 0000
                         0e80 0000 902b 4695 0980 8701 0014 0002
                         000f 0000 902b 4695 0008 00
11:58:48.373134 0:0:e8:5b:6d:85 > Broadcast sap e0 ui/C len=97
                         ffff 0060 0004 ffff ffff ffff ffff ffff
                         0452 ffff ffff 0000 e85b 6d85 4008 0002
                         0640 4d41 5354 4552 5f57 4542 0000 0000
                         0000 00
^C

    tcpdump支持相当多的不同参数,如使用-i参数指定tcpdump监听的网络界面,这在计算机具有多个网络界面时非常有用,使用-c参数指定要监听的数据包数量,使用-w参数指定将监听到的数据包写入文件中保存,等等。

    然而更复杂的tcpdump参数是用于过滤目的,这是因为网络中流量很大,如果不加分辨将所有的数据包都截留下来,数据量太大,反而不容易发现需要的数据包。使用这些参数定义的过滤规则可以截留特定的数据包,以缩小目标,才能更好的分析网络中存在的问题。tcpdump使用参数指定要监视数据包的类型、地址、端口等,根据具体的网络问题,充分利用这些过滤规则就能达到迅速定位故障的目的。请使用man tcpdump查看这些过滤规则的具体用法。

    显然为了安全起见,不用作网络管理用途的计算机上不应该运行这一类的网络分析软件,为了屏蔽它们,可以屏蔽内核中的bpfilter伪设备。一般情况下网络硬件和TCP/IP堆栈不支持接收或发送与本计算机无关的数据包,为了接收这些数据包,就必须使用网卡的混杂模式,并绕过标准的TCP/IP堆栈才行。在FreeBSD下,这就需要内核支持伪设备bpfilter。因此,在内核中取消bpfilter支持,就能屏蔽tcpdump之类的网络分析工具。

    并且当网卡被设置为混杂模式时,系统会在控制台和日志文件中留下记录,提醒管理员留意这台系统是否被用作攻击同网络的其他计算机的跳板。

    May 15 16:27:20 host1 /kernel: fxp0: promiscuous mode enabled

    虽然网络分析工具能将网络中传送的数据记录下来,但是网络中的数据流量相当大,如何对这些数据进行分析、分类统计、发现并报告错误却是更关键的问题。网络中的数据包属于不同的协议,而不同协议数据包的格式也不同。因此对捕获的数据进行解码,将包中的信息尽可能的展示出来,对于协议分析工具来讲更为重要。昂贵的商业分析工具的优势就在于它们能支持很多种类的应用层协议,而不仅仅只支持tcp、udp等低层协议。

    从上面tcpdump的输出可以看出,tcpdump对截获的数据并没有进行彻底解码,数据包内的大部分内容是使用十六进制的形式直接打印输出的。显然这不利于分析网络故障,通常的解决办法是先使用带-w参数的tcpdump 截获数据并保存到文件中,然后再使用其他程序进行解码分析。当然也应该定义过滤规则,以避免捕获的数据包填满整个硬盘。FreeBSD提供的一个有效的解码程序为tcpshow,它可以通过Packages Collection来安装。

# pkg_add /cdrom/packages/security/tcpshow*
# tcpdump -c 3 -w tcpdump.out
tcpdump: listening on fxp0
# tcpshow < tcpdump.out
—————————————————————————
Packet 1
TIME:12:00:59.984829
LINK:00:10:7B:08:3A:56 -> 01:80:C2:00:00:00 type=0026
<*** No decode support for encapsulated protocol ***>
—————————————————————————
Packet 2
TIME:12:01:01.074513 (1.089684)
LINK:00:A0:C9:AB:3C:DF -> FF:FF:FF:FF:FF:FF type=ARP
ARP:htype=Ethernet ptype=IP hlen=6 plen=4 op=request
sender-MAC-addr=00:A0:C9:AB:3C:DF sender-IP-address=202.102.245.3
target-MAC-addr=00:00:00:00:00:00 target-IP-address=202.102.245.3
—————————————————————————
Packet 3
TIME:12:01:01.985023 (0.910510)
LINK:00:10:7B:08:3A:56 -> 01:80:C2:00:00:00 type=0026
<*** No decode support for encapsulated protocol ***>

    tcpshow能以不同方式对数据包进行解码,并以不同的方式显示解码数据,使用者可以根据其手册来选择最合适的参数对截获的数据包进行分析。从上面的例子中可以看出,tcpshow支持的协议也并不丰富,对于它不支持的协议就无法进行解码。

    除了tcpdump之外,FreeBSD的Packages Collecion中还提供了Ethereal和Sniffit两个网络分析工具,以及其他一些基于网络分析方式的安全工具。其中Ethereal运行在X Window 下,具有不错的图形界面,Sniffit使用字符窗口形式,同样也易于操作。然而由于tcpdump对过滤规则的支持能力更强大,因此系统管理员仍然更喜欢使用它。对于有经验的网络管理员,使用这些网络分析工具不但能用来了解网络到底是如何运行的,故障出现在何处,还能进行有效的统计工作,如那种协议产生的通信量占主要地位,那个主机最繁忙,网络瓶颈位于何处等等问题。因此网络分析工具是用于网络管理的宝贵系统工具。为了防止数据被滥用的网络分析工具截获,关键还是要在网络的物理结构上解决。常用的方法是使用交换机或网桥将信任网络和不信任网络分隔开,可以防止外部网段窃听内部数据传输,但仍然不能解决内部网络与外部网络相互通信时的数据安全问题。如果没有足够的经费将网络上的共享集线器升级为以太网交换机,可以使用FreeBSD系统执行网桥任务。这需要使用option BRIDGE编译选项重新定制内核,此后使用bridge命令启动网桥功能。

tcpdump采用命令行方式,它的命令格式为:
      tcpdump [ -adeflnNOpqStvx ] [ -c 数量 ] [ -F 文件名 ]
          [ -i 网络接口 ] [ -r 文件名] [ -s snaplen ]
          [ -T 类型 ] [ -w 文件名 ] [表达式 ]

(1). tcpdump的选项介绍

   -a    将网络地址和广播地址转变成名字;
   -d    将匹配信息包的代码以人们能够理解的汇编格式给出;
   -dd    将匹配信息包的代码以c语言程序段的格式给出;
   -ddd    将匹配信息包的代码以十进制的形式给出;
   -e    在输出行打印出数据链路层的头部信息;
   -f    将外部的Internet地址以数字的形式打印出来;
   -l    使标准输出变为缓冲行形式;
   -n    不把网络地址转换成名字;
   -t    在输出的每一行不打印时间戳;
   -v    输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息;
   -vv    输出详细的报文信息;
   -c    在收到指定的包的数目后,tcpdump就会停止;
   -F    从指定的文件中读取表达式,忽略其它的表达式;
   -i    指定监听的网络接口;
   -r    从指定的文件中读取包(这些包一般通过-w选项产生);
   -w    直接将包写入文件中,并不分析和打印出来;
   -T    将监听到的包直接解释为指定的类型的报文,常见的类型有rpc (远程过程 调用)和snmp(简单       网络管理协议;)

(2). tcpdump的表达式介绍

    表达式是一个正则表达式,tcpdump利用它作为过滤报文的条件,如果一个报文满足表达式的条件,则这个报文将会被捕获。如果没有给出任何条件,则网络上所有的信息包将会被截获。在表达式中一般如下几种类型的关键字。

    第一种是关于类型的关键字,主要包括host,net,port, 例如 host 210.27.48.2,指明 210.27.48.2是一台主机,net 202.0.0.0 指明 202.0.0.0是一个网络地址,port 23 指明端口号是23。如果没有指定类型,缺省的类型是host.

    第二种是确定传输方向的关键字,主要包括src , dst ,dst or src, dst and src ,这些关键字指明了传输的方向。举例说明,src 210.27.48.2 ,指明ip包中源地址是210.27.48.2 , dst net 202.0.0.0 指明目的网络地址是202.0.0.0 。如果没有指明方向关键字,则缺省是src or dst关键字。

    第三种是协议的关键字,主要包括fddi,ip,arp,rarp,tcp,udp等类型。Fddi指明是在FDDI(分布式光纤数据接口网络)上的特定的网络协议,实际上它是”ether”的别名,fddi和ether具有类似的源地址和目的地址,所以可以将fddi协议包当作ether的包进行处理和分析。其他的几个关键字就是指明了监听的包的协议内容。如果没有指定任何协议,则tcpdump将会监听所有协议的信息包。

    除了这三种类型的关键字之外,其他重要的关键字如下:gateway, broadcast,less,greater,还有三种逻辑运算,取非运算是 ‘not ‘ ‘! ‘, 与运算是’and’,'&&’;或运算 是’or’ ,’││’;这些关键字可以组合起来构成强大的组合条件来满足人们的需要,下面举几个例子来说明。

    A想要截获所有210.27.48.1 的主机收到的和发出的所有的数据包:
#tcpdump host 210.27.48.1
B想要截获主机210.27.48.1 和主机210.27.48.2 或210.27.48.3的通信,使用命令:(在命令行中适用   括号时,一定要
#tcpdump host 210.27.48.1 and \ (210.27.48.2 or 210.27.48.3 \)
C如果想要获取主机210.27.48.1除了和主机210.27.48.2之外所有主机通信的ip包,使用命令:
#tcpdump ip host 210.27.48.1 and ! 210.27.48.2
D如果想要获取主机210.27.48.1接收或发出的telnet包,使用如下命令:
#tcpdump tcp port 23 host 210.27.48.1

(3). tcpdump的输出结果介绍

    下面我们介绍几种典型的tcpdump命令的输出信息

A,数据链路层头信息

使用命令
#tcpdump –e host ice
ice 是一台装有linux的主机,她的MAC地址是0:90:27:58:AF:1A
H219是一台装有SOLARIC的SUN工作站,它的MAC地址是8:0:20:79:5B:46;上一条命令的输出结果如下所示:
21:50:12.847509 eth0 < 8:0:20:79:5b:46 0:90:27:58:af:1a ip 60: h219.33357 > ice.telne
t 0:0(0) ack 22535 win 8760 (DF)

    分析:21:50:12是显示的时间, 847509是ID号,eth0 <表示从网络接口eth0 接受该数据包,eth0 >表示从网络接口设备发送数据包, 8:0:20:79:5b:46是主机H219的MAC地址,它表明是从源地址H219发来的数据包. 0:90:27:58:af:1a是主机ICE的MAC地址,表示该数据包的目的地址是ICE . ip 是表明该数据包是IP数据包,60 是数据包的长度, h219.33357 > ice.telnet 表明该数据包是从主机H219的33357端口发往主机ICE的TELNET(23)端口. ack 22535 表明对序列号是222535的包进行响应. win 8760表明发送窗口的大小是8760.

B,ARP包的TCPDUMP输出信息

使用命令
#tcpdump arp
得到的输出结果是:
22:32:42.802509 eth0 > arp who-has route tell ice (0:90:27:58:af:1a)
22:32:42.802902 eth0 < arp reply route is-at 0:90:27:12:10:66 (0:90:27:58:af:1a)
分析: 22:32:42是时间戳, 802509是ID号, eth0 >表明从主机发出该数据包, arp表明是ARP请求包, who-has route tell ice表明是主机ICE请求主机ROUTE的MAC地址。 0:90:27:58:af:1a是主机ICE的MAC地址。

C,TCP包的输出信息

    用TCPDUMP捕获的TCP包的一般输出信息是:
src > dst: flags data-seqno ack window urgent options
src > dst:表明从源地址到目的地址, flags是TCP包中的标志信息,S 是SYN标志, F (FIN), P (PUSH) , R (RST) “.” (没有标记); data-seqno是数据包中的数据的顺序号, ack是下次期望的顺序号, window是接收缓存的窗口大小, urgent表明数据包中是否有紧急指针. Options是选项.

D,UDP包的输出信息

    用TCPDUMP捕获的UDP包的一般输出信息是:
route.port1 > ice.port2: udp lenth
UDP十分简单,上面的输出行表明从主机ROUTE的port1端口发出的一个UDP数据包到主机ICE的port2端口,类型是UDP, 包的长度是lenth

三,利用网络数据采集分析工具TcpDump分析网络安全

    作为IP网络的系统管理员,经常会遇到一些网络连接方面的故障,在排查这些接故障时,除了凭借经验外,使用包分析软件往往会起到事半功倍的效果。

    常用的包分析软件非常多,常见的如tcpdump,sniffer,windump,ettercap等。

1 网络数据采集分析工具TcpDump分析

(1)网络的数据过滤

    不带任何参数的TcpDump将搜索系统中所有的网络接口,并显示它截获的所有数据,这些数据对我们不一定全都需要,而且数据太多不利于分析。所以,我们应当先想好需要哪些数据,TcpDump提供以下参数供我们选择数据:

-b在数据-链路层上选择协议,包括ip、arp、rarp、ipx都是这一层的。例如:
server#tcpdump -b arp
将只显示网络中的arp即地址转换协议信息。

-i选择过滤的网络接口,如果是作为路由器至少有两个网络接口,通过这个选项,就可以只过滤指定的接口上通过的数据。例如:
server#tcpdump -i eth0
只显示通过eth0接口上的所有报头。src、dst、port、host、net、ether、gateway这几个选项又分别包含src、dst、port、host、net、ehost等附加选项。他们用来分辨数据包的来源和去向,src host 192.168.0.1指定源主机IP地址是192.168.0.1,dst net 192.168.0.0/24指定目标是网络192.168.0.0。以此类推,host是与其指定主机相关无论它是源还是目的,net是与其指定网络相关的,ether后面跟的不是IP地址而是物理地址,而gateway则用于网关主机。可能有点复杂,看下面例子就知道了:
server#tcpdump src host 192.168.0.1 and dst net 192.168.0.0/24
过滤的是源主机为192.168.0.1与目的网络为192.168.0.0的报头。
server#tcpdump ether src 00:50:04:BA:9B and dst……
过滤源主机物理地址为XXX的报头(为什么ether src后面没有host或者net?物理地址当然不可能有网络喽)。
server#Tcpdump src host 192.168.0.1 and dst port not telnet
过滤源主机192.168.0.1和目的端口不是telnet的报头。
ip icmp arp rarp和tcp、udp、icmp这些选项等都要放到第一个参数的位置,用来过滤数据报的类型。例如:
server#tcpdump ip src……
只过滤数据-链路层上的IP报头。
server#tcpdump udp and src host 192.168.0.1
只过滤源主机192.168.0.1的所有udp报头。

(2)网络的数据显示/输入输出

    TcpDump提供了足够的参数来让我们选择如何处理得到的数据,如下所示:
-l可以将数据重定向。
如tcpdump -l>tcpcap.txt将得到的数据存入tcpcap.txt文件中。
-n不进行IP地址到主机名的转换。
如果不使用这一项,当系统中存在某一主机的主机名时,TcpDump会把IP地址转换为主机名显示,就像这样:eth0<ntc9.1165>router.domain.net.telnet,使用-n后变成了:eth0<192.168.0.9.1165>192.168.0.1.telnet。
-nn不进行端口名称的转换。
上面这条信息使用-nn后就变成了:eth0<ntc9.1165>router.domain.net.23。
-N不打印出默认的域名。
还是这条信息-N后就是:eth0<ntc9.1165>router.telnet。
-O不进行匹配代码的优化。
-t不打印UNIX时间戳,也就是不显示时间。
-tt打印原始的、未格式化过的时间。
-v详细的输出,也就比普通的多了个TTL和服务类型。

2 网络数据采集分析工具TcpDump分析详细例子

(1)网络邮件服务器(mail)在排障

    我们先来看看故障现象,在一局域网中新安装了后台为qmail的邮件服务器server,邮件服务器收发邮件等基本功能正常,但在使用中发现一个普遍的怪现象:pc机器上发邮件时连接邮件服务器后要等待很久的时间才能开始实际的发送工作。我们来看,从检测来看,网络连接没有问题,邮件服务器server和下面的pc性能都没有问题,问题可能出在哪里呢?为了进行准确的定位,我们在pc机client上发送邮件,同时在邮件服务器server上使用tcpdump对这个client的数据包进行捕获分析,如下:

server#tcpdump host client
tcpdump: listening on hme0
23:41:30.040578 client.1065 > server.smtp: S 1087965815:1087965815(0) win 64240 <mss 1460,nop,wscale 0,nop,nop,timestamp[│tcp]> (DF)
23:41:30.040613 server.smtp > client.1065: S 99285900:99285900(0) ack 1087965816 win 10136 <nop,nop,timestamp 20468779 0,nop,[│tcp]> (DF)
23:41:30.040960 client.1065 > server.smtp: . ack 1 win 64240 (DF)

    顺利的完成,到目前为止正常,我们再往下看:

23:41:30.048862 server.33152 > client.113: S 99370916:99370916(0) win 8760 <mss 1460> (DF)
23:41:33.411006 server.33152 > client.113: S 99370916:99370916(0) win 8760 <mss 1460> (DF)
23:41:40.161052 server.33152 > client.113: S 99370916:99370916(0) win 8760 <mss 1460> (DF)
23:41:56.061130 server.33152 > client.113: R 99370917:99370917(0) win 8760 (DF)
23:41:56.070108 server.smtp > client.1065: P 1:109(108) ack 1 win 10136 <nop,nop,timestamp 20471382 167656> (DF)

    看出问题了,问题在:我们看到server端试图连接client的113identd端口,要求认证,然而没有收到client端的回应,server端重复尝试了3次,费时26秒后,才放弃认证请求,主动发送了reset标志的数据包,开始push后面的数据,而正是在这个过程中所花费的26秒时间,造成了发送邮件时漫长的等待情况。问题找到了,就可以修改了,我们通过修改服务器端的qmail配置,使它不再进行113端口的认证,再次抓包,看到邮件server不再进行113端口的认证尝试,而是在三次检测后直接push数据,问题得到完美的解决。

(2)网络安全中的ARP协议的故障

    先看故障现象,局域网中的一台采用solaris操作系统的服务器A-SERVER网络连接不正常,从任意主机上都无法ping通该服务器。排查:首先检查系统,系统本身工作正常,无特殊进程运行,cpu,内存利用率正常,无挂接任何形式的防火墙,网线正常。此时我们借助tcpdump来进行故障定位,首先我们将从B-CLIENT主机上执行ping命令,发送icmp数据包给A-SERVER,如下:

[root@redhat log]# ping A-SERVER
PING A-SERVER from B-CLIENT : 56(84) bytes of data.
此时在A-SERVER启动tcpdump,对来自主机B-CLIENT的数据包进行捕获。
A-SERVER# tcpdump host B-CLIENT
tcpdump: listening on hme0
16:32:32.611251 arp who-has A-SERVER tell B-CLIENT
16:32:33.611425 arp who-has A-SERVER tell B-CLIENT
16:32:34.611623 arp who-has A-SERVER tell B-CLIENT

    我们看到,没有收到预料中的ICMP报文,反而捕获到了B-CLIENT发送的arp广播包,由于主机B-CLIENT无法利用arp得到服务器A-SERVER的地址,因此反复询问A-SERVER的MAC地址,由此看来,高层的出问题的可能性不大,很可能在链路层有些问题,先来查查主机A-SERVER的arp表:

A-SERVER# arp -a
Net to Media Table
Device IP Address Mask Flags Phys Addr
—— ——————– ————— —– —————
hme0 netgate 255.255.255.255 00:90:6d:f2:24:00
hme0 A-SERVER 255.255.255.255 S 00:03:ba:08:b2:83
hme0 BASE-ADDRESS.MCAST.NET 240.0.0.0 SM 01:00:5e:00:00:00

    请注意A-SERVER的Flags位置,我们看到了只有S标志。我们知道,solaris在arp实现中,arp的flags需要设置P标志,才能响应ARP requests。

手工增加p位
A-SERVER# arp -s A-SERVER 00:03:ba:08:b2:83 pub
此时再调用arp -a看看
A-SERVER# arp -a
Net to Media Table
Device IP Address Mask Flags Phys Addr
—— ——————– ————— —– —————
hme0 netgate 255.255.255.255 00:90:6d:f2:24:00
hme0 A-SERVER 255.255.255.255 SP 00:03:ba:08:b2:83
hme0 BASE-ADDRESS.MCAST.NET 240.0.0.0 SM 01:00:5e:00:00:00

    我们看到本机已经有了PS标志,此时再测试系统的网络连接恢复正常,问题得到解决。

(3)netflow软件的问题

    先看故障现象,在新装的网管工作站上安装cisco netflow软件对路由设备流量等进行分析,路由器按照要求配置完毕,本地工作上软件安装正常,无报错信息,但是启动netflow collector却收不到任何路由器上发出的流量信息,导致该软件失效。 排查现象,反复检查路由和软件,配置无误。采用逐步分析的方法,首先先要定位出有问题的设备,是路由器根本没有发送流量信息还是本地系统接收出现了问题?突然想到在路由器上我们定义了接收的client端由udp端口9998接收数据,可以通过监视这个端口来看路由器是否确实发送了udp数据,如果系统能够接收到来自路由的数据包,那么路由方面的问题可能行不大,反之亦然。

    在网管工作站上使用tcpdump来看看:

nms#tcpdump port 9995
tcpdump: listening on hme0
18:15:34.373435 routea > nms.9995: udp 1464
18:15:34.373829 routea.50111 > nms.9995: udp 1464
18:15:34.374100 routea.50111 > nms.9995: udp 1464
 
    马上我们就看到数据包确实从路由器上发过来了,问题出在路由器的可能性基本排除,重新核查系统,果然,网管工作站上安装了防火墙,udp端口9998是被屏蔽的,调整工作站上的防火墙配置,netflow工作恢复正常,故障得以排除。

    结尾:上面我们通过3个实际的例子演示了网络数据采集分析工具TcpDump分析软件在故障解决中起到的作用,通过这些例子,我们不难发现,用好包分析软件,对系统管理员快速准确定位网络故障,分析网络问题有不可替代的作用。任何事情都具有两面性,事实上能够获得网络上传输的数据的工具对于维护网络运行也非常重要,网络需要这些工具软件来帮助分析网络状态、解决各种网络故障,它们是网络工程师的好帮手。

    在市场上销售的有好几种专用的网络分析设备,来实现截获数据并进行分析的目的。虽然这些硬件实现的设备虽然功能强大,但价格昂贵,而使用软件通过标准计算机的网络接口来实现这种功能,相对来讲对于一般使用者还是可以承受的。

发信站: 武汉白云黄鹤站 (Tue May 15 09:43:22 2001) , 转信

来源:http://www.china-pub.com/computers/emook/0424/info.htm
作者:李国莉 


tcpdump采用命令行方式,它的命令格式为:
  tcpdump [ -adeflnNOpqStvx ] [ -c 数量 ] [ -F 文件名 ]
          [ -i 网络接口 ] [ -r 文件名] [ -s snaplen ]
          [ -T 类型 ] [ -w 文件名 ] [表达式 ]

  1. tcpdump的选项介绍
   -a    将网络地址和广播地址转变成名字;
   -d    将匹配信息包的代码以人们能够理解的汇编格式给出;
   -dd    将匹配信息包的代码以c语言程序段的格式给出;
   -ddd    将匹配信息包的代码以十进制的形式给出;
   -e    在输出行打印出数据链路层的头部信息;
   -f    将外部的Internet地址以数字的形式打印出来;
   -l    使标准输出变为缓冲行形式;
   -n    不把网络地址转换成名字;
   -t    在输出的每一行不打印时间戳;
   -v    输出一个稍微详细的信息,例如在ip包中可以包括ttl和服务类型的信息;
   -vv    输出详细的报文信息;
   -c    在收到指定的包的数目后,tcpdump就会停止;
   -F    从指定的文件中读取表达式,忽略其它的表达式;
   -i    指定监听的网络接口;
   -r    从指定的文件中读取包(这些包一般通过-w选项产生);
   -w    直接将包写入文件中,并不分析和打印出来;
   -T    将监听到的包直接解释为指定的类型的报文,常见的类型有rpc (远程过程
调用)和snmp(简单       网络管理协议;)

  2. tcpdump的表达式介绍
   表达式是一个正则表达式,tcpdump利用它作为过滤报文的条件,如果一个报文满足表
达式的条件,则这个报文将会被捕获。如果没有给出任何条件,则网络上所有的信息包将会
被截获。
   在表达式中一般如下几种类型的关键字,一种是关于类型的关键字,主要包括host,
net,port, 例如 host 210.27.48.2,指明 210.27.48.2是一台主机,net 202.0.0.0 指明
202.0.0.0是一个网络地址,port 23 指明端口号是23。如果没有指定类型,缺省的类型是
host.
   第二种是确定传输方向的关键字,主要包括src , dst ,dst or src, dst and src ,
这些关键字指明了传输的方向。举例说明,src 210.27.48.2 ,指明ip包中源地址是210.27.
48.2 , dst net 202.0.0.0 指明目的网络地址是202.0.0.0 。如果没有指明方向关键字,则
缺省是src or dst关键字。
   第三种是协议的关键字,主要包括fddi,ip ,arp,rarp,tcp,udp等类型。Fddi指明是在
FDDI(分布式光纤数据接口网络)上的特定的网络协议,实际上它是”ether”的别名,fddi和e
ther具有类似的源地址和目的地址,所以可以将fddi协议包当作ether的包进行处理和分析。
其他的几个关键字就是指明了监听的包的协议内容。如果没有指定任何协议,则tcpdump将会
监听所有协议的信息包。
   除了这三种类型的关键字之外,其他重要的关键字如下:gateway, broadcast,less,
greater,还有三种逻辑运算,取非运算是 ‘not ‘ ‘! ‘, 与运算是’and’,'&&’;或运算 是’o
r’ ,’||’;
   这些关键字可以组合起来构成强大的组合条件来满足人们的需要,下面举几个例子来
说明。
   (1)想要截获所有210.27.48.1 的主机收到的和发出的所有的数据包:
    #tcpdump host 210.27.48.1
   (2) 想要截获主机210.27.48.1 和主机210.27.48.2 或210.27.48.3的通信,使用命令
:(在命令行中适用   括号时,一定要
    #tcpdump host 210.27.48.1 and \ (210.27.48.2 or 210.27.48.3 \)
   (3) 如果想要获取主机210.27.48.1除了和主机210.27.48.2之外所有主机通信的ip包
,使用命令:
    #tcpdump ip host 210.27.48.1 and ! 210.27.48.2
   (4)如果想要获取主机210.27.48.1接收或发出的telnet包,使用如下命令:
    #tcpdump tcp port 23 host 210.27.48.1

  3. tcpdump 的输出结果介绍
   下面我们介绍几种典型的tcpdump命令的输出信息
   (1) 数据链路层头信息
   使用命令#tcpdump –e host ice
   ice 是一台装有linux的主机,她的MAC地址是0:90:27:58:AF:1A
   H219是一台装有SOLARIC的SUN工作站,它的MAC地址是8:0:20:79:5B:46;上一条
命令的输出结果如下所示:
21:50:12.847509 eth0 < 8:0:20:79:5b:46 0:90:27:58:af:1a ip 60: h219.33357 > ice.
telne
t 0:0(0) ack 22535 win 8760 (DF)
  分析:21:50:12是显示的时间, 847509是ID号,eth0 <表示从网络接口eth0 接受该
数据包,eth0 >表示从网络接口设备发送数据包, 8:0:20:79:5b:46是主机H219的MAC地址,它
表明是从源地址H219发来的数据包. 0:90:27:58:af:1a是主机ICE的MAC地址,表示该数据包的
目的地址是ICE . ip 是表明该数据包是IP数据包,60 是数据包的长度, h219.33357 > ice.
telnet 表明该数据包是从主机H219的33357端口发往主机ICE的TELNET(23)端口. ack 22535
表明对序列号是222535的包进行响应. win 8760表明发送窗口的大小是8760.

  (2) ARP包的TCPDUMP输出信息
   使用命令#tcpdump arp
   得到的输出结果是:
  22:32:42.802509 eth0 > arp who-has route tell ice (0:90:27:58:af:1a)
  22:32:42.802902 eth0 < arp reply route is-at 0:90:27:12:10:66 (0:90:27:58:af
:1a)
  分析: 22:32:42是时间戳, 802509是ID号, eth0 >表明从主机发出该数据包, arp表明是
ARP请求包, who-has route tell ice表明是主机ICE请求主机ROUTE的MAC地址。 0:90:27:5
8:af:1a是主机ICE的MAC地址。

  (3) TCP包的输出信息
   用TCPDUMP捕获的TCP包的一般输出信息是:
  src > dst: flags data-seqno ack window urgent options
  src > dst:表明从源地址到目的地址, flags是TCP包中的标志信息,S 是SYN标志, F (F
IN), P (PUSH) , R (RST) “.” (没有标记); data-seqno是数据包中的数据的顺序号, ack是
下次期望的顺序号, window是接收缓存的窗口大小, urgent表明数据包中是否有紧急指针.
Options是选项.

  (4) UDP包的输出信息
   用TCPDUMP捕获的UDP包的一般输出信息是:
  route.port1 > ice.port2: udp lenth
  UDP十分简单,上面的输出行表明从主机ROUTE的port1端口发出的一个UDP数据包到主机
ICE的port2端口,类型是UDP, 包的长度是lenth

2004年12月25日

上来留个言,在北京这边开会。会议组织的算是比较一般。不过见到了宝宝,很高兴。昨天还一起过了平安夜(and also my DOB LOL)。:)HOHO,挺高兴的。

现在是会议期间溜号出来。一会儿回去接着听。:)

2004年12月19日

Multiple local XFree users under Linux

Version 0.9 by Miguel Freitas <miguel@cetuc.puc-rio.br>

January 16, 2001



Keywords (for bots)

I’ve wasted a lot of time trying to find this kind of document in google, hotbot and so on. Let me add some keywords to help people finding it: true dual-head, multi-user support, XFree86 4.0, multiple keyboard, multiple mouse, multiple video card, dual user, XFree86 instances, dual keyboard, USB keyboard under X.
 

Motivation
 

I have one girlfriend and one computer. In normal conditions, we both couldn’t use the computer at the same time, in spite of the fact that it usually has a lot of processing power available. I also have a spare monitor and a second video card for playing 3D games (voodoo) so this idea came to me as something very obvious. New XFree86 4.0 support for dualhead suggests that most of the hard work is already done. And it has to be on Linux, because no closed source OS would allow me to make the changes that I need.

As several reports confirm, Linux is been successfully used in educational institutions and projects due to it’s great benefits and low cost. Using the same computer for two (or more) simultaneous students, workers, etc. is something that can reduce even more these costs.

This is also a great option for companies to simplify the management and upgrades of the shared resources (motherboard, processor, hds).

For everybody who may be asking: don’t it get too slow? No. The performance difference is barely perceptible as most of the time the computer is waiting some command from the user. And if you haven’t figured it out by yourself let me tell something: we live in a time of computing power in excess or do you think most of the users needs a GigaHertz Pentium 3 machine just to do their word processing and surf the web?
 

Problems
 

There are some problems that need to be addressed in order to support multiple XFree instances (and users):

  • VT handling – The Linux kernel Virtual Terminal scheme is a great hack these days. It used to be good in the past as a way to have multiple screens, but now it’s something that needs to be completely rewritten (several Linux developers have shown interest in developing a better scheme for 2.5.x series). The main issue is that VT code doesn’t understand that we may have multiple input and output devices which therefore may be completely independent. There’s no way to associate a given set of VTs for each hardware so Linux kernel would know which VTs can be used simultaneously. If we dispatch multiple instances of XFree86 they would be on different VTs and the Linux kernel will inform them of all VT switching stuff. A switched out (graphic) VT must not use the hardware as it would normally mess with the other active VT, but this is no more true as we have two independent video cards.
  • Keyboard support – Multiple mouses on X are already a reality as we may specify the “device” option for each one. Unfortunately, the keyboard driver is still deeply rooted at XFree86 core, it’s not a separated module and access console I/O functions to read the scancodes. Each XFree86 instance would have their keyboard access halted by VT switching. Besides, Linux is still lacking support for multiple keyboards in a well defined way. Let’s wait for 2.5.x tree to see what will be done…

My solution

My hack is surely not the best one, I know thousands of things that could be better implemented in XFree86 and Linux Kernel to support true dual-head (and dual-input) in a clean way. But it works for me. Don’t blame me if you spend your money and time buying videocards, monitors, keyboards, mouses and it doesn’t work. You’ve been warned.

Although I would love to see XFree86 supporting simultaneous layouts (without another instance) and a brand new keyboard driver, I don’t have the necessary understanding of the project to implement it by myself. Anyway, my regards to the XFree86 developers for this great piece of software!

My idea is to have two instances of XFree86. The first will be using a normal XFree86 server, it will initialize the main video card and attach it to a VT. It will also use the standard system AT keyboard and something (PS/2, serial, USB emulated as PS/2, whatever you want) as a mouse.

The second instance of XFree will be my modified X server. It does not support VT switching at all because it’s been used to control a hardware that is not normally used by any other VT. Read my lips, this is very important: The video card can’t be the primary one, the mouse can’t be the same used by gpm and the keyboard must be USB and must not generate scancodes to the normal Linux console!

As the keyboard doesn’t look like a normal AT keyboard (no keys to standard console) the keyboard driver of my modified X server must take care of USB events translating them to normal scancodes.
 

Procedure (step by step)
 

1) You need to get XFree 4.0.x (RedHat 7.0 and a lot of recent distros comes with it) and configure it for two video cards and monitors. I suggest that you first try it with Xinerama extension following this HowTo: http://linuxdocs.org/HOWTOs/Xinerama-HOWTO.html

Then modify your XF86Config or XF86Config-4 to separate your screens in two layouts, instead of using them with Xinerama extension. Don’t know what I am talking about? Then it’s time to read XF86Config, do a “man XF86Config”

With two layouts your XF86Config should look like this:
 

Section "ServerLayout"
    Identifier "Layout0"
    Screen 0 "Screen0"
    InputDevice "Mouse0" "CorePointer"
    InputDevice "Keyboard0" "CoreKeyboard"
EndSection

Section "ServerLayout"
    Identifier "Layout1"
    Screen 0 "Screen1"
    InputDevice "Mouse0" "CorePointer"
    InputDevice "Keyboard0" "CoreKeyboard"
EndSection

Section "InputDevice"
    Identifier "Keyboard0"
    Driver "keyboard"
    # this is for supporting deadkeys
    Option "XkbRules" "xfree86"
    Option "XkbModel" "us"
    Option "XkbLayout" "br"
EndSection

Section "InputDevice"
    Identifier "Mouse0"
    Driver "mouse"
    Option "Device" "/dev/mouse"
    Option "Protocol" "IMPS/2"
    Option "Emulate3Buttons" "off"
    Option "ZAxisMapping" "4 5"
EndSection

Section "Monitor"
    Identifier "Plex17"
    VendorName "Unknown"
    ModelName "Unknown"
    HorizSync 31.5 - 79.0
    VertRefresh 50-90
EndSection

Section "Monitor"
    Identifier "Syncmaster3"
    HorizSync 31.5 - 79.0
    VertRefresh 50-70
EndSection

Section "Device"
    Identifier "FireGL 1000 PRO"
    Driver "glint"
    BusID "pci:1:0:0"
    BoardName "Unknown"
EndSection

Section "Device"
    Identifier "Voodoo"
    Driver "glide"
    BusID "pci:0:12:0"
EndSection

Section "Screen"
    Identifier "Screen0"
    Device "FireGL 1000 PRO"
    Monitor "Plex17"
    DefaultDepth 16
    Subsection "Display"
       Depth 16
       Modes "1024x768"
    EndSubSection
EndSection

Section "Screen"
    Identifier "Screen1"
    Device "Voodoo"
    Monitor "SyncMaster 3"
    DefaultDepth 16
    SubSection "Display"
       Depth 16
       Modes "800x600"
    EndSubSection
EndSection

This should be trivial to do because it's almost the same as Xinerama configuration but with two layouts. Then switch your box to runlevel 3 (init 3) and try both layouts, one at a time:

# XFree86 -layout Layout0
# XFree86 -layout Layout1

Pay attention to BusID settings as described in howto. Note that a dualhead board (like Matrox G400) should NOT work through the next steps, as we will be using 2 instances talking to the same hardware. But I haven't tried myself (I'd be happy to try it if any reader wants to donate such video card...).

Not all video cards can be used with XFree86 dualhead support. Don't email me saying that you couldn't get your cards to work up to here or you will burn in hell! Read the Xinerama HowTo instead, thanks.
 

2) Plug your second mouse on the system and configure XF86Config to use it in the second layout. This mouse must not be used by any other program, like gpm. XF86Config will look like this (only the changed sections):

Section "ServerLayout"
    Identifier "Layout1"
    Screen 0 "Screen1"
    InputDevice "Mouse1" "CorePointer"
    InputDevice "Keyboard0" "CoreKeyboard"
EndSection

 
Section "InputDevice"
    Identifier "Mouse1"
    Driver "mouse"
    Option "Device" "/dev/ttyS1"
    Option "Protocol" "Microsoft"
EndSection
 
Again, test this layout to make sure it's working.
 

3) Get Linux Kernel 2.4.0 so we can play with USB support. Some 2.2.x kernels may work as they have backported USB support, but in doubt, stick with 2.4.0.

In the kernel configuration, enable USB support (CONFIG_USB) and keyboard (either CONFIG_USB_HID or CONFIG_USB_KBD if your don't need USB mouse support). You must enable "input core support" (CONFIG_INPUT) and MUST NOT enable "keyboard support" (CONFIG_INPUT_KEYBDEV) as we don't want the USB one to be the system keyboard. Also enable "event interface" (CONFIG_INPUT_EVDEV) as I will use it to receive scancodes.

Compile and install the kernel. Now plug your USB keyboard, once the kernel enters you should not see any pressed keys from it at the console. Now try reading the keyboard events (assuming the keyboard is the only USB device you have):

# cat /dev/input/event0

You should see some garbage on the screen as you type. That's all right, your keyboard is working. If you don't see anything or get "No such device", something is wrong with your USB system. Read Documentation/usb in your kernel sources for more information.
 

4) Get the sources of your XFree86 4.0.x if you haven't already done so. The sources are available from www.xfree86.org. There should be 3 or 4 big .tgz files, but you will only need the first one.

Expand the tree and apply my patch, which can be downloaded here (4.0.1) and here (4.0.2). Follow the instructions from the package to build the X server (make World). You should get a new XFree86 executable on directory xc/programs/Xserver. Copy it to your /usr/X11R6/bin with another name (like XFree86-2nd).

Or if you like the easy way, try one of my XFree86-2nd servers (compiled against glibc-2.1):

XFree86-4.0.1-2nd.gz

XFree86-4.0.2-2nd.gz

This server supports only USB keyboards and do not grab a VT. The only VT code it has is to switch to a given console through XFree86-2nd vtxx parameter.

Applying the patch is intended only for developers that can help me improving this scheme. It will also require you hundreds of MB of disk space. If my provided X servers doesn't work with your system there's little I can do about it. If you can, try to discover the problem and fix it.
 

5) Modify the second layout to use the USB keyboard. This will require you to use the protocol "usbev" I created and specify the /dev/input/eventx you like as the device. The XF86Config should now look like this (only the changed sections):

Section "ServerLayout"
    Identifier "Layout1"
    Screen 0 "Screen1"
    InputDevice "Mouse1" "CorePointer"
    InputDevice "Keyboard1" "CoreKeyboard"
EndSection
 
Section "InputDevice"
    Identifier "Keyboard1"
    Driver "keyboard"
    Option "Protocol" "usbev"
    Option "Device" "/dev/input/event0"
EndSection
 
Now try this X server with the command:

# XFree86-2nd -layout Layout1

It should initialize your second video card, the second mouse and the usb keyboard without interfering with your console. You can even do this from a xterm window inside your running X server. Yes! It works! Now move on to the grand finale...
 

6) If you use gdm as display manager and to provide you a graphical login, you can edit the file /etc/X11/gdm/gdm.conf as follows:

[servers]
0=/usr/bin/X11/XFree86-2nd -delay -layout layout1 vt07
1=/usr/bin/X11/X vt07

Getting this one to work may be a major challenge. It took me a lot of trial and error until I got this stable configuration. I had to add a option "-delay" (my hack) to cause a 10 second delay at one of the servers so they would not initialize the hardware at the same time. I don't know why this is needed. Playing with the order they are initialized (by exchanging 0= and 1=) also does the trick.
 

Known Bugs
 

This thing mess up with my text console. I have to switch between the VTs a couple of times before the text looks good again. Fell free to give me a solution.

Also a main problem may be that the whole thing does not work with other hardware and you may be wasting your time reading all this. But the idea is here and I can guarantee that it worked for me. So it must be some little issue that I'm sure will be quickly resolved by another developer somewhere....
 

Updates

Price study

Brad Midgley pointed that support for Matrox G400 and similar dualhead cards should be possible using framebuffer interface. I still don't have the hardware to do any tests on this, but if you want to try please note that I may have removed something important for framebuffer from the init routines. Please check for any mistakes the patch might have. Any updates on this issue are greatly appreciated...
 

Brad Midgley pointed that support for Matrox G400 and similar dualhead cards should be possible using framebuffer interface. I still don't have the hardware to do any tests on this, but if you want to try please note that I may have removed something important for framebuffer from the init routines. Please check for any mistakes the patch might have. Any updates on this issue are greatly appreciated...
 

Contact
 

Miguel Freitas <miguel@cetuc.puc-rio.br >
Center for Telecommunications Studies of the
Catholic University of Rio de Janeiro (CETUC/PUC-Rio)
Brazil

简单的说来,要点就是环境变量,还有启动脚本。
中文输入涉及到的环境变量有:LC_ALL, XIM XMODIFIERS等等。我解决scim的输入,只用到了XMODIFIERS这个环境变量。


下面的内容选自:http://www.linuxforum.net/forum/showflat.php?Cat=&Board=debian&Number=528321&page=0&view=collapsed&sb=5&o=31&fpart=

用GDM做窗口管理器,

在会话(Session)里面选择默认的会话(实际上是读取我的~/.xsession文件)



我的.xsession设置如下(记得给.xsession加上可执行标记 chmod a+x .xsession):



#!/bin/sh

export XMODIFIERS=’@im=SCIM’

export LANG=’en_US.UTF-8′ LC_ALL=’en_US.UTF-8′

exec xscreensaver -no-splash &

scim -d

exec gnome-session

#exec wmaker



我用的是windowmaker,如果你用gnome,可以将gnome-session的那个注释去掉。

这个样子就是了。



也就是说,装好了SCIM以后,只需在.xsession这个文件中添加export XMODIFIERS=’@im=SCIM’就可以了。当然这只满足了第一个环境变量的要求,然后在scim -d,也就是将SCIM启动起来。这样就OK了。

Chinese pixel project need your help.  Please come here in ‘write’ a Chinese character.

这是一个为中文编辑点阵字的站点。请来为中文作出贡献。

http://sitaphi.com/pub/song_jian_biao/index.cgi?%e9%a6%96%e9%a1%b5

Thank you!

2004年12月17日

Well, finally I got a small HD but it’s OK for me to install a debian system.  Debian is not bad, but still don’t know how to config SCIM.

2004年12月12日

为何游戏机效率比同配置pc高?









http://games.sina.com.cn 2004-12-09 10:13 新浪游戏

  不知道大家注意到没有,同样的硬件水平下,游戏机的执行效率比pc高不是一点半点。


  这个问题自从玩惯了80486 pc上劣质画面的游戏,突然看到 playstation 1 的华丽3d画面时候起就一直困扰着我。不仅ps系列如此,其他主机也同样。


  直到看了hi-pda上UGlee大侠的一篇文章我才矛塞顿开,大侠的文章本来是讨论poc





ket pc和palm os pda之间的执行效率差异,我发现稍加修改后就能套用在pc和游戏机间。论文如下:


  *****************************************************************


  PC在内存使用上是常规意义上的多任务系统,它具有内存管理单元,而且是硬件上的(CPU中),所以每个用户程序有自己独立的程序内存空间,静态数据内存空间,和栈空间。而动态内存的使用,也就是你在C语言中New一个对象,或者Malloc内存的时候,是使用系统所有程序共享的堆内存空间。


  由于使用了内存管理单元,它有很好的进程保护特性,一个程序是不可能轻易更改其他程序的内存资料的,这也是安全性和系统稳定性的一个保证–不过稳定性更多的是从操作系统理论上讲的,其前提是无穷大的物理内存可用。。而非实时操作系统理论中并不涉及程序的响应时间问题,也不考虑物理内存紧张的时候系统性能恶化和程序无法申请内存时的应对–而这恰恰是很多嵌入式系统的real world环境,所以,在实际应用中这样延续桌面甚至服务器系统的设计方式是否符合用户的需求,就时一个大大的问号了。


  而Win32体系,由于从桌面上延伸过来,更多的考虑了程序或者程序开发的向前兼容问题,在内存管理上还有其他的弱点。典型的问题就是内存漏洞和内存泄漏。在Win32构架中,系统没办法Defrag内存碎片,即使还有相当多的内存可用,如果没有一段连续的空间,仍然无法申请到足够的内存;而从系统动态内存中申请到的内存,如果程序忘记归还,或者程序意外中止,都会造成内存泄漏,这也是我们在桌面上系统越用越慢,内存越用越少的主要原因。


  另外的一个问题是,Win32体系,和所有其他的桌面操作系统一样,都是针对串行非挥发存储设计的(Win的前身DOS-Disk Operating System, , 虽然磁盘是一个界于串行存储和随机存储之间的物理设备,但是在数据结构的概念上它还是一个串行存储设备)。那么,程序在执行前需要从磁盘上载入,OS的进程列表中出现一个新的进程,分配栈空间和静态内存空间,然后程序运行,绝大多数程序都会用到动态内存。而打开文件的时候,多数情况下也需要先吧文件或者至少是文件中的一部分内容读入内存,转换成为程序需要的数据结构,在使用结束之后再重新串行化数据,写入文件。


  既然这样执行程序效率低下,要那为什么不直接存储数据对象,原位使用呢?


  这就是游戏机OS的设计方式。


  在操作系统教材中是没可能找到一个游戏机OS这样的四不象怪物的。它有一个多任务的内核,但是确只能有一个用户程序在运行,有系统级的图形控件,在底层支持图形加速只有只有几十K的系统栈空间,动态内存空间更是少的可怜(最捍的ps2是32M,PS只有2M),在系统只有不足64k的内存可用于执行程序而不是储存纹理、游戏数据的时候,仍然可以畅快的运行所有游戏。


  游戏机OS没有用户程序级的多进程/多线程支持–这是一个缺点,在流式数据应用的时候会有力不从心的感觉:表现在部分多媒体应用和网络应用上。不过当我们把注意力集中在一个程序的运行过程的时候,就会发现游戏机OS设计上优秀的一面。


  一个程序在多任务操作系统(PC)中运行时需要这些内存:


  1、OS进程列表中的一项,记录进程的所有寄存器状态和内存指针,其实也就是CPU现场,用于切换程序的时候保存和还原现场。这部分内存可以忽略不急。


  2、程序的执行代码空间。


  3、程序的静态数据空间,可大可小,但至少界面和全局变量是要初始化的吧。


  4、栈空间,用户函数调用的时候传递参数。也是可大可小,不过面向对象编程的时候,难以控制函数调用的嵌套次数,甚至有些编程风格恶劣的程序员经常用它来传递大的数据对象,那栈空间可能就会很大很大了。


  5、堆空间,也就是动态内存,从程序角度而言是存放临时对象的,不过这个临时经常会大的恐怖,比如处理图片的时候。


  在游戏机OS中,创造了一个独特的Storage Heap概念。通常我们就把他成为游戏机上的文件系统,但是从程序角度而非用户角度而言,它和文件的差异就太大了。Storage Heap是使用类似数据库的方式存储的,它有安全读写检查,以此保证数据的安全性和完整性不被破坏;它可以直接的指针操作,具有和内存访问一样的效率。那么,文件(这是用户角度的名称)和数据对象(这是程序角度的名称)就完美的统一了。而当不在需要把文件转换成数据对象的时候,我们还需要那么大的堆空间干嘛呢? (流式应用除外,)


  而程序本身,也是放在Storage Heap里面的,执行的时候只要把CPU的代码段指针直接指想程序代码的入口即可,连程序代码也是不需要载入过程的。


  游戏机OS在系统底层的图形控件支持,大大减少了程序绘制界面需要的内存空间,所以绝大多数程序只要控制一下不太多的全局变量就可以了。几K的空间通常就是非常奢侈的了。


  由于游戏机OS只有一个用户程序可以运行,而系统的栈空间只给了几十K,所以,程序员不得不用指针传递大数据对象,不但减少了内存需求,而且提高了效率。


  在内存泄漏和内存碎片问题上,游戏机OS也有优秀设计。后台的内存管理程序会在空闲时或者连续内存不足时整理内存碎片(需要程序开发者使用特定的API分配动态内存,不过Palm程序开发者都会这样做的),也可以回收程序忘记回收的动态内存。


  通过这些方式,游戏机OS把系统内存的使用降低到了少的可怜的程度,同时也把程序的运行效率推向了极致。


  ******************************************************************


  以上,就是说,游戏机比pc效率高的一个重要原因就是使用了效率高的多的内存使用方式,使用更少的内存,更少的cpu资源就可以做出画面更华丽的游戏。而wintel系列,呵呵就玩游戏方面以我所见除了多任务时候fpe以外没有什么比游戏机os好的地方。效率低下的代码执行方式决定了硬件资源的浪费。


  很遗憾,目前市面还没有哪个操作系统可以避免上文提及的低效率程序执行方式,所有的程序还是要先被载入内存然后才能执行。毕竟pc上的操作系统是为了工作而不是玩游戏设计的。除非有一天为pc机设计的专门用于玩游戏的操作系统问世,否则恐怕我们将不得不面对同样硬件水平下游戏机效果好过pc一大截的事实。说道这,如果有人crack掉xbox的操作系统让它能装到Pc上,那使用pIII633+geforce 3显卡+64m内存+DVD光驱的pc机就能玩所有xbox游戏了吧,嘿嘿~拭目以待~~~


  来源:TGFC


  作者:dreamz

作者:DDVIP 更新人:Ideal 来源:不详 更新时间:2004-07-01 投稿信箱: tg*ddvip.co





本函数库提供 System V 的信号处理机制。这个机制可以让系统限制同时使用行程所存取的资源。本函数库亦提供了内存共享的机制,可让不同的程序存取相同的变量,方便交换程序信息。

下表为系统的共享内存的限制值














SHMMAX 共享内存的最大值,一般为 131072 bytes
SHMMIN 共享内存的最小值,一般为 1 byte
SHMMNI 内存共享部分的最大值,一般为 100
SHMSEG 每个行程所能共享的最大内存空间,一般为 6



sem_get: 取得信号代码。
sem_acquire: 捕获信号。
sem_release: 释出信号。
shm_attach: 打开建立共享内存空间。
shm_detach: 中止共享内存空间链接。
shm_remove: 清除内存空间。
shm_put_var: 加入或更新内存空间中的变量。
shm_get_var: 取得内存空间中指定的变量。
shm_remove_var: 删除内存空间中指定的变量。


sem_get
取得信号代码。
语法: int sem_get(int key, int [max_acquire] , int [perm]);
返回值: 整数
函数种类: 操作系统与环境
内容说明: 本函数用来取得 System V 系统信号 (semaphore) 的代码值。参数 key 为存取信号的键值。参数 max_acquire 可省略,默认值为 1,表示同时可取得的处理数目。参数 perm 可省略,表示该内存空间的控制权限,默认值为 0666。
参考: sem_acquire() sem_release()


sem_acquire
捕获信号。
语法: int sem_acquire(int sem_identifier);
返回值: 整数
函数种类: 操作系统与环境
内容说明: 本函数用来捕获系统信号 (semaphore)。若捕捉信号的数量超过限度 (max_acquire),则行程在捕捉时会先封锁 (block) 住信号。
参考: sem_get() sem_release()


sem_release
释出信号。
语法: int sem_release(int sem_identifier);
返回值: 整数
函数种类: 操作系统与环境
内容说明: 本函数用来释出调用行程捕获的系统信号 (semaphore)。成功则返回 true 值。
参考: sem_get() sem_acquire()


shm_attach
打开建立共享内存空间。
语法: int shm_attach(int key, int [memsize], int [perm]);
返回值: 整数
函数种类: 操作系统与环境
内容说明: 本函数用来打开或者建立共享内存空间。参数 key 为这部分的键。参数 memsize 可省略,表示所需最小的内存空间 (单位为 byte 位组),默认值在 php3.ini 或 php.ini 中的 sysvshm.init_mem 配置,若无配置则为 10000 bytes。参数 perm 亦可省略,为该内存空间的使用权限,默认值为 666。返回值为共享内存的ID 值,可供程序使用。


shm_detach
中止共享内存空间链接。
语法: int shm_detach(int shm_identifier);
返回值: 整数
函数种类: 操作系统与环境
内容说明: 本函数用来中止与共享内存空间的链接。参数 shm_identifier 即为欲停止部分的共享内存 ID 值。


shm_remove
清除内存空间。
语法: int shm_remove(int shm_identifier);
返回值: 整数
函数种类: 操作系统与环境
内容说明: 本函数用来清除共享内存空间的所有资料。参数 shm_identifier 即为欲停止部分的共享内存 ID 值。


shm_put_var
加入或更新内存空间中的变量。
语法: int shm_put_var(int shm_identifier, int variable_key, mixed variable);
返回值: 整数
函数种类: 操作系统与环境
内容说明: 本函数可用来增加或者修改内存空间中变量值。参数 shm_identifier 为欲增加修改的共享内存 ID 值。参数 variable_key 为欲增加修改的变量名称键。参数 variable 为变量的内容,变量的类型可以是倍精确数 (double)、整数 (integer)、字符串 (string) 或者是数组 (array)。


shm_get_var
取得内存空间中指定的变量。
语法: mixed shm_get_var(int shm_identifier, int variable_key);
返回值: 混合类型资料
函数种类: 操作系统与环境
内容说明: 本函数可用来取得内存空间中指定的变量值。参数 shm_identifier 为欲取得的共享内存 ID 值。参数 variable_key 为欲取得的变量名称键。返回值即为指定变量键的值。


shm_remove_var
删除内存空间中指定的变量。
语法: int shm_remove_var(int id, int variable_key);
返回值: 整数
函数种类: 操作系统与环境
内容说明: 本函数可用来删除内存空间中指定的变量值。参数 shm_identifier 为欲除去的共享内存 ID 值。参数 variable_key 为欲删除的变量名称键。







PostgreSQL 7.2 Documentation
Chapter 3. 服务器运行时环境
共享内存和信号灯

共享内存和信号灯的正确叫法是System VIPC( 还有消息队列,不过对于PostgreSQL而言没什么 关系.)尽管所有现代操作系统都提供这个特性,但并不是 所有系统缺省都打开它或者有足够的资源,尤其是有 BSD 亲源 的系统. (对于QNXBeOS移植? PostgreSQL自己提供这套 机制的替换实现.)


完全缺少这些机制的表现通常是在 postmaster 启动的时候的 Illegal system call错误.这时除了重新配置内核以外 没什么可做的 — PostgreSQL 没它们干不了活.


如果 PostgreSQL 超出了这些IPC 资源的硬限制之一的时候 就会拒绝启动并且留下一条相当有启发性的错误信息告诉你它碰到了 什么问题以及需要为它做些什么. (又见 Section 3.3.1.) 相关的内核参数在不同系统之间有着相对固定的术语; Table 3-2 是一个概况.不过,设置它们的方法却 多种多样.不过要注意的是,你可能最好重新启动你的机器,或者还要 重新编译内核来修改这些设置.



Table 3-2. System V IPC参数
















































名字 描述 合理取值
SHMMAX 最大共享内存段尺寸(字节) 250kB + 8.2kB * shared_buffers + 14.2kB * max_connections 或者无穷大
SHMMIN 最小共享内存段尺寸(字节) 1
SHMALL 可用共享内存的总数量(字节或者页面) 如果是字节,就和 SHMMAX 一样;如果是页面,ceil(SHMMAX/PAGE_SIZE)
SHMSEG 每进程最大共享内存段数量 只需要 1 个段,不过缺省比这高得多.
SHMMNI 系统范围最大共享内存段数量 类似 SHMSEG 加上用于其他应用的空间
SEMMNI 信号灯标识符的最小数量(也就是说,套) >= ceil(max_connections % 16)
SEMMNS 系统范围的最大信号灯数量 ceil(max_connections / 16) * 17+ 用于其他应用的空间
SEMMSL 每套信号灯最小信号灯数量 >= 17
SEMMAP 信号灯映射里的记录数量 参阅文本
SEMVMX 信号灯的最大值 >= 255 (缺省通常是32767,除非被要求,否则不要修改)

最重要的共享内存参数是 SHMMAX, 以字节记的共享内存段可拥有的最大尺寸. 如果你收到来自shmget的一行Invalid argument 这样的错误信息,那么很有可能是你超过限制了. 要求的共享内存段随着请求的缓冲区数量(-B选项)和 允许的连接数量(-N选项)的变化而变化,尽管前者是 主要因素. (因此,作为一种临时的解决方法,你可以降低这些设置来绕过失败.) 如果粗略地估计,你可以估计所需要的段尺寸是缓冲区数量乘以块 尺寸(缺省 8 kB)加上足够的盈余(至少半兆字节). 任何错误信息都会包含分配失败的尺寸.


不太可能出问题的是共享内存段的最小尺寸(SHMMIN), 对 PostgreSQL来说最多是 256 kB左右(通常只是 1),而 系统范围(SHMMNI)或每进程(SHMSEG) 最大共享内存段数量不应该会产生问题,除非你的系统把它们设成零. 有些系统还对系统里的共享内存总量有限制;参阅下面平台相关的指导.


PostgreSQL 每个允许的联接使用一个信号灯 (-N选项), 以 16 个为一套.每套信号灯还包含第十七个信号灯, 它里面存储一个“magic number(标志数字)”, 以检测和其他应用使用的信号灯集冲突. 系统里的最大信号灯数目是由SEMMNS设置的, 因此这个值应该至少和联接设置一样大,并且每十六个联接还要另外加一个. (参阅Table 3-2 里面的公式.) 参数SEMMNI决定 系统里一次可以存在的信号灯集的数目.因此这个参数至少应该为 ceil(max_connections % 16).降低允许的联接数目是一个临时的 绕开失败的方法,这个启动失败通常被来自函数semget() 的错误响应 No space left on device搞得很让人迷惑.


有时候你还会发现有必要增大SEMMAP,使之至少按照 SEMMNS配置.这个参数定义信号灯资源映射的尺寸, 可用的每个连续的信号灯块在这个映射中存放一条记录. 每当一套信号灯被释放,那么它要么会加入到该映射中一条相连的 已释放的块的入口中,要么注册成一条新的入口.如果映射填满了碎片, 那么被释放的信号灯就丢失了(除非重起).因此时间长信号灯空间的碎片 了会导致可用的信号灯比应该有的信号灯少.


SEMMSL 参数,决定一套信号灯里可以有多少信号灯,对于 PostgreSQL而言应该至少是 17.


许多设置与 “semaphore undo(信号灯恢复)”有关,比如 SEMMNUSEMUME,这些与 PostgreSQL无关.







BSD/OS


共享内存. 缺省时是只支持 4MB 的共享内存.请记住共享内存是不能分页的;它是 锁在 RAM 里面的.要增加 postmaster 支持的共享缓冲区数目,向 你的内核配置文件里增加下面的行.一个值为 1024 的 SHMALL 代表 4M 共享内存.下面的东西把共享内存区域增加到 32 MB∶

options “SHMALL=8192″
options “SHMMAX=\(SHMALL*PAGE_SIZE\)”


对于运行 4.1 或更新的版本的人,只需要做上面的修改, 然后编译内核并重起.对于运行 更早的版本的,请用 bpatch 找出当前内核的 sysptsize值.它是启动的时候自动计算的.

$ bpatch -r sysptsize
0×9 = 9

然后,把 SYSPTSIZE修改为在内核配置文件里的一个硬代码值. 用 bpatch 算出来的值,并且为你需要的每个额外的 4 MB 共享内存再加 1.

options “SYSPTSIZE=16″

sysptsize不能用 sysctl 修改.



信号灯. 你可能需要增加信号灯的数量.缺省时,PostgreSQL 分配 34 个信号灯.这个数量只是刚刚超过缺省的系统总数 60 的一半.


在内核配置文件里设置你需要的值,比如:

options “SEMMNI=40″
options “SEMMNS=240″
options “SEMUME=40″
options “SEMMNU=120″


FreeBSD
NetBSD
OpenBSD

编译内核时 需要把选项SYSVSHMSYSVSEM打开. (缺省是打开的.) 共享内存的最大尺寸是由选项SHMMAXPGS(以页计). 下面显示了一个如何设置这些参数的例子:

options         SYSVSHM
options SHMMAXPGS=4096
options SHMSEG=256

options SYSVSEM
options SEMMNI=256
options SEMMNS=512
options SEMMNU=256
options SEMMAP=256


(在 NetBSDOpenBSD里,关键字实际上是单数的 option)


HP-UX

缺省设置看来对普通安装是足够的了. 在 HP-UX 10,SEMMNS的出厂缺省是 128, 可能对大的数据库节点来说太小了.


IPC可以在 System Administration Manager(系统管理器) (SAM)下面的 Kernel Configuration->Configurable Parameters 配置.你配置完了以后敲 Create A New Kernel选项.


Linux

在 2.2 内核里缺省的共享内存限制( SHMMAXSHMALL)都是 32 MB,但是你可以在 proc 文件系统里修改这些值(不用重起). 比如,要允许 128 MB:

$ echo 134217728 >/proc/sys/kernel/shmall
$ echo 134217728 >/proc/sys/kernel/shmmax

你可以把这些命令放到一个引导时运行的脚本中.


另外,如果你的系统里有的话,你可以使用 sysctl 来控制这些参数. 查找一个叫 /etc/sysctl.conf 的文件,然后再它里面加下面 这样的几行:

kernel.shmall = 134217728
kernel.shmmax = 134217728

通常在引导的时候会处理这个文件, 但你也可以稍后明确调用 sysctl


其他参数对任何应用来说都足够了. 如果你想自己查看,你可以看看下面几个文件: /usr/src/linux/include/asm-xxx/shmparam.h/usr/src/linux/include/linux/sem.h.


SCO OpenServer

缺省配置时,只允许每段 512KB 共享内存,大概只够 -B 24 -N 12用的.要增大设置,首先进入 /etc/conf/cf.d目录.要显示当前的以字节记的 SHMMAX,运行

./configure -y SHMMAX

设置 SHMMAX的新值:

./configure SHMMAX=value

这里 value 是你想设置的以字节记的新值. 设置完了以后SHMMAX重新制作内核

./link_unix

然后重起.


Solaris

至少到版本 2.6 为止,共享内存段的参数设置对PostgreSQL 来说是太低了.相关的设置可以在/etc/system里面修改, 例如:

set shmsys:shminfo_shmmax=0×2000000
set shmsys:shminfo_shmmin=1
set shmsys:shminfo_shmmni=256
set shmsys:shminfo_shmseg=256

set semsys:seminfo_semmap=256
set semsys:seminfo_semmni=512
set semsys:seminfo_semmns=512
set semsys:seminfo_semmsl=32


你要重起系统令修改生效.


又见 http://www.sunworld.com/swol-09-1997/swol-09-insidesolaris.html 获取关于 Solaris 里面的共享内存的信息.


UnixWare

UnixWare 7 上,缺省配置里的最大共享内存段是 512 kB. 这个数只够-B 24 -N 12用的.要显示SHMMAX的 当前值,运行

/etc/conf/bin/idtune -g SHMMAX

就会显示以字节记的当前的缺省的最小和最大值. 要给SHMMAX设置一个新值,运行:

/etc/conf/bin/idtune SHMMAX value

这里 value是你想设置的以字节记的新值. 设置完SHMMAX后,重建内核

/etc/conf/bin/idbuild -B

然后重起.




3.5.2. 资源限制


Unix 类系统强制了许多资源限制,这些限制可能干扰你的 PostgreSQL 服务器的运行. 这里尤其重要是对每个用户的进程数目的限制,每个进程打开文件数目, 以及一个进程可用的内存. 这些限制中每个都有一个“硬”限制和一个“软” 限制. 软限制实际是管用的,但用户可以自己修改成最大为硬限制的数目. 而硬限制是只能由 root 用户修改的限制. 系统调用 setrlimit 负责设置这些参数. shell 的内建命令 ulimit(Bourne shells) 或limitcsh) 就是用于在命令行上控制资源限制的. 在 BSD 衍生的系统上,文件/etc/login.conf 控制在登录时对各种资源设置什么样的限制数值. 参阅 login.conf 获取细节. 相关的参数是 maxprocopenfiles,和 datasize. 比如:

default:\

:datasize-cur=256M:\
:maxproc-cur=256:\
:o penfiles-cur=256:\

-cur 是软限制,后面附加 -max 就可以设置硬限制.)


内核通常也有一些与其具体实现相关的系统范围的一些资源的限制.





  • Linux 上, /proc/sys/fs/file-max 决定内核可以支持的 最大文件数.你可以通过往该文件写入一个不同的数值修改此值, 或者在 /etc/sysctl.conf 里增加一个赋值. 每个进程的最大打开文件限制是在编译内核的时候固定的; 参阅 /usr/src/linux/Documentation/proc.txt 获取更多信息.



PostgreSQL 服务器每个联接都使用一个进程, 所以你应该至少允许和联接数相同的进程数,再加上你的系统其它部分 所需要的数目.通常这个并不是什么问题,但如果你在一台机器上 运行多个服务器,那你就要把事情理清楚.


打开文件数目的出厂缺省设置通常设置为 “社会友好”数值,就是说允许许多用户共存于一台机器, 而不会导致只使用系统资源的不当比例.如果你在一台机器上运行许多 服务器,这也许就是你想要的,但是在特殊的服务器上,你可能需要提高 这个限制.


问题的另外一边,一些系统允许独立的进程打开非常多的文件; 如果有那么几个进程这么干,那系统范围的上限就很容易达到. 如果你发现这样的现象,并且不想修改系统范围的限止, 你就可以把 PostgreSQLmax_files_per_process 配置参数设置为你允许的 最大单进程打开文件数.