startx启动过程分析

startx 启动过程分析

1       xinit

在说明 startx 之前,我想我们应该先 了解一下 xinit 。因为 startx 就是通过调用 xinit 启动 X 的。

1.1     功 能

当我们安装了 Ubuntu 后,默认就已经安装了 xinit ,它位于 /usr/bin 下。 xinit 是一个二进制文件,并非是一个脚本。它的主要功能是启动一个 X 服务器,同时启动一个基于 X 的 应用程序。

1.2     用 法

xinit 的用法为: xinit [[client] options ] [-- [server] [display] options] 。其中 client 用于指定一个基于 X 的应用程序, client 后面的 options 是传给这个应用程序的参数, server 是用于指定启动哪个 X 服务器,一般为 /usr/bin/X 或 /usr/bin/Xorg , display 用于指定 display number ,一般 为 0 ,表示第一个 display , option 为传给 server 的参数。

 

如果不指定 client , xinit 会查找 HOME ( 环境变量 ) 目录下的 .xinitrc 文件,如果存在这个 文件, xinit 直接调用 execvp 函数执行该文件。如果这个文件不存在,那么 client 及其 options 为:  xterm -geometry +1+1 -n login -display :0 。

 

如果不指定 server , xinit 会查找 HOME( 环境变量 ) 目录下的 .xserverrc 文件,如果存在这个文件, xinit 直接调用 execvp 函数执行该文件。如果这个文件 不存在,那么 server 及其 display 为:  X :0 。如果系统目录中不存在 X 命令,那么我们需要在系统目录下建立一个名为 X 的链接,使其指向真正的 X server 命令( Ubuntu 下为 Xorg )。

 

1.3     例 子

下面是几个关于 xinit 应用的例子:

1)       xinit /usr/bin/xclock -- /usr/bin/X :0

该例子将启动 X server , 同时将会启动 xclock 。请注意指定 client 或 server 时,需要用绝对路径,否则 xinit 将因无法区别是传给 xterm 或 server 的参数还是指定的 client 或 server 而直接当成是参数处理。

2)       在 HOME 下新建 .xinitrc 文件,并加入以下几行:

         
xsetroot -solid gray &


         
xclock -g 50x50-0+0 -bw 0 &


         
xterm -g 80x24+0+0 &


         
xterm -g 80x24+0-0 &


         
twm


当 xinit 启动时,它 会先启动 X server ,然后启动一个 clock ,两个 xterm ,最后启动窗口管理器 twm 。

请注意:

最后一个命令不能后台运行,否则所有命令都后台运行的话 xinit 就会返回退出,同样的,除最后一个命令外都必须后台运行,否则后面的命令将只有在该命令退出后才能 运行。

 

1.4     分 析

看到这里,眼尖的人或许早以看出 xinit 的功能完全可以由脚 本来实现,例如要启动 X Server 和一个 xterm ,就像 xinit 默认启动的那样,只需要在新建一个脚本或在 rc.local 中加入:

X&

export DISPLAY=:0.0

xterm

这个实现完全正确,然而却并没有完全实现 xinit 所具有的功能, xinit 所有的一项功能就是当最后一个启 动的 client (如上面第二个例子中的 twm 窗口管理器)退出后, X 服务器也会退出。而我们的脚本实现中当我们退出 xterm 后并不会退出 X server 。


 

2       startx 脚本

用过 linux 的人基本上都知道 linux 下有个命令叫做 startx , 那么它到底是怎么实现的呢 ?

2.1     功 能

当我们在终端下想启动图形界面时,我们都会通过输入 startx 来实现,该命令可 以启动一个 X server ,而且可以启动一个漂亮的图形界面( Ubuntu 下,我装的是 gnome )。

2.2     用 法

Startx 的用法和 xinit 的基本一样 : startx [ [ client ] options ... ] [ -- [ server ] options ... ] 。为什么呢?这是因为 startx 其实就是一个脚本,它启动 X server 就是通过调用 xinit 命令实现的, startx 的参数将全部传给 xinit 。因此,这些参数的意义和 xinit 的参数是一样的。

2.3     例 子

下面是两个关于 startx 命令的简单例子:

1)   startx -- -depth 16

该例子主要是以 16 位色启动 X 服务器。

2)   startx -- -dpi 100

该例子主要是以 100 的 dpi 启动 X 服务器。

2.4     分 析

