Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1020938
  • 博文数量: 326
  • 博客积分: 10135
  • 博客等级: 上将
  • 技术积分: 2490
  • 用 户 组: 普通用户
  • 注册时间: 2006-04-22 23:53
文章分类

全部博文(326)

文章存档

2014年(1)

2012年(4)

2011年(1)

2010年(4)

2009年(41)

2008年(44)

2007年(63)

2006年(168)

我的朋友

分类: LINUX

2006-05-24 17:12:23

第一次在Debian下装XFree86,startx启动了twm,装了gnome 后startx启动了gnome环境,为什么?装gnome 时修 改了什么文件以及X环境是怎么起来的?本来是想搞清这几个文题开始研究这个题目的,没想到还学到了很多别的东西^_^本文主要说明 X Window System的基本运行原理,其启动过程,及常见的跨网络运行X Window System。 

一) 基本运行原理 
X Window System 采用C/S结构,但和我们常见的C/S不同。常见的C/S结构中,称提供服务的一方为server,即服务器端(如HTTP服务,FTP服务等),使用服 务的称为client,即客户端。但在X Window System中,client是执行程序的一方,在上面执行各种X程序,而server则是负责 显示client运行程序的窗口的一方。 
X Window System的组成可以分为X server,X client, X protocol三部分。X server主要控制输入输出,维护字体,颜色等相关资源。它接受输入设备的输入信息并传递给X client, X client将这些信息处理后所返回的信息,也由X server负责输出到输出设备(即我们所见的显示器)上。X server传递给 X client的信息称为Event,主要是键盘鼠标输入和窗口状态的信息。X client传递给X server的信息则称为Request,主要 是要求X server建立窗口,更改窗口大小位置或在窗口上绘图输出文字等。X client主要是完成应用程序计算处理的部分,并不接受用户的输入信 息,输入信息都是输入给X server,然后由X server以Event的形式传递给X client(这里感觉类似Windows的消息机制,系 统接收到用户的输入信息,然后以消息的形式传递给窗口,再由窗口的消息处理过程处理)。X client对收到的Event进行相应的处理后,如果需要输 出到屏幕上或更改画面的外观等,则发出Request给X server,由X server负责显示。 
常见的情况是X server与 X client都在同一台电脑上运行,但他们也可分别位于网络上不同的电脑上。在X Window System中,X client是与硬件无关的, 它并不关心你使用的是什么显卡什么显示器什么键盘鼠标,这些只与X server相关。我们平常安装完XFree86后运行xf86config或 xf86cfg进行的配置实际上只是与X server有关,可以说就是配置X server吧,不配置照样可以运行X client程序(如: xeyes -display xserver:0就可以在xserver这台机器上的0号屏幕(屏幕编号displaynumber为0)上显示那对大 眼睛了)。 
X protocol就是X server于X client之间通信的协议了。X protocol支持现在常用的网络通信协 议。我只能测试TCP/IP,可以看到X server侦听在tcp 6000端口上。那X protocol就是位于运输层以上了,应该属于应用层 吧?。 
总结下运行过程吧: 
(1) 用户通过鼠标键盘对X server下达操作命令 
(2) X server利用Event传递用户操作信息给X client 
(3) X client进行程序运算 
(4) X client利用Request传回所要显示的结果 
(5) X server将结果显示在屏幕上 

