LightDM Greeter的启动流程与分析

重要的概念

LightDM Greeter是什么?它是一个登录管理器,用于在Ubuntu或其他基于Linux的操作系统中管理用户登录。它提供了一个图形化用户界面,用户可以在其中输入他们的用户名和密码以及选择登录的桌面环境。LightDM Greeter还提供了可定制的选项,如自定义主题和背景图像。它是一个轻量级的登录管理器,可以与各种桌面环境和窗口管理器一起使用。

如果把系统比作一栋建筑,Greeter就像是那个门卫——它还不算是警卫。通过LightDM的配置把它屏蔽,用户可以长驱直入。下文以Linux Deepin系统开发的lightdm-deepin-greeter为样本。其它系统大同小异。LightDM视角下Greeter流程如下图所示:
LightDM Greeter的启动流程与分析_第1张图片

配置部分

lightdm配置

LightDM支持以下位置的配置文件:

/usr/share/lightdm/lightdm.conf.d/*.conf
/etc/lightdm/lightdm.conf.d/*.conf
/etc/lightdm/lightdm.conf

当多个配置文件存在相同配置时以最后的配置文件的配置为依据,读取顺序从上到下。dde-session-shell直接修改最后一个配置文件/etc/lightdm/lightdm.conf,把greeter-session设置为lightdm-deepin-greeter

Desktop文件

代码里面的files文件夹下的lightdm-deepin-greeter.desktop文件就是按照LightDM的要求写的配置文件,内容如下:

[Desktop Entry]
Name=Deepin Lightdm Greeter
Comment=Deepin Lightdm Greeter
Exec=/usr/bin/deepin-greeter
Type=Application
X-Ubuntu-Gettext-Domain=deepin-lightdm-greeter

CMakeLists.txt第396行代码是关于这个文件的安装规则代码,它指定安装包把这个Desktop文件复制到/usr/share/xgreeters/下面。
Desktop文件其中的Exec指定启动/usr/bin/deepin-greeter这个文件。

Shell部分

deepin-greeter

deepin-greeter是一个shell文件,代码位于files文件夹下,代码如下:

for i in /etc/deepin/greeters.d/*; do
    $i
done

CMakeLists.txt第387行代码是关于这个文件的安装规则代码,它指定安装包把这个shell文件复制到/usr/bin/下面。
它的作用是遍历/etc/deepin/greeters.d/下面的所有可执行文件,把它们依次轮流启动执行。

深度shell

这部分shell代码不在dde-session-shell工程代码里面。其中存在2个关键的shell,第一个是00-xrandr。文件名为什么要加00-呢?因为这个shell是用来获取显示设备最大支持的分辨率并改变分辨率。按照deepin-greeter这个shell的依次循环执行做法,为了保证先设置分辨率后启动界面应用,所以加了这个前缀。它的代码如下:

#!/bin/bash
#
# xrandr 输出的主屏幕有可能是断开的
# $ xrandr|egrep -o '^.* (connected|primary)'
# DVI-I-0 disconnected primary
# DVI-I-1 connected
# VGA-1-1 connected

xinfo(){
    local IFS=$'\n'
    XINFO=($(xrandr|egrep -o '^.* connected( primary)?'))
}

# 仅当连接两个屏幕时进行如下操作
if xinfo && ((${#XINFO[@]} == 2)); then
    # 假设第一行为主屏
    primary=(${XINFO[0]})
    second=(${XINFO[1]})
    # 如果第二行输出含有 primary, 则交换
    if ((${#second[@]} == 3)); then
        primary=(${XINFO[1]})
        second=(${XINFO[0]})
    fi
    xrandr --output ${second[0]} --right-of ${primary[0]} --auto
fi

第二个是lightdm-deepin-greeter。注意这还是个shell,不是Qt编译的二进制可执行文件。它的代码是:

#!/bin/bash
display_daemon="/usr/lib/deepin-daemon/greeter-display-daemon"
if [ -x $display_daemon ]; then
    $display_daemon &
fi
/usr/bin/lightdm-deepin-greeter

为了计时,编者把代码改成了:

#!/bin/bash
display_daemon="/usr/lib/deepin-daemon/greeter-display-daemon"
if [ -x $display_daemon ]; then
    echo $(date +"%Y-%m-%d %H:%M:%S") $display_daemon  >> /home/log/greeter-elapse.log
    $display_daemon &
fi
echo $(date +"%Y-%m-%d %H:%M:%S") /usr/bin/lightdm-deepin-greeter started >> /home/log/greeter-elapse.log
/usr/bin/lightdm-deepin-greeter
echo $(date +"%Y-%m-%d %H:%M:%S") /usr/bin/lightdm-deepin-greeter ended >> /home/log/greeter-elapse.log

增加到代码都是把时刻打印到/home/log/greeter-elapse.log。需要注意是的这些shell的启动身份是lightdm这个用户。这个用户权限很低,/home/log/ 的权限须为755greeter-elapse.log的权限须为777

可执行文件部分

/usr/bin/lightdm-deepin-greeter是最终的可执行文件,它才是dde-session-shell的编译结果。CMakeLists.txt第386行代码指定安装包把lightdm-deepin-greeter复制到/usr/bin

主程序入口

main函数位于lightdm-deepin-greeter.cpp第181行。开始启动时调用DTK加载主题,设置Qt主程序相关信息,设置Qt的调色板等等。最重要的是判断当系统环境是不是X11,如果是则加载XCB插件。

SessionBaseModelGreeterWorkek类型虽然不是单例模式的实现,但是单例模式的用法,它在界面类型中层层传递,确认只有这些类型的单个对象。GreeterWorkek实现了登录逻辑。

多屏的信号监听由MultiScreenManager提供支持。每个屏幕信号都触发一次std::function 类型的回调。

LoginWindow类型

这个类型是主窗口,继承自FullscreenBackground类型。FullscreenBackground的作用是全屏遮挡,但它作用一个通用类型不提供界面的实现细节,也不实现对鼠标和键盘信号的抓取并屏蔽功能。它特别提供了一个调试功能,debug模式编译的程序可按Esc键退出。

绘制的背景图片之前要获取用户设置的背景图片。曾经的做法是从com.deepin.daemon.Accounts服务获取用户的背景图片的路径,然后调用com.deepin.daemon.ImageEffect生成虚化的背景图片,用虚化的背景图片填充效果。这样的做法存在一个巨大的敝端:无论用户是否修改过背景图片,它在每次登录操作都要生成一次。对于龙芯这样的没有真实GPU只能模拟图形处理的硬件平台造成不必要的启动缓慢问题。后来引入共享内存技术,通过保存用户修改背景图片设置时的保存的缓存图片,一定程序上提高了greeter启动速度,特别对于开机后的注销、锁屏操作,速度提升效果更加明显。

LoginContent类型

LoginContent类型继承自LockContent类型。这里是greeter和锁屏程序的逻辑存在共用的地方。框架上的整体布局由它管理和设置,它管理的LogoWidget对象实现了左下角UOS的标志,MediaWidget对象实现了锁屏播放音乐,UserLoginInfo对象实现中间的登录界面,ControlWidget实现了切换用户、关机、重启等界面。

关于服务器版本

服务器版本不显示用户列表,不过它并非通过LightDM的配置实现,而是自己写了一个配置文件,代码位于files文件夹下的dde-session-ui.conf.in,代码是:

[Power]
sleep=$$ENABLE_SLEEP
hibernate=$$ENABLE_HIBERNATE

[OS]
isDeepin=$$IS_DEEPIN

[General]
loginPromptAvatar=$$LOGIN_PROMPT_AVATAR
loginPromptInput=$$LOGIN_PROMPT_INPUT
lockNoPassword=false

[Lock]
#[always | ondemand | disabled]
showSwitchUserButton=$$SHOW_SWITCH_USER_BUTTON

其中$ENABLE_SLEEP$$LOGIN_PROMPT_INPUT$$IS_DEEPIN$$LOGIN_PROMPT_INPUT$$SHOW_SWITCH_USER_BUTTON是CMake传递过来的变量。showSwitchUserButton指明是否显示切换用户按钮,sleep指明是否显示休眠按钮,hibernate指明是否显示待机按钮,isDeepin指示是否深度系统,loginPromptAvatar指示是否显示用户头像。

dde-session-ui.conf.inCMakeLists.txt指定安装到/usr/share/dde-session-ui/dde-session-ui.conf

作者: 岬淢箫声
日期: 2020年12月16日
版本: 1.0
博客: http://caowei.blog.csdn.net
创作不易,请大家多多支持关注、转发。转发请注明来源。

你可能感兴趣的:(Linux,lightdm,linux)