下面我们来分析一下 startx 脚本。 startx 脚本位于 /usr/bin 下,直接用 vim 打开我们可以看到它的具体实现如下:

 

#!/bin/bash # 注意:该脚本用的是 bash shell 解析的

 

# $Xorg: startx.cpp,v 1.3 2000/08/17 19:54:29 cpqbld Exp $

#

# 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.

#

# $XFree86: xc/programs/xinit/startx.cpp,v 3.16tsi Exp $

 

# 下面主要是对一些变量进行赋值。

userclientrc=$HOME/.xinitrc

sysclientrc=/etc/X11/xinit/xinitrc

 

 

userserverrc=$HOME/.xserverrc

sysserverrc=/etc/X11/xinit/xserverrc

defaultclient=xterm

defaultserver=/usr/bin/X

defaultclientargs=""

defaultserverargs=""

clientargs=""

serverargs=""

 

# 下面的语句主要是说:如果 $HOME/.xinitrc 文件存在,并且不是一个目录,那么就将 defaultclientargs 赋值为 $HOME/.xinitrc ,否则,如果 /etc/X11/xinit/xinitrc 存在并且不是一个目录,就将 defaultclientargs 赋值为 /etc/X11/xinit/xinitrc 。

 

if [ -f $userclientrc ]; then

    defaultclientargs=$userclientrc

elif [ -f $sysclientrc ]; then

    defaultclientargs=$sysclientrc

 

 

 

 

 

 

fi

 

# 下面的语句主要是说:如果 $HOME/.xserverrc 文件存在,并且不是一个目录,那么就将 defaultclientargs 赋值为 $HOME/.xserverrc ,否则,如果 /etc/X11/xinit/xserverrc 存在并且不是一个目录,就将 defaultclientargs 赋值为 /etc/X11/xinit/xserverrc 。

 

if [ -f $userserverrc ]; then

    defaultserverargs=$userserverrc

elif [ -f $sysserverrc ]; then

    defaultserverargs=$sysserverrc

fi

# 将 whoseargs 变量赋值为字符串“ client ”,表示当前解析的指定 client 的参数。

whoseargs="client"

# 当 startx 的一个参数不为空时就进入 while 循环。

while [ x"$1" != x ]; do

    case "$1" in

    # '' required to prevent cpp from treating "/*" as a C comment.

    /''*|/./''*)

  if [ "$whoseargs" = "client" ]; then

     if [ x"$clientargs" = x ]; then

  client="$1" # 解析出了用户指定的 Client 程序

     else

  clientargs="$clientargs $1"  # 解析出了 Client 的参数

     fi

  else

     if [ x"$serverargs" = x ]; then

  server="$1"  # 解析出了用户指定的 X Server 程序

     else

  serverargs="$serverargs $1" # 解析出了 X Server 的参数

     fi

  fi

  ;;

    --)    # 遇到“ - - ”就解析 server

  whoseargs="server"

  ;;

    *)

  if [ "$whoseargs" = "client" ]; then

     clientargs="$clientargs $1"

  else

     # display must be the FIRST server argument

     if [ x"$serverargs" = x ] && /

   expr "$1" : ':[0-9][0-9]*$' > /dev/null 2>&1; then

  display="$1" # 解析出 display

      else

  serverargs="$serverargs $1"

     fi

  fi

  ;;

    esac     #case 语句结束

shift  # 将参数列表左移一位,即解析下个参数 .

done

 

# process client arguments

if [ x"$client" = x ]; then # 如果 client 变量为空,即用户没有指定 client 。

    # if no client arguments either, use rc file instead

    if [ x"$clientargs" = x ]; then # 如果用户没有 指定 client 参 数 就将 client 设为前面设定的默认的 rc 文件(为 $HOME/.xinitrc ,或 /etc/X11/xinit/xinitrc )

  client="$defaultclientargs"

    else

  client=$defaultclient # 如果用户指定了 client 参数,就将 client 设定为 xterm

    fi

fi

 

# process server arguments

if [ x"$server" = x ]; then # 如果 server 变量为空,即用户没有指定 server 。

    # if no server arguments or display either, use rc file instead

    if [ x"$serverargs" = x -a x"$display" = x ]; then # 如果 serverargs 为空,并且 display 为空,就将 server 设为前面设定的默认的 rc 文件(为 $HOME/. xserverrc ,或 /etc/X11/xinit/ xserverrc )

  server="$defaultserverargs"

    else

  server=$defaultserver # 如果用户指定 了 serverargs 或 display ,就将 server 设定为 /usr/bin/X

    fi