二) 启动过程 
我们从控制台进入X一般是用startx命令。下面就从startx分析起。首先man startx和man xinit可以看到staratx和xinit的使用方法: 
startx [[client] options .....] [-- [server] options ....] 
xinit [[client] options ] [-- [server] [display] options] 
把上面[client]和[server]分别称为client程序和server程序。man手册里写明其必须以/或者./开头。 
下面看看startx这个脚本,中文为我加的注释,这个脚本是安装x-window-system-core后得到的,都是XFree86,不同发行版的linux里该脚本应该大同小异: 
#!/bin/sh 
userclientrc=$HOME/.xinitrc #用户的client定义文件 
userserverrc=$HOME/.xserverrc #用户的server定义文件
sysclientrc=/usr/X11R6/lib/X11/xinit/xinitrc #系统的client 
sysserverrc=/usr/X11R6/lib/X11/xinit/xserverrc #系统的server 
defaultclient=/usr/X11R6/bin/xterm #默认的client程序 
defaultserver=/usr/X11R6/bin/X #默认的server程序 
defaultclientargs="" #下面定义了client和server的参数变量 
defaultserverargs="" 
clientargs="" 
serverargs="" 
#如果用户client文件存在则使用用户文件里定义的client,否则使用系统定义的client 
if [ -f $userclientrc ]; then 
defaultclientargs=$userclientrc 
elif [ -f $sysclientrc ]; then 
defaultclientargs=$sysclientrc 
fi 
#如果用户server文件存在则使用用户文件里定义的server,否则使用系统定义的server 
if [ -f $userserverrc ]; then 
defaultserverargs=$userserverrc 
elif [ -f $sysserverrc ]; then 
defaultserverargs=$sysserverrc 
fi 
#下面循环处理client和server的参数 
whoseargs="client" 
while [ x"$1" != x ]; do #若第一个参数为空,退出循环 
case "$1" in 
# ’’ required to prevent cpp from treating "/*" as a C comment. 
/’’*|./’’*) #如果$1是/*或者./*形式(xinit程序要求其参数里的client程序和server程序必须以/或./开头,否则会被视为client程序和server程序的参数,见man xinit) 
if [ "$whoseargs" = "client" ]; then #如果当前是在处理client的参数 
if [ x"$clientargs" = x ]; then #如果 clientargs为空,则赋值$1给client变量,也即上面#startx使用方法里的[client]参数 
client="$1" 
else 
clientargs="$clientargs $1" #否则clientargs赋值为$clientargs $1,即上面#startx使用#方法里的options参数 
fi 
else #当前在处理server的参数,代码的含义同上 
if [ x"$serverargs" = x ]; then 
server="$1" 
else 
serverargs="$serverargs $1" 
fi 
fi 
;; 
--)#如果$1为--,则表示开始处理server的参数,--为client和server参数的分界 
whoseargs="server" 
;; 
*) 
if [ "$whoseargs" = "client" ]; then #处理给client程序的参数 
clientargs="$clientargs $1" 
else #处理给server程序的参数 
# display must be the FIRST server argument 
#屏幕编号必须为第一个给server程序的参数,以:x的形式(x为数字),这可从上面startx和xinit 
的使用方法的区别看出,xinit多了个[display],这里即过滤出这个[display]。试试看这两个命令: 
xinit /usr/bin/X11/xeyes -display localhost:1 -- /usr/bin/X11/X :1 -dpi 70& 
xinit /usr/bin/X11/xeyes -display localhost:1 -- /usr/bin/X11/X -dpi 70 :1& 
即可看出不把屏幕编号作为第一个server参数的后果 
if [ x"$serverargs" = x ] && expr "$1" : ’:[0-9][0-9]*$’ > /dev/null 2>&1; then
display="$1" 
else #处理屏幕编号以外的参数 
serverargs="$serverargs $1" 
fi 
fi 
;; 
esac 
shift #所有参数左移一次 
done 
# process client arguments 
if [ x"$client" = x ]; then #如果client程序为空 
# if no client arguments either, use rc file instead 
if [ x"$clientargs" = x ]; then #且clientargs为空,赋值$defaultclientargs给client程序 
client="$defaultclientargs" 
else 
client=$defaultclient #使用默认的client程序 
fi 
fi 
# process server arguments处理server参数,同上 
if [ x"$server" = x ]; then 
# if no server arguments or display either, use rc file instead 
if [ x"$serverargs" = x -a x"$display" = x ]; then 
server="$defaultserverargs" 
else 
server=$defaultserver 
fi 
fi 
#…………省略授权代码若干 

