• X Window System介绍


        1、概述
        X Window System是1984年由麻省理工学院(MIT)和DEC公司共同开发研究的,是执行在UNIX系统上的视窗系统。严格地说,X Window System并非一个软件,而是一个协议,这个协议定义一个系统成品所必需具备的功能(就如同TCP/IP、DECnet或IBM的SNA,这些也都是协议,定义软件所应具备的功能)。能满足此协议及符合X协会其它规范的系统便可称为X。X Window System独有的网络通透性(Network Transparency),使其成为UNIX平台上的工业标准,如今UNIX的工作站或大型主机差点儿都执行着X Window。X Window是非常巧妙的设计,非常多时候它在概念上比其他窗体系统先进,以至于经过非常多年它仍然是工作站上的工业标准。很多其他窗体系统的概念都是从X Window学来的。
        X Window System本身是一个很复杂的图形化作业环境,我们能够将它分成3个部分,各自是X Server、X Client和X Protocol。X Server主要是处理输入输出的信息,X Client运行大部分应用程序的运算功能,X Protocol则是建立X Server和X Client的沟通管道。
        (1)X Server
        X Server主要负责处理输入输出的信息,而且维护字体、颜色等相关资源。它接收输入设备(如键盘、鼠标)的信息,将这些信息交给X Client处理,而X Client所传来的信息就由X Server负责输出到输出设备(如显示卡、荧幕)上。X Server传给X Client的信息称作Events(事件)。X Client传给X Server的信息称作Request(要求)。Events(事件)主要包含键盘的输入和鼠标的移动、按下等动作,而Request(要求)主要是X Client要求对显示卡及屏幕的输出作调整。
        (2)X Client
        X Client主要负责应用程序的运算处理部分,它将X Server所传来的Events作运算处理后,再将结果以Request的方式去要求X Server显示在屏幕上的图形视窗。在X Window System的结构中,X Server和X Client所负责的部分是分开的,所以X Client和硬件无关,仅仅和程序运算有关。这样有一个优点,比如更换显示卡时,X Client部分不须要又一次编写;由于X Server和X Client是分开的,所以能够将两者分别安装在不同电脑上,这样就能够利用本地端的屏幕、键盘和鼠标来操作远端的X Client程序。常见的X Client有大家熟悉的gdm, xterm, xeyes等。
        (3)X Protocol
        X Protocol就是X server与X client之间通信的协议。X protocol支持如今经常使用的网络通信协议。比如測试TCP/IP,能够看到X server侦听在tcp 6000port上。那X protocol就是位于传输层以上了,应该属于应用层。通常,X server和X client在两台机器上时,则之间一般使用TCP/IP协议通信,若在同一台机器,则使用高效的操作系统内部通信协议。
        (4)X Library、X Toolkit和Widget
        X Client主要就应用程序,而开发程序大多会提供函数库,以方便开发人员开发,在X则提供有X Library(X Lib),X Library主要提供X Protocol的存取能力,因为X Server仅仅是依据X Client所给的Request(要求)去显示画面,因此全部的图形使用界面都交由X Client负责。我们没有必要每写一个应用程序都得从头再开发一个界面,所以有了图形界面库X Toolkit和Widget的产生,开发人员就能够使用Toolkit和Widget来创建button、对话框、轴、窗体等视窗结构,这样开发人员能够easy地开发各种程序。
        总结下执行过程:
        (1)用户通过鼠标键盘对X server下达操作命令
        (2)X server利用Event传递用户操作信息给X client
        (3)X client进行程序运算
        (4)X client利用Request传回所要显示的结果
        (5)X server将结果显示在屏幕上
        能够看出,X Window的工作方式跟Microsoft Windows有着本质的不同。Microsoft Windows的图形用户界面(GUI)是跟系统紧密相联的。而X Window则不是,它实际上是在系统核心(kernel)的上面执行的一个应用程序。
        X Window的执行分为4层。最底层的是X Server(server),提供图形界面的驱动,为X Window提供服务。上面的一层是用于网络通信的网络协议,即X网络协议,这部分使远程执行X Window成为可能。仅仅须要在server上执行一个X Server,而客户机(Client)上执行更上一层的程序,则能够实现X Window的远程执行。再往上的一层是称作Xlib的函数接口,介于基础系统和较高层应用程序之间。应用程序的实现是通过调用这一层的函数实现的。最顶层就是窗体管理器了,也就是一般所说的WM(Window Manager),这一层的软件是用户常常接触的,比方fvwm、AfterStep、Enlightment以及WindowMaker等。
        从上面的介绍来看,X Window的执行是一种客户机/server(Client/Server)的模式,server用于显示客户机执行的应用程序,又被称为显示server (Display Server)。显示server位于硬件和客户机之间,它跟踪全部来自输入设备(比方键盘、鼠标)的输入动作,经过处理后将其送回客户机。这样,用户能够在 Microsoft Windows的机器上执行X Client,截取并传送用户的输入,仅仅是将X Window的屏幕输出显示在用户的屏幕上。客户机的输入和输出系统跟Xserver之间的通信都是遵守X协议的。
        搞清楚X server与X client关系非常重要。一般X server非常easy,就是/usr/bin/X11/X程序或Xorg程序,在Microsoft Windows上经常使用的X server有Xming,Xmanager,Exceed和X-win32等。而X client则花样繁多,从高级的CDE,GNOME,KDE,到低级一点的仅仅有twm,Window Maker,blackbox等窗体管理器,再到最简陋的仅仅有xterm,rxvt,xeyes等单个x程序。正是因为X client的各种搭配,使得我们的X Window System看起来多样化。
        注意,X中所提及的“client”和“server”等字眼用词与人们一般想定的相反,“server”反而是在用户本地端的自有机器上执行,而非是在远程的还有一部机器上执行。非常多熟悉Internet原理的人首次遇到X Window的这两个概念都会搞错。假设他从一台Windows机器上使用Exceed通过XDMCP登录到一台Sunserver,他就说Exceed是client(client),而Sun机器是server(server)。这就全然搞错了。X server不是指你登录的那台机器,而是指一个程序,它负责在某台机器上接受客户的要求,在屏幕上显示客户请求的图形,而且把消息(键盘,鼠标,窗体消息)通知客户程序。这个样例里本地的Exceed就是一个X server,它负责控制这台Windows机器上的显示(display),远程Sun机器上的程序xterm, xxgdb, dtwm(CDE的窗体管理器)等,是客户程序。它们一般会使用TCP 6000号port连接Windows机器,而Windows机器的6000号port是由Exceed来bind和listen的。比方,当你通过telnet启动Sun机器上的xterm,就会 Exceed的屏幕上显示一个窗体。实际发生的事情是: xterm请求连接Windows机器的6000号port,跟Exceed连接,然后xterm请求得到资源,然后xterm请求在屏幕上显示一个窗体。你在xterm的窗体里按下"A"键时,Exceed会把这个事件通知xterm进程,然后xterm会发送数据报,请求Exceed, “请在坐标(100,30)处显示一个字母A,然后在后面显示一个矩形作为光标。”这样你的xterm窗体里就会多显示一个字母。
        实际的远端client的样例有:图形化管理远程计算机;在远端UNIX计算机上执行计算密集的仿真程序并把结果显示到本地的Windows桌面计算机;用一套显示器、键盘和鼠标控制同一时候执行在多台计算机上的图形化软件。
        2、X Window System的启动过程
        从控制台(即字符界面)进入X通常是用startx命令。在前面“Linux init程序分析“中介绍过startx(以Fedora为例),这里以Ubuntu为例。startx是用xinit程序来启动X的。首先man startx和man xinit能够看到staratx和xinit的用法:
        startx [ [client] options .....] [-- [server] [display] options ....]
        xinit [ [client] options ] [-- [server] [display] options ...]
        把上面[client]和[server]分别称为X client程序和X server程序。man手冊里写明其必须以/或者./开头,即必须是绝对路径或从当前路径開始。

        以下看看/usr/bin/startx这个脚本。

    #!/bin/bash
    
    #
    # This is just a sample implementation of a slightly less primitive
    # interface than xinit.  It looks for user .xinitrc and .xserverrc
    # files, then system xinitrc and xserverrc files, else lets xinit choose
    # its default.  The system xinitrc should probably do things like check
    # for .Xresources files and merge them in, startup up a window manager,
    # and pop a clock and serveral xterms.
    #
    # Site administrators are STRONGLY urged to write nicer versions.
    #
    
    unset DBUS_SESSION_BUS_ADDRESS
    unset SESSION_MANAGER
     
    userclientrc=$HOME/.xinitrc                  # 用户的client定义文件
    sysclientrc=/etc/X11/xinit/xinitrc           # 系统的client定义文件
    
    userserverrc=$HOME/.xserverrc                # 用户的server定义文件
    sysserverrc=/etc/X11/xinit/xserverrc         # 系统的server定义文件
    defaultclient=xterm                          # 默认的client程序 
    defaultserver=/usr/bin/X                     # 默认的server程序 
    defaultclientargs=""                         # 以下定义了client和server的參数变量
    defaultserverargs=""
    defaultdisplay=":0"
    clientargs=""
    serverargs=""
    
    enable_xauth=1
    
    # 參数解析:将whoseargs变量赋值为字符串“client”,表示当前解析的指定client的參数
    whoseargs="client"
    while [ x"$1" != x ]; do                     # 若第一个參数为空,则直接退出循环
        case "$1" in
        # 须要单引號''以避免cpp把"/*"当作凝视
        /''*|./''*)            # 假设$1是/*或者./*形式 (xinit程序要求其指定的client程序和server程序必须以/或./开头,
                                # 否则会被视为client程序和server程序本身的options參数,见man xinit) 
    		if [ "$whoseargs" = "client" ]; then       # 解析client程序的參数
    	  		if [ x"$client" = x ] && [ x"$clientargs" = x ]; then
    				client="$1"              # 解析出用户指定的client程序
    	  		else
    				clientargs="$clientargs $1"   #解析出client程序的options參数
    	  	  	fi
    		else
    	    	if [ x"$server" = x ] && [ x"$serverargs" = x ]; then
    				server="$1"                  # 解析出用户指定的X server程序
    	    	else
    				serverargs="$serverargs $1"  # 解析出X server的options參数
    	    	fi
    		fi
    		;;
        --)                       # 遇到“- -”就解析server
    		whoseargs="server"
    		;;
        *)
    		if [ "$whoseargs" = "client" ]; then
    	  		clientargs="$clientargs $1"
    		else
    	 	    # 解析[display]參数,屏幕编号[display]必须为第一个给server程序的參数,以:x的形式(x为数字)
    	   		if [ x"$serverargs" = x ] && 
    		 		expr "$1" : ':[0-9][0-9]*> /dev/null 2>&1; then
    				display="$1"
    	   		else
    				serverargs="$serverargs $1"   # 解析[display]以外的參数
    	    	fi
    		fi
    		;;
        esac
        shift         # 全部參数左移一次
    done
    
    # 处理client參数
    if [ x"$client" = x ]; then    # 假设用户没有指定X client,则使用默认的X client即xterm
        client=$defaultclient
    
        # 假设没有client的选项參数,则用rc文件取代
        if [ x"$clientargs" = x ]; then
            if [ -f "$userclientrc" ]; then
                client=$userclientrc
            elif [ -f "$sysclientrc" ]; then
                client=$sysclientrc
            fi
    
            clientargs=$defaultclientargs
        fi
    fi
    
    # 处理server參数
    if [ x"$server" = x ]; then     # 假设用户没有指定X server,则使用默认的X server即X
        server=$defaultserver
    
        # 假设没有server的选项參数或display參数,使用默认值
        if [ x"$serverargs" = x -a x"$display" = x ]; then
    	# 为了兼容性的考虑,假设没有server的命令行參数,仅仅使用xserverrc文件
    	if [ -f "$userserverrc" ]; then
    	    server=$userserverrc
    	elif [ -f "$sysserverrc" ]; then
    	    server=$sysserverrc
    	fi
    
    	serverargs=$defaultserverargs
    	display=$defaultdisplay
        fi
    fi
    
    if [ x"$enable_xauth" = x1 ] ; then
        if [ x"$XAUTHORITY" = x ]; then       # 假设环境变量XAUTHORITY为空,就设定为$HOME/.Xauthority
            XAUTHORITY=$HOME/.Xauthority
            export XAUTHORITY
        fi
    
        removelist=
    
        # 设置本机的默认Xauth信息
    
        # 检查GNU主机名,假设hostname –version中不包括GNU 就将hostname变量设定为命令hostname –f返回的字符串
        if hostname --version > /dev/null 2>&1; then
            if [ -z "`hostname --version 2>&1 | grep GNU`" ]; then
                hostname=`hostname -f`
            fi
        fi
    
        if [ -z "$hostname" ]; then
            hostname=`hostname`
        fi
    
        authdisplay=${display:-:0}
    
        mcookie=`/usr/bin/mcookie`
    
        if test x"$mcookie" = x; then
            echo "Couldn't create cookie"
            exit 1
        fi
        dummy=0
    
        # 为server创建带有auth信息的文件,假设为屏幕编号为':0'
        xserverauthfile=`mktemp --tmpdir serverauth.XXXXXXXXXX`
        trap "rm -f '$xserverauthfile'" HUP INT QUIT ILL TRAP KILL BUS TERM
        xauth -q -f "$xserverauthfile" << EOF
    add :$dummy . $mcookie
    EOF
    
        serverargs=${serverargs}" -auth "${xserverauthfile}
    
    
        # now add the same credentials to the client authority file
        # if '$displayname' already exists do not overwrite it as another
        # server man need it. Add them to the '$xserverauthfile' instead.
        for displayname in $authdisplay $hostname$authdisplay; do
            authcookie=`xauth list "$displayname" 
            | sed -n "s/.*$displayname[[:space:]*].*[[:space:]*]//p"` 2>/dev/null;
            if [ "z${authcookie}" = "z" ] ; then
                xauth -q << EOF 
    add $displayname . $mcookie
    EOF
            removelist="$displayname $removelist"
            else
                dummy=$(($dummy+1));
                xauth -q -f "$xserverauthfile" << EOF
    add :$dummy . $authcookie
    EOF
            fi
        done
    fi
    
    # #以下的语句通过xinit启动X server和Clients,把处理的參数传给它
    xinit "$client" $clientargs -- "$server" $display $serverargs
    
    retval=$?
    if [ x"$enable_xauth" = x1 ] ; then
        if [ x"$removelist" != x ]; then
            xauth remove $removelist
        fi
        if [ x"$xserverauthfile" != x ]; then
            rm -f "$xserverauthfile"
        fi
    fi
    
    exit $retval
    

        以上即为X Window System的启动过程,startx仅仅是负责一些參数传递,真正的X启动由xinit实现。我们能够知道,startx将会先解析用户的參数,假设该用户指定了该參数(即解析结果不为空),那么startx就会以该參数来启动xinit,否则就会解析(与其说是解析,还不如说是运行)$HOME文件夹下的rc文件,假设该文件不存在,就会解析系统文件夹下(/etc/X11/xinit/)的rc文件,假设这个文件也不存在,那startx就将以默认的client(xterm)和server(/usr/bin/X)为參数来启动xinit。比如,能够在用户文件夹下构造.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。
        到眼下为止,我们还不知道只在终端输入startx是怎么样启动gnome桌面的,gnome当然属于X client了。通过对startx的分析可知,startx主要有三种启动方式:
        (1)一种是自己指定要启动的client和server, 比如:startx /usr/bin/xclock -- /usr/bin/X :0;
        (2)一种是通过在$HOME下新建.xinitrc文件来指定要启动的多个client和.xserverrc来指定要启动的server(注意:这两个文件本来是不存在的);
        (3)另一种是直接输入startx而不指定參数,这也就是我们启动gnome桌面的方法。
        在第(3)中启动方法中,我们能够知道,startx脚本会先去看系统文件夹(/etc/X11/xinit/)下的rc文件是否存在,假设不存在就会用默认的xterm和/usr/bin/X来启动xinit。显然,startx启动的不是xterm,而是gnome桌面,因此gnome的启动是通过系统文件/etc/X11/xinit/xinitrc来指定的。在“Linux init程序分析”中具体介绍过的gnome的启动。这里以Ubuntu为例,/etc/X11/xinit/xinitrc文件里仅仅包括了. /etc/X11/Xsession一句话,因此gnome是通过Xsession脚本启动的(在Fedora中则是直接用xinitrc来启动gnome)。以下是Xsession文件:

    #!/bin/sh      # 注意该脚本用的是Bourne shell解析的
    #
    # /etc/X11/Xsession
    #
    # global Xsession file -- used by display managers and xinit (startx)
    
    # $Id: Xsession 967 2005-12-27 07:20:55Z dnusinow $
    
    set -e         # 打开errexit选项,该选项表示假设以下有命令返回的状态非0,则退出程序
    
    PROGNAME=Xsession
    
    # 以下4个是信息输出函数,能够无论
    message () {
      # pretty-print messages of arbitrary length; use xmessage if it
      # is available and $DISPLAY is set
      MESSAGE="$PROGNAME: $*"
      echo "$MESSAGE" | fold -s -w ${COLUMNS:-80} >&2
      if [ -n "$DISPLAY" ] && which xmessage > /dev/null 2>&1; then
        echo "$MESSAGE" | fold -s -w ${COLUMNS:-80} | xmessage -center -file -
      fi
    }
    
    message_nonl () {
      # pretty-print messages of arbitrary length (no trailing newline); use
      # xmessage if it is available and $DISPLAY is set
      MESSAGE="$PROGNAME: $*"
      echo -n "$MESSAGE" | fold -s -w ${COLUMNS:-80} >&2;
      if [ -n "$DISPLAY" ] && which xmessage > /dev/null 2>&1; then
        echo -n "$MESSAGE" | fold -s -w ${COLUMNS:-80} | xmessage -center -file -
      fi
    }
    
    errormsg () {
      # exit script with error
      message "$*"
      exit 1
    }
    
    internal_errormsg () {
      # exit script with error; essentially a "THIS SHOULD NEVER HAPPEN" message
      # One big call to message() for the sake of xmessage; if we had two then
      # the user would have dismissed the error we want reported before seeing the
      # request to report it.
      errormsg "$*" 
               "Please report the installed version of the "x11-common"" 
               "package and the complete text of this error message to" 
               "<debian-x@lists.debian.org>."
    }
    
    # 初始化被全部session脚本使用的变量
    
    OPTIONFILE=/etc/X11/Xsession.options
    
    SYSRESOURCES=/etc/X11/Xresources
    USRRESOURCES=$HOME/.Xresources
    
    SYSSESSIONDIR=/etc/X11/Xsession.d
    USERXSESSION=$HOME/.xsession
    USERXSESSIONRC=$HOME/.xsessionrc
    ALTUSERXSESSION=$HOME/.Xsession
    ERRFILE=$HOME/.xsession-errors
    
    # 尝试创建一个error文件,假设不能创建则退出
    if (umask 077 && touch "$ERRFILE") 2> /dev/null && [ -w "$ERRFILE" ] &&
      [ ! -L "$ERRFILE" ]; then
      chmod 600 "$ERRFILE"
    elif ERRFILE=$(tempfile 2> /dev/null); then
      if ! ln -sf "$ERRFILE" "${TMPDIR:=/tmp}/xsession-$USER"; then
        message "warning: unable to symlink "$TMPDIR/xsession-$USER" to" 
                 ""$ERRFILE"; look for session log/errors in" 
                 ""$TMPDIR/xsession-$USER"."
      fi
    else
      errormsg "unable to create X session log/error file; aborting."
    fi
    
    # 截短ERRFILE,假设它太大了,以避免硬盘空间的DoS攻击
    if [ "`stat -c%s "$ERRFILE"`" -gt 500000 ]; then
      T=`mktemp -p "$HOME"`
      tail -c 500000 "$ERRFILE" > "$T" && mv -f "$T" "$ERRFILE" || rm -f "$T"
    fi
    
    exec >>"$ERRFILE" 2>&1
    
    echo "$PROGNAME: X session started for $LOGNAME at $(date)"
    
    # 理智的检查:#假设/etc/X11/Xsession.d不存在或不是一个文件夹则打印错误信息并退出
    if [ ! -d "$SYSSESSIONDIR" ]; then
      errormsg "no "$SYSSESSIONDIR" directory found; aborting."
    fi
    
    # Attempt to create a file of non-zero length in /tmp; a full filesystem can
    # cause mysterious X session failures.  We do not use touch, :, or test -w
    # because they won't actually create a file with contents.  We also let standard
    # error from tempfile and echo go to the error file to aid the user in
    # determining what went wrong.
    WRITE_TEST=$(tempfile)
    if ! echo "*" >>"$WRITE_TEST"; then
      message "warning: unable to write to ${WRITE_TEST%/*}; X session may exit" 
              "with an error"
    fi
    rm -f "$WRITE_TEST"
    
    # use run-parts to source every file in the session directory; we source
    # instead of executing so that the variables and functions defined above
    # are available to the scripts, and so that they can pass variables to each
    # other
    SESSIONFILES=$(run-parts --list $SYSSESSIONDIR)   # 将/etc/X11/Xsession.d文件夹中的全部文件都读出,并存入SESSIONFILES变量中
    if [ -n "$SESSIONFILES" ]; then
      set +e       # 关闭errexit选项
      for SESSIONFILE in $SESSIONFILES; do        # 运行Xsession.d下的每个脚本
        . $SESSIONFILE
      done
      set -e
    fi
    
    exit 0
    
    # vim:set ai et sts=2 sw=2 tw=80:
         从以上的对Xsession脚本文件的分析,能够看出,Xsession脚本不过运行了/etc/X11/Xsession.d文件夹下的全部文件,每个文件名称都以数字开头,这些数字就表示了文件被运行的优先级,数字小的优先级高,run-parts会将数字小的排在前面,这样就能确保以上文件能按数字由小到大的顺序运行。基本的文件例如以下:
        (1)20x11-common_process-args:这个文件主要是处理传给/etc/X11/xinit/ xinitrc脚本文件的參数的。该參数个数仅仅能为0或一个,否则将不进行不论什么处理。假设该參数是failsafe,则该脚本将运行x-terminal-emulator,否则就运行该參数。须要说明的是,x-terminal-emulator是一个符号链接,指向/etc/alternatives/x-terminal-emulator,同一时候,/etc/alternatives/x-terminal-emulator也是一个符号链接,它指向/usr/bin/gnome-terminal.wrapper,而gnome-terminal.wrapper则是一个perl脚本,它终于是调用了gnome-terminal。
        (2)30x11-common_xresources:该文件主要是调用xrdb,依据/etc/X11/Xresources文件夹下及$HOME/.Xresources文件夹下的文件的内容来设置根窗体的屏幕0上的RESOURCE_MANAGER属性的内容。
        (3)40x11-common_xsessionrc:该文件主要是推断$HOME/.xsessionrc文件是否存在,假设存在则运行该脚本文件。
        (4)50x11-common_determine-startup:该文件主要先查看配置文件/etc/X11/Xsession.options中是否同意使用用户的xsession,假设/etc/X11/Xsession.options中存在allow-user-xsession字段,则查看用户指定的$HOME/.xsession是否存在并有运行权限,假设是,则将STARTUP变量设置为该文件,假设没有运行权限就将STARTUP变量设置为“sh 该xsession文件”。假设此时STARTUP变量仍然为空(即没有使用用户指定的.xsession脚本),则将其设置为/usr/bin下的x-session-manager,x-window-manager或x-terminal-emulator,它们都是指向/etc/alternatives/下对应程序的符号链接。注意这个STARTUP将会在后面的脚本中被启动。
        (5)55gnome-session_gnomerc:该文件会先得到STARTUP的basename,如STARTUP=/usr/bin/x-session-manager,则其basename为x-session-manager。再推断该basename是否为gnome-session,或者为x-session-manager而且x-session-manager是个符号链接,它指向/usr/bin/gnome-session,假设选择的是gnome-session,则运行$HOME/.gnomerc(假设该文件存在而且可读)。
        (6)60x11-common_localhost:使用xhost程序,把本机的username加入到同意连接X server的username列表中。username由`id -un`命令给出。
        (7)60xdg_path-on-session:依据选择的窗体会话,通过设置XDG_CONFIG_DIRS变量来加入额外的xdg路径。
        (8)60xdg-user-dirs-update:用xdg-user-dirs-update自己主动生成$HOME下的目录,该命令主要是依据/etc/xdg/user-dirs.defaults文件的内容来为用户创建目录的。
        (9)70gconfd_path-on-session:依据选择窗体会话,加入额外的gconf路径。
        (10)75dbus_dbus-launch:把use-session-dbus选择放入Xsession.options文件里,表示使用在窗体会话中使用dbus。把启动/usr/bin/dbus-launch程序的选择加入到STARTUP变量中。
        (11)80im-switch:该文件主要用于设置输入法。详细的请自己參考文件内容。
        (12)90consolekit:假设环境变量$XDG_SESSION_COOKIE为空,而且/usr/bin/ck-launch-session可运行,则将STARTUP又一次赋值为” /usr/bin/ck-launch-session $STARTUP”。至于ck-launch-session的功能,我也不是非常清楚,预计是和session有关,对窗体会话进行一些检查。
        (13)90x11-common_ssh-agent:该文件主要先查看配置文件/etc/X11/Xsession.options中是否使用ssh agent,假设/etc/X11/Xsession.options中存在use-ssh-agent字段,则推断/usr/bin/ssh-agent是否可运行,而且环境变量$SSH_AUTH_SOCK和$SSH2_AUTH_SOCK是否都为空,假设是,这将STARTUP又一次赋值为” /usr/bin/ssh-agent $STARTUP”。
        (14)99x11-common_start:它不过用exec启动$STARTUP。关于exec,在Bourne shell中,它与fork的差别就在于它运行一个新的脚本不需创建sub-shell,而它与Source和Dot的差别就在与在这条语句后面的语句将不会再被运行。此时,我们能够发现变量$STARTUP的值为:“startup=/usr/bin/ssh-agent  /usr/bin/ck-launch-session /usr/bin/seahorse-agent --execute x-session-manager”, 因此,终于将会被运行的就是这么一条语句。而x-session-manager终于指向的是gnome-session。
        gnome-session就是终于启动GNOME桌面环境的,这个程序一般被登入管理器gdm、xdm和脚本startx调用。总结一下Ubuntu中Gnome的启动过程,核心的流程总结例如以下:

    /usr/bin/startx
    	--->xinit /etc/X11/xinit/xinitrc -- /etc/X11/xinit/xinitrc
    		--->./etc/X11/Xsession
    			--->/etc/X11/Xsession.d/
    				--->50x11-common_determine-startup
    					--->/etc/X11/Xsession.options		# 寻找相关配置选项
    					--->STARTUP=$HOME/.xsession		# 假设有.xsession脚本,则设置成执行它
      					--->STARTUP=/usr/bin/x-session-manager	# 假设没有.xsession脚本,则设置成执行x-session-manager
      						--->/usr/bin/gnome-session	# x-session-manager指向gnome-session程序
      				--->55gnome-session_gnomerc
      					--->$HOME/.gnomerc		# 选择了gnome-session,则执行$HOME/.gnomerc
      				--->75dbus_dbus-launch		# 启动dbus
      				--->80im-switch		# 设置输入法
      				--->99x11-common_start
      					--->exec $STARTUP		# 启动gnome会话,进入gnome桌面
        3、跨网络执行X Window System
        通经常使用来做服务器的系统(Linux,FreeBSD,Solaris等等)都用字符界面,不会装X server,甚至非常多都没有显示器。这样能够在这些系统里安装简单的X client,以GUI的方式远程显示在管理员们所坐的X server里。比如能够用FreeBSD做网关,提供WWW,FTP服务,一般在管理员的本地机器起个X server,然后通过ssh或telnet登录远程到FreeBSD系统,执行X client程序显示在本地显示器上,当然,也可用XDMCP(X Display Manager Control Protocol)的方式来登录执行。man xsession手冊里提到/etc/X11/Xsession一般被startx(Ubuntu中在/etc/X11/xinit/xinitrc里调用 Xsession脚本)或display manager调用,但有的display manager仅仅调用Xsession而不是xinitrc,故为了startx和display manager两种方式下都可正常启动GUI,最好把X client启动的程序放在Xsession文件中。远程执行X client程序须要设置DISPLAY环境变量,设置为 Xserver主机名称:屏幕编号(如192.168.1.115:0,则表示X server是192.168.1.115这台机器上的0号屏幕);或是给X client程序加个—display參数。这里我们在TCP/IP网络环境中測试X Window System。
        在VMWare虚拟机中安装Fedora 14,地址为192.168.1.115,使用/usr/bin/X作为X server。安装Ubuntu 10.04,地址为192.168.1.116。如今我们要使它们默认启动到字符界面。Fedora中比較简单,改动/etc/inittab文件,把当中的默认执行由5改成3,重新启动就可以。Ubuntu中使用grub v2,须要把/etc/default/grub文件里的GRUB_CMDLINE_LINUX_DEFAULT变量改动成"quiet splash text",即加上一个text參数,然后执行sudo update-grub,又一次生成grub启动菜单的配置文件/boot/grub/grub.cfg。重新启动就可以。
        (1)配置X Server
        第一步:在$HOME下生成.Xauthority认证文件里
    [jackzhou@localhost ~]$ xauth add 192.168.1.115:0 . `mcookie`
    xauth: creating new authority file /root/.Xauthority
        第二步:查看认证文件
    [jackzhou@localhost ~]$ xauth list
    192.168.1.115:0  MIT-MAGIC-COOKIE-1  728ef8138827dcc82b7aa562d946796a
        第三步:通过上面的认证文件生成一个密钥文件jackcookie
    [jackzhou@localhost ~]$ xauth extract jackcookie 192.168.1.115:0
    [jackzhou@localhost ~]$ ls -l jackcookie
    -rw-------. 1 jackzhou jackzhou 49 Jul 17 13:20 jackcookie
        第四步:将生成的密钥文件jackcookie,复制到X Client端。注意这须要Ubuntu上安装有open ssh server,能够用sudo apt-get install openssh-server安装。
    [jackzhou@localhost ~]$ scp jackcookie 192.168.1.116:$HOME
    The authenticity of host '192.168.1.116 (192.168.1.116)' can't be established.
    RSA key fingerprint is fe:a2:ef:ab:75:37:04:47:c6:4d:02:9d:58:1c:f7:35.
    Are you sure you want to continue connecting (yes/no)? yes
    Warning: Permanently added '192.168.1.116' (RSA) to the list of known hosts.
    jackzhou@192.168.1.116's password:
    jackcookie                                      100%   49     0.1KB/s   00:00
        第五步:在后台启动X Server
    [jackzhou@localhost ~]$ X -auth $HOME/.Xauthority &
        这样X server会在tty7上执行(tty7上是执行图形界面的),通过Ctrl+Alt+F7能够切换到X界面,上面一片黑暗,仅仅显示一个光标。能够通过Ctrl+Alt+F1切换回原来的字符界面,因为在不同的tty上执行,它们互不影响。
        (2)配置X Client
        第一步:将X Server传送过来的password文件jackcookie,进行导入操作
    jackzhou@jackzhou-desktop:~$ ls -l jackcookie
    -rw------- 1 jackzhou jackzhou 2011-07-17 13:17 jackcookie
    jackzhou@jackzhou-desktop:~$ xauth merge jackcookie
    jackzhou@jackzhou-desktop:~$ ls -l jackcookie
    -rw------- 1 jackzhou jackzhou 49 2011-07-17 13:21 jackcookie
        第二步:配置DISPLAY环境变量
    jackzhou@jackzhou-desktop:~$ export DISPLAY=192.168.1.115:0
        第三步:启动各种X Client,如xterm和xeye、、xclock、twm、gedit、gnome-terminal,甚至gnome-session程序,都行。注意twm在Ubuntu中默认没有安装,能够用apt-get安装。
    jackzhou@jackzhou-desktop:~$ xterm &
    jackzhou@jackzhou-desktop:~$ xeyes &
    jackzhou@jackzhou-desktop:~$ twm &
        这样在Fedora的X Server上就会显示Ubuntu中对应的X client界面了。通常的应用场景是X client机器在远程且没有显示器,X Server机器在本地,你能够通过在Fedora中使用ssh 192.168.1.116登录到远程的X client机器,来配置X Client,而不用直接跑到远程的机器上去配。
        要更加深入地研究X Window System,可參考man xserver和man x的手冊页,Wikipedia的介绍http://zh.wikipedia.org/zh-cn/X_Window,以及Xorg Foundation的官方网站http://www.x.org/wiki/。下载X11R7.6的源码,里面有各模块设计的具体文档说明。

  • 相关阅读:
    Struts2 HelloWorld_1
    Java Web JavaMail 邮件发送
    Struts2 ActionWildcard(通配符配置)约定优于配置
    Struts2 Action
    Struts2 struts2简介
    Struts2 ActionMethod DMI(动态方法调用)
    Java Web Servlet过滤器
    com学习笔记(2)基本的com接口QueryInterface的实现
    com学习笔记(4)动态链接
    silverlight Visifire图表转图片偷天换日的做法
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/3866293.html
Copyright © 2020-2023  润新知