fi

 

if [ x"$XAUTHORITY" = x ]; then # 如果环境变量 XAUTHORITY 为空,就设定为 $HOME/.Xauthority

    XAUTHORITY=$HOME/.Xauthority

    export XAUTHORITY

fi

 

removelist=

 

# set up default Xauth info for this machine

 

# check for GNU hostname

if hostname --version > /dev/null 2>&1; then # 如果 hostname 命令存在

       if [ -z "`hostname --version 2>&1 | grep GNU`" ]; then # 如果 hostname –version 中不包含 GNU 就将 hostname 变量设定为命令 hostname –f 返回的字符串。

  hostname=`hostname -f`

       fi

fi

 

if [ -z "$hostname" ]; then # 如果 hostname 长度为 0, 就将 hostname 变量设定为命令 hostname 返回的字符串。

hostname=`hostname`

fi

 

authdisplay=${display:-:0}

 

mcookie=`/usr/bin/mcookie`

 

 

 

 

 

 

 

dummy=0

 

# create a file with auth information for the server. ':0' is a dummy.

xserverauthfile=`mktemp -p /tmp 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

echo "client=$client,clientargs=$clientargs,server= $server, display= $display, serverargs=$serverargs"

 

# 下面的语句通过 xinit 启动 X server 和 Clients 。

xinit $client $clientargs -- $server $display $serverargs

 

 

if [ x"$removelist" != x ]; then

    xauth remove $removelist

fi

if [ x"$xserverauthfile" != x ]; then

    rm -f $xserverauthfile

fi

 

 

 

 

 

if command -v deallocvt > /dev/null 2>&1; then

    deallocvt  # 释 放所有未使用的虚拟终端的核心内存和数据结构

fi

 

 

2.5     总 结

由以上对 startx 脚本的分析,我们可以 知道: startx 将会先解析用户的参数,如果该用户指定了该参数(即解析结果不为空),那么 startx 就会以该参数来启动 xinit ,否则就会解析(与其说是解析,还不如说是执行) $HOME 目录下的 rc 文 件,如果该文件不存在,就会解析系统目录下( /etc/X11/xinit/ )的 rc 文件,如果这个文件也不存在,那 startx 就将以默认的 client ( xterm )和 server ( /usr/bin/X )为参数来启动 xinit 。


 

3       startx 默认启动过程

通过以上对 startx 脚本的分析,我们知道 了 startx 的基本的启动流程,但是到目前为止,我们还不知道仅仅在终端输入 startx 是怎么样启动 gnome 那漂亮的桌面的,下面我们来看一下其启动过程。

3.1     startx 的几种启动方式

由对 startx 脚本的分析,我们可以知道 startx 主要有三种启动方式:

a) 、一种是自己指定要启动的 client 和 server , 例如: startx /usr/bin/xclock -- /usr/bin/X :0 ;

b )、一种是通过在 $HOME 下新建 .xinitrc 文件来指定要启动的多个 client 和 .xserverrc 来指定要启动的 server (注意:这两个文件本来是不存在的);

c )、还有一种是直接输入 startx 而不指定参数,这也就是我们启动 gnome 桌面的方法。这里

 

我们主要介绍最后一种启动方法。

 

在 c 这种启动方法中,我们可以知道, startx 脚本会先去看系统目录( /etc/X11/xinit/ )下的 rc 文件是否存在,如果不存在就会用默认的 xterm 和 /usr/bin/X 来启动 xinit 。显然, startx 启动的不是 xterm ,而是 gnome 桌面,因此 gnome 的启动是通过系统文件 /etc/X11/xinit/xinitrc 来指定的。

 

而 /etc/X11/xinit/xinitrc 文件的内容如下所示:

 

#!/bin/bash  # 注意 : 该脚本用的是 bash shell 解析的

 

# $Xorg: xinitrc.cpp,v 1.3 2000/08/17 19:54:30 cpqbld Exp $

 

# /etc/X11/xinit/xinitrc

#

# global xinitrc file, used by all X sessions started by xinit (startx)

 

# invoke global X session script

. /etc/X11/Xsession   # 在当前这个 shell 环境中执行 Xsession 脚本

 

 

因此, gnome 的启动应该在 Xsession 里。

 

而 X Server 的启动则是通过系统文件 /etc/X11/xinit/xserverrc 来指定的 , 这个文件的内容为 :

 

#!/bin/sh # 注意:该脚本用的是 Bourne shell 解析的

 

# $Id: xserverrc 189 2005-06-11 00:04:27Z branden $

 

exec /usr/bin/X11/X -nolisten tcp

 

3.2      Xsession

下面是 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

 

# 下面四个是信息输出函数,可以不管

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>."

}

 

# initialize variables for use by all session scripts

 

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

 

# attempt to create an error file; abort if we cannot

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

# truncate ERRFILE if it is too big to avoid disk usage 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)"

 

# sanity check; is our session script directory present?

 

# 如果 /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

 

# 将 /etc/X11/Xsession.d 目录中的所有文件都读出,并存入 SESSIONFILES 变量中。

SESSIONFILES=$(run-parts --list $SYSSESSIONDIR)

# 如果 SESSIONFILES 变量中的字符串不为空,即 /etc/X11/Xsession.d 中有文件存在

if [ -n "$SESSIONFILES" ]; then

  set +e # 关闭 errexit 选项

  for SESSIONFILE in $SESSIONFILES; do

    . $SESSIONFILE # 在当前 shell 环境下执行该文件

  done

  set –e # 打卡 errexit 选项

fi

exit 0

 

从以上的对 Xsession 脚本文件的分析 , 可以看出 , Xsession 脚本仅仅是执行了 /etc/X11/Xsession.d 目录下的所有文件,在该目录下,文件包括:

20x11-common_process-args

30x11-common_xresources

40x11-common_xsessionrc

50x11-common_determine-startup

55gnome-session_gnomerc

60seahorse

60xdg-user-dirs-update

80im-switch

90-console-kit

90x11-common_ssh-agent

99x11-common_start

 

每个文件名都以数字开头,这主要是为了确保这些脚本的 执行顺序, 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 变量仍然为空,则将其设置为 x-session-manager , x-window-manager 或 x-terminal-emulator 。注意:这个 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 ,如果是则执行 $HOME/.gnomerc (如果该文件存在并且可读)。

 

6 、 60seahorse

   将 STARTUP 重新赋值为“ /usr/bin/seahorse-agent $STARTUP ”,这个可能只是为安全考虑才这么做的,具体的我也不 是很清楚,只是看了一下 seahorse-agent 的帮助,知道 seahorse 是一个 GNOME 的应用程序,它用于为用户的输入进行暂时的安全存储,而 seahorse-agent 则是 seahorse 的一个代理而已。

 

7 、 60xdg-user-dirs-update

   用 xdg-user-dirs-update 自动生成 $HOME 下的文件夹,该命令主要是根据 /etc/xdg/user-dirs.defaults 文件的内容来为用户创建文件夹的。

 

8 、 80im-switch

   该文件主要用于设置输入法。具体的请自己参考文件内容。

 

9 、 90-console-kit

   如果环境变量 $XDG_SESSION_COOKIE 为空,并且 /usr/bin/ck-launch-session 可执行,则将 STARTUP 重新赋值为 ” /usr/bin/ck-launch-session $STARTUP” 。至于 ck-launch-session 的功能,我也不是很清楚,估计是和 session 有关。

 

10 、 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” 。

 

11 、 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 在 Ubuntu8.04 中仅仅是个符号链接,它最终指向的是 gnome-session 。

    gnome-session 则是启动 GNOME 桌面环境的,这个程序一般被登入管理器 gdm 、 xdm 和脚本 startx 调用。( gnome-session 如何启动桌面,待研究)

 


 

4       startx 启动过程小结

综上所述, startx 的默认启动过程为: startx 调用并将系统文件 /etc/X11/xinit/xinitrc 和 /etc/X11/xinit/xserverrc 作为参数传给 xinit , xinit 就会先执行系统文件 /etc/X11/xinit/xserverrc 以启动 X Server ,然后执行 /etc/X11/xinit/xinitrc ,而 xinitrc 则会执行脚本 /etc/X11/Xsession ,而 Xsession 则会按顺序调用执行 /etc/X11/Xsession.d 目录下的文件,从而最终调用了 gnome-session 这个用于 启动 GNOME 桌面环境的程序。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页