xinit $client $clientargs -- $server $display $serverargs #把处理过的参数交由xinit程序处理 
#………… 
由 上面代码可以得出startx主要是置X client和X server所在的位置,并处理相关参数,最后交给xinit处理。可以看出startx  设置X client的位置是先搜寻$HOME/.xinitrc,然后是/etc/X11/xinit/xinitrc;设置X server的位置是 先搜寻$HOME/.xserverrc,然后是/etc/X11/xinit/xserverrc。这就解释了我们平常为什么说启动X Window时 用户目录下的.xinitrc和.xserverrc文件优先级要高。所以我们用startx命令启动X时,如果用户目录存在.xinitrc和. xserverrc文件,则实际上等价于命令xinit $HOME/.xinitrc -- $HOME/.xserverrc 。如果用户目录不存在 那两个文件,则等价于xinit /usr/X11R6/lib/X11/xinit/xinitrc --  /usr/X11R6/lib/X11/xinit/xserver。别的情况类推。 
至于xinit,则根据startx传过来的参数启动X server,成功后根据xinitrc启动X client。 
以 上即为X Window System的启动过程,startx只是负责一些参数传递,真正的X启动由xinit实现。实际上可以分为启动 X server和启动X client两部分。下面在用户目录下构造.xinitrc(即X client)和.xserverrc(即 X server)文件。在.xserverrc里写入/usr/bin/X11/X :1。.xinitrc里写入 /usr/bin/X11/xeyes -display localhost:1。这就是最简单的X server+ X client了,只不过把屏 幕编号从默认的0改为了1,这里X server即是/usr/bin/X11/X 程序,X client即是/usr/bin/X11/xeyes  程序。 
总结下单机用startx启动过程吧: 
(1) startx置X client和X server的位置,处理参数并调用xinit 
(2) xinit根据传过来的参数启动X server,成功后呼叫X client 
(3) 根据xinitrc设置相关资源,启动窗口管理器,输入法和其他应用程序等X client程序。 

但还未搞清楚gnome是怎么起来的!gnome当然属于X client了,看上面启动过程第(3)步。 
这 里分两种情况看吧,第一种是用系统的xinitrc文件。看/etc/X11/xinit/xinitrc文件(我的sarge装x-window- system-core和gnome-core),里面只包含了. /etc/X11/Xsession一句话。接着看 /etc/X11/Xsession这个脚本,只看关键部分吧。最后面有.
SESSIONFILES=$(run_parts $SYSSESSIONDIR) 
if [ -n "$SESSIONFILES" ]; then 
for SESSIONFILE in $SESSIONFILES; do 
. $SESSIONFILE 
done 
fi 
exit 0 
接着看run_parts(),位于本文件中间: 
run_parts () { 
# until run-parts --noexec is implemented 
if [ -z "$1" ]; then 
internal_errormsg "run_parts() called without an argument." 
fi 
if [ ! -d "$1" ]; then 
internal_errormsg "run_parts() called, but "$1" does not exist or is" 
"not a directory." 
fi 
for F in $(ls $1); do 
if expr "$F" : ’[[:alnum:]_-]+$’ > /dev/null 2>&1; then 
if [ -f "$1/$F" ]; then 
echo "$1/$F" 
fi 
fi 
done 

大 概意思就是run_parts () 把$SYSSESSIONDIR目录下的文件名取出来赋值给$SESSIONFILES,然后循环运行该目录下的文 件。看看该目录,即/etc/X11/Xsession.d目录,可以看到几个以数字开头的文件,实际上这些数值就表示了这几个文件被运行的优先级,数字 小的优先级高,因为在上面的run_parts () 里是用ls命令显示该目录下的文件,所以前面数字小的被ls时显示在前面,所以被 
for SESSIONFILE in $SESSIONFILES; do 
. $SESSIONFILE 
done 
这个for循环执行时也先被执行。看到/etc/X11/Xsession.d目录下有个55gnome-session_gnomerc文件,里面提到了STARTUP变量。然后运行: 
xdkui@Debian:/etc/X11/Xsession.d$ grep STARTUP * 
看到50xfree86-common_determine-startup文件。里面有 
if [ -z "$STARTUP" ]; then 
if [ -x /usr/bin/x-session-manager ]; then 
STARTUP=x-session-manager 
elif [ -x /usr/bin/x-window-manager ]; then 
STARTUP=x-window-manager 
elif [ -x /usr/bin/x-terminal-emulator ]; then 
STARTUP=x-terminal-emulator 
fi 
fi 
即设置启动程序,实际上设置STARTUP变量,如果以上程序都没有找到,则会报错退出,即X环境没有被启动。再运行 
xdkui@Debian:/etc/X11/Xsession.d$ grep STARTUP * 
看到优先级最低也即最后被运行的99xfree86-common_start文件,里面只有一句话: 
exec $STARTUP 
好了,到这里就启动我们的X client了,终于完了^_^?
阅读(619) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~