• 首页
  • 加入
  • RSS
  • Wednesday, December 12, 2018

    最近deepin要添加休眠功能,但是之前测试的通过swapfile来休眠失败了,所以对正在使用swap分区的用户提供休眠功能。但是昨天我在askubuntu上看到有人发了在ubuntu下通过swapfile休眠的方案,今天试了一下,效果良好,觉得可以考虑给deepin也加上这样的功能。

    原文链接: Hibernate and resume from a swap file

    具体步骤是通过uswsusp这个包来做的,uswsusp是一组用户空间工具,用于Linux系统上的休眠(挂起到磁盘)和挂起(挂起到RAM或待机)。详细内容可以在ArchWiki上参考。点这里

    先创建一个和内存同等大小的swapfile,为了确保休眠成功,不能小于内存的容量。

    sudo fallocate -l 16g /swapfile # 我的机子是16G,具体自己修改
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    sudo swapon /swapfile
    echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab

    安装用户空间软休眠(Userspace Software Suspend)包

    sudo apt install uswsusp

    创建需要的配置文件,只需要创建文件即可。

    sudo touch /etc/uswsusp.conf
    sudo dpkg-reconfigure -pmedium uswsusp

    这时候终端会提醒是否继续,选择Yes,然后会要求你创建一个密码,设置一个密码继续即可。

    此时就可以测试一下功能了,不过我是跳过这个步骤了(比较喜欢作死)。

    修改systemd的hibernate服务,使用uswsusp来代替systemd的功能。

    sudo systemctl edit systemd-hibernate.service

    写入以下内容:

    [Service]
    ExecStart=
    ExecStart=/usr/sbin/s2disk
    ExecStartPost=/bin/run-parts -a post /lib/systemd/system-sleep

    这时候可以使用systemd的命令来测试的,我表示工作的非常正常。

    systemctl hibernate

    执行以后可以看到屏幕上会打印当前保存的进度,然后设备就关机了,此时再开机,等待一会儿以后就看到了背景是我漂亮老婆的锁屏,解锁以后看到工作区还是执行命令前的,一切ok。

    参考以下内容:

    https://askubuntu.com/questions/6769/hibernate-and-resume-from-a-swap-file

    https://wiki.archlinux.org/index.php/Uswsusp

    Wednesday, June 27, 2018

    CUDA(Compute Unified Device Architecture,统一计算架构)是由NVIDIA所推出的一种集成技术,是该公司对于GPGPU的正式名称。通过这个技术,用户可利用NVIDIA的GeForce 8以后的GPU和较新的Quadro GPU进行计算。亦是首次可以利用GPU作为C-编译器的开发环境。NVIDIA营销的时候,往往将编译器与架构混合推广,造成混乱。实际上,CUDA可以兼容OpenCL或者自家的C-编译器。无论是CUDA C-语言或是OpenCL,指令最终都会被驱动程序转换成PTX代码,交由显示核心计算。

    在论坛上看到有些用户希望在deepin下使用CUDA,但是他们采取的做法往往是手动下载nvidia的二进制文件,直接进行安装。

    但是这样会破坏一部分的glx链接,导致卸载的时候无法彻底恢复,结果就是系统因为卸载nvidia驱动而废掉,所以我推荐使用包管理器的方式安装nvidia驱动和cuda相关的东西,尽量不要手动修改。

    需要安装的很少,只有五个包,不过会依赖很多nvidia的库,总量还是有一些的。

    sudo apt install nvidia-cuda-toolkit nvidia-profiler nvidia-visual-profiler nvidia-cuda-doc nvidia-cuda-dev

    nvcc是cuda的编译器,它目前只支持g++5,所以还需要安装g++5。

    sudo apt install g++-5

    然后,重启一下计算机。

    这里有个小栗子,可以用来测试cuda是否能够成功编译和运行

    将以下代码保存为 main.cu

    #include <stdio.h>

    __global__ void vector_add(const int *a, const int *b, int *c) {
    *c = *a + *b;
    }

    int main(void) {
    const int a = 2, b = 5;
    int c = 0;

    int *dev_a, *dev_b, *dev_c;

    cudaMalloc((void **)&dev_a, sizeof(int));
    cudaMalloc((void **)&dev_b, sizeof(int));
    cudaMalloc((void **)&dev_c, sizeof(int));

    cudaMemcpy(dev_a, &a, sizeof(int), cudaMemcpyHostToDevice);
    cudaMemcpy(dev_b, &b, sizeof(int), cudaMemcpyHostToDevice);

    vector_add<<<1, 1>>>(dev_a, dev_b, dev_c);

    cudaMemcpy(&c, dev_c, sizeof(int), cudaMemcpyDeviceToHost);

    printf("%d + %d = %d, Is that right?\n", a, b, c);

    cudaFree(dev_a);
    cudaFree(dev_b);
    cudaFree(dev_c);

    return 0;
    }

    编译:

    nvcc main.cu

    运行:

    ./a.out

    如果一切顺利,在编译的时候就不会有报错,不过在我的环境下nvcc会有架构被弃用的警告,本着只要不error就算没事的原则,我们无视这条警告即可。

    输出结果:

    2 + 5 = 0, Is that right?

    Sunday, June 24, 2018

    笔记本一直使用的bumblebee来省电,毕竟我也不想笔记本的电只够从一张桌子移动到另一张桌子,但是今天在调待机唤醒后dde-dock崩溃的问题,我需要切换到私有驱动下,因为笔记本使用bumblebee需要使用acpi的参数,否则会见图形就死。

    一切准备就绪以后,我开始调试dde-dock,通过codedump已经知道崩溃在wifi列表为空时访问了first节点,但是当我开始测试修复的代码时,发生了很意外的事情,恢复待机以后键盘和触摸板无法使用了。

    虽然之前我也偶尔会用用私有驱动,但是还没遇到过无法键盘和触摸板无法使用的情况。想到论坛好像也有人报了类似的问题,恢复待机以后无wifi和外置键盘无法使用,刚好可以趁这个机会调试一下。

    /var/log/Xorg.0.log里看到了大量的synaptics错误,然后该模块被卸载,键盘则是没看到什么信息。

    尝试重新modprobe synaptics模块,但是失败了,然后在/etc/modprobe.d/nvidia.conf里看到了几行配置。

    # These aliases are defined in *all* nvidia modules.
    # Duplicating them here sets higher precedence and ensures the selected
    # module gets loaded instead of a random first match if more than one
    # version is installed. See #798207.
    #aliaspci:v000010DEd00000E00sv*sd*bc04sc80i00*nvidia
    #aliaspci:v000010DEd00000AA3sv*sd*bc0Bsc40i00*nvidia
    #aliaspci:v000010DEd*sv*sd*bc03sc02i00*nvidia
    #aliaspci:v000010DEd*sv*sd*bc03sc00i00*nvidia

    似乎是通配出错了,匹配到了键盘和触摸板,然后就无法使用了。刚好deepin 15.6升级了nvidia驱动,所以是现在才会出这个问题。

    Tuesday, May 22, 2018

    从零构建 dde-dock 的插件
    本教程将展示一个简单的 dde-dock 插件的开发过程,插件开发者可跟随此步骤为 dde-dock 创造出更多具有丰富功能的插件。

    在本教程中,将创建一个可以实时显示用户家目录(~/)使用情况的小工具。

    插件的工作原理
    dde-dock 插件本质是一个按 Qt 插件标准所开发的共享库文件(so)。通过 dde-dock 预定的规范与提供的接口,共同完成 dde-dock 的功能扩展。

    准备环境
    插件的开发环境可以是任意的,只要是符合 Qt 插件规范及 dde-dock 插件规范的共享库文件,都可以被当作 dde-dock 插件载入。下面以 Qt + qmake 为例进行说明:

    安装依赖
    以 Deepin 15.5.1 环境为基础,至少先安装如下的包:

    • dde-dock-dev
    • qt5-qmake
    • qtbase5-dev-tools
    • libqt5core5a
    • libqt5widgets5
    • pkg-config

    基本的项目结构
    创建必需的项目目录与文件
    插件名称叫做home_monitor,所以创建以下的目录结构:

    home_monitor
    ├── home_monitor.json
    ├── homemonitorplugin.cpp
    ├── homemonitorplugin.h
    └── home_monitor.pro

    Sunday, March 11, 2018

    dde-session-ui里面包含了很多项目,是一个集合,但是其中的代码缺少合理的维护,以至于已经到了必须重构才能继续开发和维护,在支持AD域登录的时候,如果强制加上功能,代码会变得更加糟糕,所以和石博文一块重构了其中非常重要的UserWidget。

    重构前的设计

    重构前的dde-lock和lightdm-deepin-greeter是非常混乱的,处理逻辑都混杂在一块,虽然能看出有基本的结构,但是整体并未解耦。

    重构后的设计

    • 基于User类的处理
    • UserWidget负责提供对用户的处理,暴露出基本的currentUser和LogindUsers。
    • Lock和Greeter的Manager从UserWidget、SessionWidget中获取用户和用户的会话。
    • Manager只负责控件的位置和用户的验证。
    • 背景修改为Manager提供模糊的壁纸,FullBackground只提供绘制。

    重构以后用了大概原代码的1/3,启动速度也快了,感觉世界充满了美好… 就是重构历程太辛苦…

    本次也发现了很多自身的问题,基础并没有学好,很多地方都可以使用更好的处理方式【就是管不住这手…】

    Friday, January 12, 2018

    在阅读本篇文章之前,你需要掌握基本的Qt/C++开发知识。

    注意:本篇文章基于Deepin平台,其他平台请自行补充依赖关系。

    先安装DTK的依赖关系。

    sudo apt install libdtkwidget2 libdtkcore2

    新建Qt项目,编辑pro文件,添加项目依赖。

    CONFIG += c++14 link_pkgconfig
    PKGCONFIG += dtkwidget

    DTK目前有两个组件,一个是提供库功能的core,一个是提供控件的widget。

    修改main.cpp,删除QApplication的相关内容,改为DApplication。

    注意: 使用DTK的组件,需要使用DTK的宏,根据使用的文件来选择对应的宏。

    DWIDGET_USE_NAMESPACE
    DCORE_USE_NAMESPACE

    DTK使用了deepin自己的qt插件,需要在DApplication前调用。

    DApplication::loadDXcbPlugin();
    DApplication app(argc, argv);

    DApplication中提供了很多方法来设置程序的各种信息,具体请看头文件的定义。

    主窗口由DMainWindow提供,新建类,然后添加DMainWindow的头文件和DTKWIDGET的宏。

    #include <DMainWindow>

    DWIDGET_USE_NAMESPACE

    然后修改继承关系,改为继承DMainWindow。DMainWindow提供了一些我们封装的方法。目前为止,该程序的界面已经符合Deepin程序的风格了,我们封装了一些其他控件,使其样式符合我们的风格,如果要在其他Qt程序中使用,也是同样的步骤,载入Qt插件,添加对应的头文件和DTK的宏。

    Wednesday, August 23, 2017

    这里记录了开发topbar中遇到的坑和一些问题。

    使用Qt提供的qxcb方法注册阴影为dock类型,反而处于DESKTOP和NORMAL之间。其实当初并不是想设置为DOCK类型的,因为这样阴影也会在窗口上方,我希望的是阴影在普通程序下方,在桌面上方。今天曹哥来讲窗管的一些坑,讲到窗管是如何控制窗口的,我的阴影其实是被Qt注册成_NET_WM_STATE_BELOW了。
    这里可以看到一些type的介绍

    在_NET_WM_STATE中一共有这么几个类型:

    _NET_WM_STATE_MODAL, ATOM
    _NET_WM_STATE_STICKY, ATOM
    _NET_WM_STATE_MAXIMIZED_VERT, ATOM
    _NET_WM_STATE_MAXIMIZED_HORZ, ATOM
    _NET_WM_STATE_SHADED, ATOM
    _NET_WM_STATE_SKIP_TASKBAR, ATOM
    _NET_WM_STATE_SKIP_PAGER, ATOM
    _NET_WM_STATE_HIDDEN, ATOM
    _NET_WM_STATE_FULLSCREEN, ATOM
    _NET_WM_STATE_ABOVE, ATOM
    _NET_WM_STATE_BELOW, ATOM
    _NET_WM_STATE_DEMANDS_ATTENTION, ATOM

    如果程序被注册成_NET_WM_STATE_BELOW,则会被放置在DESKTOP之上的一层。不是很清楚Qt是出于什么策略,才把我的阴影注册为这个状态,反而是刚好满足了我的需求。

    这要多谢曹哥了,我才终于明白了为什么会这样,以及以后如何正确的设置type。

    DESKTOP1DESKTOP2

    Wednesday, August 16, 2017

    前言: 项目一定要留一些文档!! 修bug前一定要知道所有的流程!!!

    这两天一直在修一个用户切换的bug,众所周知,deepin的多用户切换一直都不是正常工作的,确切来说是压根没有正常工作,还好用户不是经常切换,不然早就收到一大波的报告了。

    dde-session-ui项目中包含了以下软件:

    • dde-lock
    • dde-shutdown
    • dde-osd
    • lightdm-deepin-greeter
    • dde-switchtogreeter
    • dde-suspend-dialog
    • dde-warning-dialog
    • dde-welcome
    • dde-wm-chooser
    • dde-lowpower
    • dde-offline-upgrader

    大部分项目根据名字就可以知道是做什么的,这是一个软件组的集合。
    而dde-lock和lightdm-deepin-greeter二者有大量重复的功能和代码,这是它俩的工作性质决定的。

    lightdm-deepin-greeter: display-manager启动的实体,登录的界面是它负责的。

    dde-lock: 用户层面的屏幕锁定,基于我们的设计,和lightdm-deepin-greeter是大致相同的布局。

    而且都包含了用户密码的验证,用户的切换,但是二者工作的层面是不同的,为了方便切换,就有了dde-switchtogreeter,用来协调二者的工作,只需要提供用户名就可以切换。

    然而,虽然这样的想法是很好的,可是当初并没有人写文档,随着人员的变动,现在公司应该没有一个人是比较完整了解整个的工作流程了,用户切换的bug也就这样被留下来了。

    上次修复用户切换的问题,是发现登录以后lightdm-deepin-greeter没有退出,由于不是很清楚linux的登录流程,再加上代码中有不工作的退出代码,当时就改好了退出的问题,这样就引入了第二个问题,而这个问题,就导致了两天三个人在一直查找问题所在。

    这次的问题是发现一直切换greeter,会导致Xorg一直在开新的display,这就很奇怪了,正常来说是不会一直创建才对。

    最开始以为是dde-switchtogreeter的问题,毕竟切换是它在做,dde-switchtogreeter是单文件的c代码,代码没有任何的说明,真的是为切换而生,我从main函数开始自己走了好几遍的流程,一边看着d-feet的数据来验证,然而只发现了一个小问题,整个代码是没啥问题的。

    最后在后端大佬的帮助下,知道了display-manager会自己退掉greeter,不需要自己退,然后我就想起来了以前改的地方,赶紧把退出代码删掉,重新编译,问题得到了解决。

    如果我知道display-manager的工作流程,也许这个问题就不会拖两天了。

    Monday, August 14, 2017

    排查了一天,最后终于确认了流程,知道了问题所在,不得不说,dde-session-ui这个项目太需要一个文档了,要把工作流程写的非常详细才可以。

    上午收到了一条新任务,是龙芯上新安装的系统需要输入两次密码才可以登录,没有错误提示。近期并没有什么太大的改动,无非是给龙芯也用上了简单重构过的dde-session-ui,怎么会导致这样的问题。

    由于是新安装的系统才会发生,而且是现象一旦发生,就无法重现,这让我头有点大,怎么会有这样的神奇的事情,而且日志中很正常,没有收到message导致密码框被清空。我提交了一个添加了更多日志的,然后重装的龙芯的系统(龙芯重装一次要半个小时),等重装完了,切换到tty去安装这个包,然后重启lightdm,让我输入密码回车以后,密码消失,我赶紧去看日志,但是日志中并没有我的输出,回车以后肯定会有的一行输出也没有(内心OS:What the fuck is that?)

    我又回去看验证的流程,并没有发现有什么不对的地方,而且是近期才有的,我在自己电脑上使用了龙芯的编译参数,打了一个deb包,并没有发生和龙芯一样的情况(这里并不需要,既然是新安装的系统才会发生,在旧系统上是无法重现的)。

    再然后我暂时没有管这个,先去修其他bug了。忙完以后,我去问了一下其他大佬,大佬给我提了几条让我去看看,是不是起了两个lightdm-deepin-greeter进程,确认一下使用的二进制是不是你加了log的。(然后我又重装龙芯了),之后确认了是我的二进制,也没有起两个进程。但是ps中有两行输出,我以为是起了两个,就让后端大佬看了一下,后端大佬告诉我说一个是shell的进程,一个是本体,还是只有一个进程存在的。我彻底懵逼了,然后后端大佬告诉我,是不是greeter进程写入什么了,之后的验证中内容已经存在,所以就不会重现了。

    其实这个我也想过,但是没考虑太深,greeter并没有操作文件,但是大佬这么一说,我想到有一些dbus的调用,是有写入文件的,然后我把/var/lib/lightdm/lightdm-deepin-greeter目录给删除了,完美重现。

    我的天啊,排查了快一天,居然是这个目录在新装的系统上没有,所以回车登录以后收到了来自dbus的switchToUser,界面重启导致的内容消失,根本不是收到了Message才被清空的,所以我的log也没有打印出来。

    知道了如何重现,可是要怎么修复呢,似乎在greeter上并不能修复,只能去改dde-daemon中LockService,如果文件不存在,就不要发送userChanged的信号。(流程是读取这个文件的信息,和传入的参数进行对比,但是文件是空的,所以被认为不是同一个账户,就发送了信号,也导致了界面上重启,以后无法重现是因为里面已经有内容了)。

    就这样,一个流程很正确,但是表现到界面上时就成了一个bug的问题被解决了。写下这篇内容是为了记录我如何解决对我来说很棘手的问题,其实这个问题并不是很困难,但是对整个工作的流程不是很熟悉,导致浪费了大量的时间在非关键点处理,有空要写一些文档了。

    Friday, August 11, 2017

    其实这个问题影响并不是很大,只是稍微的增加一点点访问速度,缓存这东西有利有弊。

    在写完这篇文章以后,我就不用dnsmasq了,现在用的是github上的Pcap_DNSProxy。用来防止dns污染的。

    根据https://stackoverflow.com/questions/11020027/dns-caching-in-linux 中回答者提供的信息来看,linux发行版是不提供dns解析缓存的,上面提到的nscd也不在deepin的预装列表中,所以我们只能自己动手丰衣足食了。

    首先安装口碑较好的dnsmasq,来为我们提供dns缓存。

    sudo apt install dnsmasq

    如果是deepin最新的2015.4.1版本中安装,安装结束会提醒一个错误,这个错误的解决办法来自https://stackoverflow.com/questions/16939306/i-cant-restart-my-dnsmasq-service-so-my-fog-server-wont-work.
    这个错误似乎是因为/usr/share/dns/root.ds文件更新后结构导致的错误。

    编辑/etc/init.d/dnsmasq,并找到

    ROOT_DS="/usr/share/dns/root.ds"

    if [ -f $ROOT_DS ]; then
    DNSMASQ_OPTS="$DNSMASQ_OPTS `sed -e s/". IN DS "/--trust-anchor=.,/ -e s/" "/,/g $ROOT_DS | tr '\n' ' '`"
    fi

    修改为

    ROOT_DS="/usr/share/dns/root.ds"

    if [ -f $ROOT_DS ]; then
    DNSMASQ_OPTS="$DNSMASQ_OPTS `sed -e s/".*IN[[:space:]]DS[[:space:]]"/--trust-anchor=.,/ -e s/"[[:space:]]"/,/g $ROOT_DS | tr '\n' ' '`"
    fi

    当错误解决以后,我们手动重启一下dnsmasq的systemd服务。

    sudo systemctl restart dnsmasq

    deepin的/etc/resolv.conf来自/etc/NetworkManager/resolv.conf.是一个软连接。我采取的行为是删除这个文件,重新创建。

    sudo rm /etc/resolv.conf

    sudo vim /etc/resolv.conf

    然后写入本地地址当做dns地址。

    nameserver 127.0.0.1

    dnsmasq是一个本地的dns和dhcp服务器,当我们在上面成功启动dnsmasq以后,个人系统中就已经在提供dns服务了,所以本机使用回环地址来表明dns服务器就是本机,所有的dns查询都会发送到本机的dnsmasq中。

    如果需要额外添加dns服务器,做法来自https://wiki.archlinux.org/index.php/Dnsmasq#More_than_three_nameservers.

    创建一个 /etc/resolv.dnsmasq.conf,写入其他dns服务器的地址。

    nameserver 114.114.114.114

    然后编辑 /etc/dnsmasq.conf,找到resolv-file字段,改为

    resolv-file=/etc/resolv.dnsmasq.conf

    然后重启dnsmasq。

    验证的话通过dig命令。

    dig blog.mkacg.com

    通过执行两次来判断,Query time在第二次查询是为0 msec。