• 首页
  • 加入
  • RSS
  • Sunday, September 6, 2020

    This repository only provides the git version of deepin. You can replace the deepin group in the community by installing the deepin-git group.

    The PKGBUILD for all packages are there https://github.com/justforlxz/deepin-git-repo, Each branch saves the corresponding software.

    Before adding this repository, you should first add the key used to sign the packages in it. You can do this by running the following commands:

    wget -qO - https://packages.justforlxz.com/deepingit.asc \
    | sudo pacman-key --add -

    It is recommended that you now fingerprint it by running

    sudo pacman-key --finger DCAF15B4605D5BEB

    and in a final step, you have to locally sign the key to trust it via

    sudo pacman-key --lsign-key DCAF15B4605D5BEB

    More infos on this process can be found at https://wiki.archlinux.org/index.php/Pacman/Package_signing#Adding_unofficial_keys. You can now add the repository by editing /etc/pacman.conf and adding

    [deepingit]
    Server = https://packages.justforlxz.com/

    at the end of the file. See https://wiki.archlinux.org/index.php/Pacman#Repositories_and_mirrors for details.

    to install deepin git version:

    sudo pacman -Syy deepin-git

    If you don’t want to use the repository anymore, you can uninstall deepin git, or install the deepin group in Community.

    sudo pacman -Rscn deepin-git

    to install deepin group for community.

    sudo pacman -S deepin

    Thursday, September 3, 2020

    本文将介绍如何使用VSCode的远程开发套件连接到Deepin主机,进行DDE和其他软件的开发与调试.

    介绍

    Visual Studio Code(简称VS Code)是一个由微软开发,同时支持Windows 、 Linux和macOS等操作系统的免费代码编辑器,它支持测试,并内置了Git 版本控制功能,同时也具有开发环境功能,例如代码补全(类似于 IntelliSense)、代码片段和代码重构等。该编辑器支持用户个性化配置,例如改变主题颜色、键盘快捷方式等各种属性和参数,同时还在编辑器中内置了扩展程序管理的功能。

    在VSCode出来之前,Sublime曾经是前端开发者必备的软件,它使用python作为插件运行环境,并且也拥有不少的插件,但是很遗憾的是插件不能更改界面元素,可玩性不是很高。

    再后来Atom作为GitHub的顶梁柱出现了,它基于使用Chromium和Node.js的跨平台应用框架Electron(最初名为Atom Shell),并使用CoffeeScript和Less撰写,并且支持js开发的插件,一时间拥有非常多的用户,并且从Sublime那里拉拢了非常多的前端开发者。

    但是一切都在VSCode面世以后变了。VSCode同样也是基于Chromim和Electron开发,并且支持TypeScript开发插件,而且启动速度比Atom快很多,而且作为微软面向开源社区的主力产品,它和TypeScript一样,吸收了社区的很多意见和贡献,使得软件越来越好用。在语言支持方面,对 C#、JavaScript、和 TypeScript 等编程语言的原生支持最为完善。

    安装VS Code

    官网提供的有vscode的安装包,windows用户下载stable版本的exe(System Installer)。

    System Installer可以自动下载对应语言的环境包,推荐安装此版本。

    图片

    安装完成后就可以安装插件了。

    安装插件

    插件系统是一个编辑器的左膀右臂,emacs和vim作为终端下开发经常使用的编辑器,就拥有非常丰富的插件,几乎每个大佬使用的emacs和vim都不能互换使用。

    dde的项目几乎都是cmake的项目,所以需要安装cmake插件和c++的插件,安装了这两个插件以后。vscode打开项目工程就会自动解析CMakeLists.txt,并且开启vscode的快速调试功能,还可以开始构建项目和调试项目了。

    图片

    安装CMake、CMake Tools这两个插件就可以开发了。

    图片

    安装C/C++和C++ Intellisense这两个插件可以对项目中的c++代码进行智能感知和代码补全,推荐安装。

    图片

    安装Remote - SSH插件,可以让vscode通过ssh连接到目标机器,打开远程机器的目录和文件,并且在该模式下,部分插件可以自动切换成本地/远程模式,这样就可以在本机直接开发,但是操作的内容都是远程环境的。

    安装完Remote - SSH插件以后,vscode的左下角就会有一个绿色的按钮,可以用来切换模式。

    图片

    配置远程环境

    因为是要在Windows上进行远程开发,如果是直接在UOS或者Deepin上开发DDE,这一部分是可以不用看的,上面的插件安装完成以后就可以开发项目了。

    点击左下角的绿色按钮,在弹出的面板选择Remote-SSH: Connect to Host。

    图片

    会继续弹出一个面板,用来选择配置ssh的连接。

    图片

    选择Add New SSH Host添加一个服务器。

    图片

    输入ssh的命令,例如 ssh [email protected]

    图片

    然后选择一个保存配置的位置,一般默认选择用户家目录的.ssh目录即可。然后就提示添加成功,此时可以点击Connect按钮进行连接。

    图片

    输入密码

    图片

    登录以后会打开一个新的窗口,并提示正在连接。连接成功以后可以在左下角看到机器的信息。

    图片图片

    然后打开命令面板,选择在SSH中安装本地扩展。

    图片

    在打开的列表选择全选,然后安装。

    图片

    等待全部安装成功。

    图片图片

    开发和调试

    功能介绍

    CMake插件提供了编译、运行和调试的功能和命令,可以点击下方面板中的select target,选择要运行的目标程序,选择切换编译模式,可以选择Debug或者Release。还可以选择使用哪个编译器进行构建。

    图片图片图片图片

    设置启动参数

    如果程序启动不需要提供参数,则可以直接点击下方面板的Debug按钮,或者打开命令面板选择CMake Debug Target,如果没有选择过Target,则会询问一次设置Target。

    点击左侧的调试按钮,选择添加配置。

    图片

    在弹出的面板选择GDB

    图片

    此时vscode会创建出一个json文件,并生成了默认的配置文件。

    图片

    我们需要进行一些调整,以便使用该配置文件进行调试。

    program字段是程序二进制文件的位置,一般情况下我们是要手动写好路径,但是如果项目的二进制特别多,更换配置文件就会非常麻烦,而且配置文件里写死路径也不是很方便,我查阅了CMake插件的文档,发现CMake插件提供了两个很重要的变量,可以让我们方便的查找到路径。

    "program": "${command:cmake.launchTargetPath}"

    CMake插件提供了launchTargetPath的变量,它对应的是CMake插件选择的默认target,启动调试之前需要我们先选择好Target。

    "value": "$PATH:${command:cmake.launchTargetDirectory}"

    CMake插件还提供了launchTargetDirectory变量,用于获取程序启动所在的目录,一般需要我们指定到本次调试所需的环境变量中。

    "environment": [
    {
    "name": "PATH",
    "value": "$PATH:${command:cmake.launchTargetDirectory}"
    },
    ]

    然后我们就可以添加启动参数了。
    args字段保存了程序启动会传递的参数列表,例如这里会给fuse传递-d和/tmp/x。

    "args": [
    "-d",
    "/tmp/x"
    ]

    完整的配置如下:

    {
        "name": "(gdb) fuse",
        "type": "cppdbg",
        "request": "launch",
        "program": "${command:cmake.launchTargetPath}",
        "args": [
            "-d",
            "/tmp/x"
        ],
        "stopAtEntry": false,
        "cwd": "${workspaceFolder}",
        "environment": [
            {
                "name": "PATH",
                "value": "$PATH:${command:cmake.launchTargetDirectory}"
            },
        ],
        "externalConsole": false,
        "MIMode": "gdb",
        "setupCommands": [
            {
                "description": "为 gdb 启用整齐打印",
                "text": "-enable-pretty-printing",
                "ignoreFailures": true
            }
        ]
    }

    gdb调试

    此时我们就可以先通过CMake插件构建整个项目,再切换到运行面板,启动调试。

    点击下方面板的Build按钮,构建项目。

    图片

    再点击左侧的gdb fuse(deepin-turbo)按钮,因为配置文件里面我们起的名字是gdb fuse。我们在main函数添加一个断点,用来测试gdb是否工作正常。

    图片

    一切都工作正常,在调试控制台可以使用-exec作为前缀来执行gdb的命令。

    图片

    调试图形程序

    调试图形程序稍微有一些麻烦,因为是远程开发,图形程序又只能工作在目标机器,这里提供两个可行的方案。

    1. synergy之类的键盘鼠标共享软件
    2. 在windows安装xserver

    第一种方案是通过共享本机的键盘鼠标到远程机器,这样就可以在远程环境上面进行直接操作,好处是除了调试,也可以同时操作远程机器进行使用。

    第二种方案是利用X11协议的网络透明,既图形程序和显示服务不一定在同一台机器上运行,我们只需要在Windows安装XServer程序,就可以让远程机器上的程序的画面显示到当前机器,并且可以操作。但是此方案有缺点,虽然设计上这种分离结构设计的很巧妙,但是因为远程OpenGL调用并不支持,所以图形无法调用3D程序渲染,并且和远程机器沟通需要大量的带宽,所以用起来体验并不好。

    为了使用这两种方案,我们都需要在调试的launch.json中添加一个环境变量。

    在运行面板点击齿轮按钮,可以编辑当前方案。

    图片

    在打开的json文件中,找到environment字段,添加DISPLAY环境变量。

    "environment": [
    {
    "name": "DISPLAY",
    "value": ":0"
    }
    ]

    这样程序启动就有DISPLAY环境变量,我们就可以让程序在目标机器的屏幕上运行了。

    图片图片图片

    还有一种自动化测试的方案,该方案是我个人认为所有开发都应该掌握的,通过自动化测试,我们就可以完全使用远程开发来完成开发任务,调试的时候只需要等待自动测试结果返回即可,设想一下,某个模块需要点击很多地方才可以重现一个问题,我们只需要设置好断点,让程序自动开始执行所有函数,并在最终出现问题的地方停下,我们就可以开始手动单步跟踪问题,完全不需要使用鼠标人工点击。(然而理想很美好,现实很残酷,我个人目前都没有掌握自动化测试的方式,现在也是只能通过鼠标点点点来重现问题。

    Thursday, August 6, 2020

    dde 后端使用 go 作为主要的开发语言,使用 dbus 提供接口,主要使用 gsettings 来保存配置。 所以在进行后端开发前需要对以上内容有基本的了解,这里假定本文档的阅读者熟悉 dbus 和 gsettings,并有一定的开发经验。

    安装依赖

    虽然本项目是go语言开发的,但是我们并没有直接使用go的mod作为依赖管理方案,而是走系统包管理器的方式,所以要先安装startdde的编译依赖。

    sudo pacman -Sy golang-github-linuxdeepin-go-dbus-factory golang-deepin-gir golang-deepin-lib golang-deepin-dde-api go git jq golang-golang-x-net golang-github-linuxdeepin-go-x11-client

    这些包会被安装到系统的/usr/share/gocode目录下。还需要手动go get一个依赖到本地的GOPATH中。

    go get -v github.com/cryptix/wav

    设置GOPATH

    为了方便以后的开发,可以将GOPATH环境变量定义到~/.xprofile等文件中,或者shell的配置文件。例如我使用的zsh:

    export GOPATH=$HOME/Develop/Go:/usr/share/gocode
    export PATH=$HOME/Develop/Go/bin:$PATH

    设置项目目录

    go要求项目目录必须在GOPATH中,所以要将startdde放到GOPATH的pkg.deepin.io/dde/目录下,但是GOPATH每次进入不方便,可以采用软链的形式将startdde的目录链接到GOPATH下。

    cd ~/Develop/Deepin
    git clone https://github.com/linuxdeepin/startdde
    mkdir -p ~/Develop/Go/src/pkg.deepin.io/dde/
    ln -sf ~/Develop/Deepin/startdde ~/Develop/Go/src/pkg.deepin.io/dde/startdde

    这样就可以在一个方便的目录进行开发了。

    vscode开发工具

    我个人推荐使用vscode当作开发工具,打开vscode安装go的插件,打开startdde目录,vscode会提示安装一些go的工具,选择全部安装即可。

    Monday, July 27, 2020

    本来打算7月份给dde添加github action验证,但是被各种事情耽误了,然后发现麒麟居然抢在我前面部署了全套的github action,这不能忍,赶紧把dde的github action也提上日程。并且打算听肥肥猫大佬的话,在aur给dde弄一套commit构建包,这样就可以在arch上使用比testing仓库更testing的dde了!

    github actions是github官方出的持续集成功能,以前大家在github上的项目都使用的第三方的Travis CI或者自建jenkins构建,但是github被微软收购以后,微软为了表现出给社区和用户的诚意,将大量github的付费功能免费公开给开发者使用,希望能将github打造成开发者中心,于是在2019年微软推出了免费的github actions,每个项目都可以免费使用官方提供的持续集成和持续部署功能,这对第三方业务无疑是个巨大的打击,虽然Travis CI和jenkins等方式仍然有一定的市场,但是对于中小项目的开源项目,使用官方提供的功能无疑是方便的。

    github actions的配置十分简单,只需要几个简单的步骤就可以实现构建、执行和测试代码。并且可以使用Linux、Windows和MacOS环境,机器性能也十分强劲,编译速度非常的快。

    这是给dde-launcher的一份基础配置,需要将配置文件放在.github/workflows/目录下,以build.yaml文件名保存。

    name: CI Build

    on:
    push:
    branches:
    - UOS

    pull_request:
    branches:
    - UOS

    jobs:
    archlinux:
    name: Archlinux Build Check
    runs-on: ubuntu-latest
    container: docker.io/library/archlinux:latest
    steps:
    - name: Checkout branch
    uses: actions/checkout@v2
    - name: Refresh pacman repository
    run: pacman -Syy
    - name: Install build dependencies
    run: pacman -S --noconfirm base-devel cmake ninja qt5-tools deepin-qt-dbus-factory dtkwidget
    - name: CMake & Make
    run: |
    mkdir build
    cd build
    cmake ../ -G Ninja
    ninja

    介绍一下配置文件吧,name是设置ci的名字,github允许有多个ci存在,可以做不同的事情,例如部署三个ci,一个做语法检查,一个做静态检查,一个做编译检查。name就是用来在界面上显示的。on是设置ci对哪些事件感兴趣,在这里我设置了push和pull_request,当发生push和pull request时,这个ci就会被启动,执行接下来的jobs的内容。jobs里是可以设置多个任务的,同样name字段也是用来展示本次动作的名称。runs-on是设置该job工作的环境,ubuntu-latest是linux环境,container是指使用哪个docker容器,github actions是可以使用docker的,也可以将自己的ci配置共享给其他人使用。run就是执行命令了,在配置文件中我手动运行了刷新仓库和编译项目所需的命令。job的steps可以理解成shell中一次动作的执行,uses是使用其他人封装好的命令,run则是执行本地命令。

    可以看出github actions的配置是十分简单的,并且构建速度也非常的快,并且构建环境是使用的arch linux环境,为什么要选择arch作为ci的基础构建环境呢,原因当然不是因为和肥肥猫有py交易,arch上的dde更新速度很快,并且很多用户都使用arch+dde的方式使用linux,deepin自己维护的发行版因为基础仓库更新较慢,不适合一些用户,所以为了能让dde被更多的人接受和使用,在arch上及时更新dde是十分有必要的。所以才选择actions的环境为arch linux。

    Tuesday, July 21, 2020

    最近在对DDE进行性能优化,所以补习了一下linux下的各种分析工具的使用方法。

    bpf_performance_tools_book

    这张图是来自Brendan Gregg大佬提供的linux分析工具的应用场景,可以看出几乎包含了系统每个地方应该用什么工具去分析。

    Linux Perf Tool

    允许系统进行分析

    为了能够正常分析,首先需要打开系统的调试功能,允许我们去对其他进程进行访问。

    SysCtl

    较新的Linux内核具有sysfs可调参数/proc/sys/kernel/perf_event_paranoid,该参数允许用户调整perf_events非root用户的可用功能,数量越大则越安全(相应地提供较少的功能):

    Consider tweaking /proc/sys/kernel/perf_event_paranoid:
    -1 - Not paranoid at all
    0 - Disallow raw tracepoint access for unpriv
    1 - Disallow cpu events for unpriv
    2 - Disallow kernel profiling for unpriv

    默认值是不允许获取任何信息,所以我们需要修改为1或者0,允许我们访问CPU的事件信息。

    • 临时修改

    执行命令向内核接口直接写入值。

    sudo tee /proc/sys/kernel/perf_event_paranoid <<< 1
    • 永久修改

    使用sysctl来配置其值,创建/etc/sysctl.d/50_perf_event_paranoid.conf文件,并写入kernel.perf_event_paranoid=1,执行sysctl -p来刷新系统配置。

    perf 采样

    性能优化相关的三种类型的工具,一种是sampling类型的,即采样,这种工具就是不停“询问”程序在做什么,perf在我们使用的这种模式下就是 sampling模式,如果是追踪某些event,就工作在trace模式,实际上就是第二种类型的工具,这种工具主要依靠事件或者hook,程序在运行的过程中不停主动告诉工具它自己在做什么,比如 strace;第三种是 instrument 类型的,这种主要就是依赖编译器进行插桩,精确知道代码行级别的执行情况(参考gcc instrumentation )。

    by hualet on deepin 15.7

    我们通过perf record命令才对程序进行采样记录。

    perf record -g --call-graph=dwarf -F 99 /usr/bin/dde-shutdown

    命令介绍:

    -g: 即采样全部信息
    --call-graph: 设置并启用调用图(堆栈链/回溯)记录,参数有fp(frame pointers)、dwarf(debug information)和lbr(Last Branch Record)。
    -F: 采样率

    perf可以直接启动一个程序进行分析,也可以使用-p参数指定一个pid进行采样。

    查看 perf 的采样结果

    当我们通过perf record完成采样以后,会在执行目录生成perf.data文件,此时我们就可以使用perf report命令对data文件进行数据分析了。

    perf report --stdio

    perf report会自动打开当前目录下的perf.data文件,当然也可以在最后指定perf.data文件的路径。

    perf report会根据–call-graph参数来生成不同的图,使用dwarf参数时会以函数调用栈的顺序来显示,使用这种方式可以方便的看出哪个函数执行的时间比较长,因为每次采样都能落到该函数上,也就意味着函数执行的时间非常长,再通过调用栈的深度来分析函数执行期间都在做什么事情。

    hotspot火焰图

    在命令行下查看函数调用不是特别方便,所以就有图形化的工具用来方便的查看perf工具的生成结果,其中使用比较友好的是kde开发的hotspot工具,该工具可以直接打开perf.data文件,并生成对应的火焰图,火焰图是函数调用的另一种表现形式,火焰越高,也就意味着调用栈越深,火焰越广,也就意味着函数执行的时间很长。

    Wednesday, January 1, 2020

    上一次写年终总结还是18年回家的动车上,可惜写了一半没发表,觉得一年了没有什么能够回想起来的,就又删除了。今年不同了,今年有好多想说的。

    脱单

    第一件重要的事是我遇到了生命中的她。

    自从工作以后,我妈天天念叨我的就是找对象,和我预想的没错,上学的时候盼我毕业,毕业以后盼我工作,工作以后盼我找对象结婚,找对象以后盼我赶紧生个娃让她抱。(大家的父母应该都这样)

    加薪

    这件事确实也令我挺开心的,我的工资在2019年成功涨到了0.375乔(1乔等于**元 @nanpuyue)

    涨工资谁不高兴,我估计也就马云不高兴了,毕竟他看不上钱。

    学习

    今年看了很多C++的资料,对C++和编译器都有了更深的了解。想2016年半夜@zccrs在家教我编译原理,到现在我可以理解一门语言从设计到实现,再到使用模板完成编译时计算,我走了快三年,这三年里我一直没停下学习的脚步,在学习各种知识,从各种编程语言到各种框架原理,到图形界面的实现。还学习了单元测试,并且@hualet大佬给我讲了单元测试是什么,以及单元测试的重要性,从那以后我才算真正的了解单元测试的重要性,也使我在写代码的时候注重通过单元测试来保障我的功能。

    去年对深度学习进行了一波学习,今年对Web工程化和TypeScript也学习了一下,也算是对目前最热门的两个领域进行了一定的了解。

    读书

    去年买的TensorFlow看了没一半,今年倒是没买书,开始在微信读书上读书,利用一些空余时间读一点,我也推荐大家多利用空闲时间读读书,少刷抖音和bilibili。

    • 《TensorFlow》未读完
    • 《TypeScript实战》正在读

    博客

    2019年我一共水了15篇文章。

    2019
    ├── 01
    │   └── 23
    │   └── fuck-taobao
    │   └── index.html
    ├── 02
    │   └── 21
    │   └── how-to-use-LNMP-on-deepin
    │   └── index.html
    ├── 05
    │   └── 23
    │   └── CMake-CTests-for-dde-control-center
    │   └── index.html
    ├── 06
    │   ├── 15
    │   │   └── 入坑typescript了
    │   │   ├── 深度录屏_选择区域_20190615202044.gif
    │   │   └── index.html
    │   └── 16
    │   └── wsl2的使用体验
    │   ├── index.html
    │   ├── Snipaste_2019-06-16_21-49-15.png
    │   └── Snipaste_2019-06-16_21-52-42.png
    ├── 10
    │   ├── 14
    │   │   └── webpack入门
    │   │   └── index.html
    │   ├── 22
    │   │   └── 使用webpack打包Vue和TypeScript
    │   │   └── index.html
    │   └── 24
    │   └── 给Archlinux开启BFQ和MuQSS
    │   └── index.html
    ├── 11
    │   └── 25
    │   └── 使用webpack-dev-server来监听项目变化
    │   └── index.html
    └── 12
    ├── 08
    │   ├── vue-component-props
    │   │   └── index.html
    │   └── vue-transitions
    │   └── index.html
    ├── 09
    │   ├── 记录一个坑爹的usb网卡
    │   │   └── index.html
    │   └── use-github-actions-to-depoly-hexo
    │   └── index.html
    └── 26
    ├── cpp-sort
    │   └── index.html
    └── use-serial-port-debug-deepin-on-archlinux
    └── index.html

    34 directories, 18 files

    科普视频

    1. 妈咪叔 (一个较真的理工男)

    这个名字我第一眼看到的时候,还以为是个卖母婴的,没想到居然是个搞科普的,而且内容讲的也很好,有数学、物理、化学和天文学。

    1. 李永乐老师

    以前偶尔看过老师的视频,因为一直都在热榜,所以没想到关注,后来是youtube上看到了,就点了关注,youtube上更新的和bilibili的还不是一样的,看最后结尾的时候youtube的只说youtube帐号关注,而bilibili的是bilibili,有时候还要多个平台去看。

    1. 萝王二号

    之前在科普区随便看的时候,对生物学产生了一些兴趣,萝王讲的风格我很喜欢,特别是他注重昆虫分类学(骨包皮,皮包骨啊2333),还有一些辟谣视频。

    1. 芳斯塔夫 (鬼古)

    也使对生物学产生了一些兴趣,鬼古说以他很中二的风格带领我学习了一波古生物的相关知识(旧日支配者!!!)。

    1. 木偶君

    和鬼古一样是专门讲古生物的,不过每次结束的比较仓促,突然就结束了。

    1. 木鱼水心

    木鱼并不是今年才关注的,最开始关注是他做EVA剧场版解析,后来《木鱼说》开始做一些科普,我开始一直关注了。

    1. 宇宙视觉 (永远不要停止思考)

    一个讲天文的科普up,不过年底的时候换了配音,疑似配音出去单干了。

    电影

    1. 流浪地球
    2. 阿丽塔:战斗天使
    3. 战狼2
    4. 惊奇队长
    5. 复仇者联盟4
    6. 何以为家
    7. 速度与激情: 特别行动
    8. 叶问4

    纪录片

    1. 混沌:数学探秘
    2. 维度:数学漫步

    动漫

    1. 刀剑神域
    2. 紫罗兰永恒花园
    3. darling in the franxx
    4. 心理测量者
    5. 进击的巨人第三季
    6. 五等分的新娘
    7. citrus~柑橘味香气~

    Thursday, December 26, 2019

    电脑主板上的接口:进行串行传输的接口,它一次只能传输1Bit。串行端口可以用于连接外置调制解调器、绘图仪或串行打印机。它也可以控制台连接的方式连接网络设备,例如路由器和交换机,主要用来配置它们。消费性电子已经由USB取代串列接口;但在非消费性用途,如网络设备等,串列接口仍是主要的传输控制方式。

    首先给虚拟机分配一个串口设备,选择Settings->Add->Serial Port。分配好串口设备以后,我们需要选择一个串口设备的调试方式,一个是将输出转向一个文件,或者是通过socket。

    如果只是查看方式,选择outpu file即可。如果需要调试,则可以通过socket方式来进行。

    socket方式需要给一个固定的路径分配/tmp/,我调试的时候给出的是/tmp/vhost,From选择Server,To选择An Application。From的意思是信息从哪里来,信息是虚拟机里的系统发出的,所以这里选择的是Server,如果是反向操作,需要选择Client。To也是有两个选项,第一个是An Virtual Machine,第二个是An Application。用于把消息发送给另外的虚拟机,或者是宿主机的一个应用程序。

    安装minicom包,用于进行调试,minicom这个东西,不是太好用,退出方式是先按Ctrl+A,然后按q,有时候还不一定管用,不知道是没接受到,还是按错了。

    先minicom -s 进行初始化,选择Serial port setup,按A编辑Serial Device,这里需要注意一下,通过socket进行调试,需要使用unix#前缀,然后加上在虚拟机里写的路径 unix#/tmp/vhost。然后保存,选择Exit,退出以后其实重启minicom,就进入minicom的调试界面了,然后此时开启虚拟机,给内核添加一个console=ttyS0的参数,就看到minicom显示输出的信息了,还可以交互。

    [    3.855725] [drm:vmw_fb_setcolreg [vmwgfx]] *ERROR* Bad regno 254.
    [ 3.857125] [drm:vmw_fb_setcolreg [vmwgfx]] *ERROR* Bad regno 255.
    deepin Login:

    CTRL-A Z for help | unix-socket | NOR | Minicom 2.7.1 | VT102 | Offline | unix#/tmp/vhost

    此时就可以交互了,用法和tty一样,最后一行是minicom的输出,可以看到CTRL-A Z可以看help,minicom的版本,和访问的串口socket。

    Tuesday, September 3, 2019

    还记得刚推出屏幕保护功能那会儿,我偶逛论坛,围观大家对这个功能的评价。其中让我印象最深的一句话就是:“一股Windows98风”,总之,评价总结出来就是一个字:“吃藕”。

    大家追求美好事物的诚挚之心深深地打动了我,而且,我个人做事情的风格是喜欢未雨绸缪,在屏幕保护程序开发之初,就已经定好了易于扩展的架构,所以我当时就下定了决心,为大家开发一个非Windows98风格的屏保。

    为了达到绝对“非Windows98”的目的,我特意选择了Windows10中的默认屏保作为参考,在无数个周末的战斗下,最终成功将名为“泡泡”的屏保应用发布到了商店(项目地址:https://github.com/zccrs/screensaver-pp )。

    本着“授人以鱼不如授人以渔”的理念,特地整理了这篇文章协助大家开发一款属于自己的时尚屏保应用。

    正文

    在Linux+X11生态环境中,xscreensaver是最“流行”的屏幕保护程序,有着非常多的屏保资源,所以deepin-screensaver必然要兼容它的资源。

    但是,xscreensaver对屏保资源的扩展方式并不符合deepin的开发理念,因此,deepin-screensaver实现了一套全新的屏保扩展方式。

    支持使用Qt qml模块编写屏保应用,一个标准的屏保应用只需要包含一个 “xx.rcc” 文件,将文件安装到 /usr/lib/deepin-screensaver/resources目录。

    rcc 格式是一个编译之后的Qt资源文件,在这个资源文件中至少要包含两个文件:qml代码文件、屏保封面图。

    image

    图中文件名括号内为其别名,也就是屏保主应用加载文件时能读取到的文件名。

    • qml代码文件:屏保应用的代码入口,会被屏保主程序加载显示

    • 屏保封面图:设置屏保入口显示的预览图,支持svg png jpeg bmp等格式 所有的文件必须以特定的目录结构组织到一个Qt资源文件(qrc文件),以“泡泡”屏保为例:qml.qrc 为其资源文件,包含三个前缀路径

    • /deepin-screensaver/modules:放置屏保应用的主qml文件,此路径下的所有qml文件都会被当做一个独立的屏保应用,因此,项目中的其它文件需要额外建立新的前缀放置

    • /deepin-screensaver/modules/cover:放置屏保应用封面图文件,文件名称必须和modules目录中的qml文件一致,且包含它的 “.qml” 后缀。如图上,qml文件全名为:“pp.qml”,封面图全名为:“pp.qml.svg”。

    • /deepin-screensaver/modules/pp:此前缀不是必须的,用于放置项目中的其它文件。为了不与其它项目产生冲突,建议使用项目名作为目录名称 资源文件最好以项目名称命名,避免和其它屏保应用冲突。另外,大家可能已经发现了,这三个前缀都有一个共同点,那就是以 “/deepin-screensaver/modules"开头,的确,这是一个格式要求,不能随意更改路径。

    主qml文件作为屏保应用的入口,它的根元素一定要设置

    anchors.fill: parent
    

    这样才能确保屏保应用充满整个屏幕。在多屏的情况下下,会创建多个窗口示例,可根据屏幕绘制不同的屏保内容。 项目编译其实很简单,只需要使用Qt提供的rcc命令将qrc文件编译为rcc文件即可,使用qmake构建系统时,可以在pro文件中调用以下命令:

    system(rcc --binary $$_PRO_FILE_PWD_/xx.qrc -o $$_PRO_FILE_PWD_/xx.rcc)
    

    当然,最后不要忘记将 xx.rcc 文件安装到deepin-screensaver所要求的目录。做完这所有的步骤后,回到桌面,在右键菜单中选择“壁纸与屏保”,切换到屏保设置后即可看到新添加的屏保应用。 另外,deepin-screensaver为qml提供了获取当前屏幕截图的接口,只需要为Image项指定特定的路径即可:

    Image {
        anchors.fill: parent
        source: "image://deepin-screensaver/screen/" + Screen.name
    }
    

    由于要获取屏幕名称,上述代码需要 “import QtQuick.Window 2.2” 使用

    后记

    屏保封面图最佳比例为:8:5,推荐使用svg格式,以更好的适应高分屏缩放。

    推荐大家使用Qt Creator作为项目的开发工具,可以方便的编辑 qrc 文件。

    泡泡屏保是一个完整的demo,有任何疑问的地方都可以以其作为参考

    参考

    Thursday, February 21, 2019

    为了节省读者的时间,我先简述一下阅读这篇文章需要了解的知识。

    这篇文章将基于Docker来构建nginx、php和mysql来搭建LNMP环境,和其他教程有所不同的是,需要有一定的Docker基础。

    Docker是一个不错的工具,使我们不需要虚拟机那样的庞然大物就可以轻松的隔离运行的程序,这要感谢Linux的资源分离机制,避免启动一个虚拟机造成了大量资源浪费。

    首先需要在Deepin上安装Docker,添加Docker的deb仓库,并安装docker-ce。

    创建文件

    sudo nano /etc/apt/sources.list.d/docker.list

    写入

    deb [arch=amd64] https://download.docker.com/linux/debian jessie edge

    刷新一下仓库就可以安装了。

    sudo apt update && sudo apt install docker-ce docker-compose

    安装完成后重启一下系统,准备工作就算完成了一半了。

    在家目录创建一个Projects目录,当做我们LNMP的工作目录,创建一个名叫docker-compose.yaml的文件,这是docker-compose的配置文件,我们通过docker-compose这个工具来管理我们的Docker容器。

    所有的镜像均采用最新版本,nginx(1.15.8),php(7.3.2),mysql(8.0.15),如有需要,自行选择不同版本的镜像。

    注意PHP7已经不支持mysql扩展,使用内置的MySQLnd。

    写入以下配置文件:

    version: '3'

    services:
    nginx:
    # 设置容器名字
    container_name: "nginx"
    # 采用最新的nginx
    image: nginx:latest
    # 绑定80端口
    ports:
    - "80:80"
    # 添加php容器的依赖
    depends_on:
    - "php"
    # 绑定数据目录
    volumes:
    - "./volumes/nginx/conf.d:/etc/nginx/conf.d"
    - "./volumes/html:/usr/share/nginx/html"
    restart: always

    php:
    # 设置容器名字
    container_name: "php"
    # 采用最新的php
    image: php:fpm
    # 绑定端口
    ports:
    - "9000:9000"
    # 绑定数据目录
    volumes:
    - "./volumes/html:/var/www/html"
    restart: always

    mysql:
    # 设置容器名字
    container_name: "mysql"
    # 采用最新的mysql
    image: mysql:latest
    # 绑定端口
    ports:
    - "3306:3306"
    # 设置环境变量
    environment:
    - MYSQL_ROOT_PASSWORD=(自己设置密码)
    # 绑定数据目录
    volumes:
    - "./volumes/mysql:/var/lib/mysql"
    restart: always

    创建nginx的配置文件,编辑 ./volumes/nginx/conf.d/nginx.conf

    server {
    listen 80;
    server_name localhost;
    location / {
    root /usr/share/nginx/html;
    index index.html index.htm index.php;
    }
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    root /usr/share/nginx/html;
    }
    location ~ \.php$ {
    fastcgi_pass php:9000;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME /var/www/html/$fastcgi_script_name;
    include fastcgi_params;
    }
    }

    创建php测试文件,编辑 ./volumes/html/index.php :

    <?php
    phpinfo();
    ?>

    启动docker,第一次需要拉取一下镜像:

    docker-compose up --build -d

    等全部结束以后,就可以访问localhost看到php的信息了。

    通过Docker的方法来使用LNMP,不污染宿主机环境,不会再因为各种依赖问题而搞坏系统,这恰恰是新手容易犯的错误,使用Docker,方便你我。

    Monday, December 17, 2018

    头段时间入了一个大坑儿,大概被坑了有一个月之久,出来之后同事还不忘嘲讽一番:”这么个事情就搞了一个月,看吧,你果然是老了“。听了这句话,心里真是百般滋味,但转念一想,”我年轻的时候做事好像也不怎么快“,顿时也就释怀了 🙂

    这个坑就是”给 FreeRDP 的 RAIL 模式添加托盘支持“,当然,跟所有的需求一样,这么具有总结性而又直指根源的需求描述,绝对不是它最原始的模样——我刚接到这个坑的时候,它是这样的:FreeRDP 的 RAIL 模式下,应用的托盘在我们 DDE 下不显示。请注意这里说得是不显示,而不是后来发现的压根儿没有支持

    FreeRDP

    说到这,可能有读者还不了解 FreeRDP 和 RAIL,所以先简单介绍一下。

    RDP 其实是一个协议名称,全称 Remote Desktop Protocol(远程桌面协议),是微软公司开发的一套用于远程桌面展示和操作的协议,FreeRDP 就是它在开源世界的实现咯。而 RAIL 的全称是 Remote Application Integrated Locally (远程应用本地集成),其实就是非常类似大家熟悉的虚拟机的”无缝模式“,通过将应用的显示跟本地环境相融合,让用户完全感受不到这个应用其实不在本机运行——就是这么一种技术。

    问题也就出在这,我当时第一反应是这么老的技术实现肯定比较完整了,托盘没有显示出来应该是跟 DDE 的兼容性有点小问题,稍微修一下就完了,三下五除二的事情,所以满口答应了下来……

    经过

    既然答应了,硬着头皮也要顶下去的。何况调 BUG 这种事情——不管是不是我们自己的问题——在深度都是家常便饭。慢慢地,调各种项目的 BUG 竟然成了我的一种乐趣——每次开始接手一个新的项目的时候,我都把自己当成了福尔摩斯或者胡八一,或者也可以是其他全世界最聪明的那类人 ?,在通过代码找寻问题线索的过程中,慢慢成为这个项目世界中的主宰,解开真相……

    额……不好意思,白日梦又发作了一会儿。总之,这次也不例外,而且刚好这次在调问题的过程中有记录几个关键环节,所以打算把中间的过程写成日记性质的记录,看看能不能有更好的阅读效果:

    2018-11-14

    从”沈老板“那收到需求,说 FreeRDP 在我们系统上有问题,应用的托盘显示不出来,QQ之类的程序关闭了窗口以后就没办法显示出来了,无法使用。这丫的又拿刘老大来压我……呵呵,想削他。不过看在他快要当爸爸的份上,还是算了。问了下时间要求,大概需要两周左右有初步的结果。不过我自己最近没有什么时间,先把锅丢给了印象中还比较熟悉网络协议的 @Blumia 同学。

    2018-11-15

    从 @Blumia 那收到反馈,可能 FreeRDP 没有实现托盘图标这部分的功能,我怕他一个人搞不定,简单翻了翻 FreeRDP 的项目 wiki 和 RDP 的一些介绍,给了他,让他先帮忙找一下需要补充实现部分的代码结构。

    2018-11-16

    没时间处理。

    @Blumia 搭了测试环境。

    中间几天两人都没有时间处理 FreeRDP事情。

    2018-11-22

    留了少部分时间,看了 FreeRDP 的代码,大概找到了托盘图标相关处理应该在的位置。

    • RAIL 主要接口的实现都在 xf_rail.c 中。
    • 托盘图标相关的处理在 xf_rail_no``t``ify_icon_* 相关的函数,这些函数在 xf_rail_re``gi``s``t``er_``u``pdate_call``b``a``c``ks 里面被注册到 rdpWind``o``wUpdate 对象上。
    • 部署了一份测试服务器的虚拟机。
    • 在 wf_rail.``c 中发现一个 PrintRailI``c``onInfo 函数,放在 xf_``r``ail_notify_i``c``on_common 中打印了获取到的图标的信息,发现能正常获取一些图标的数据。
    • xf 应该是 x11 freerdp 的缩写,而 wf 应该是 windows freerdp 的缩写。 中间又是几天没有时间处理 FreeRDP 的事情。

    2018-11-27

    有半天的时间看 FreeRDP 的代码,同时跟 FreeRDP 的邮件列表发了邮件询问相关技术问题,主要是为了验证自己的想法,没有指望有回复或者什么比较大用处的信息,只是希望如果自己想法是错的,有人及时纠正一下。

    • 图标显示的问题不打算优先处理,现在的问题变成如何让服务端知道了本地用户点了托盘图标。
    • 搜了一下 event 相关的文件,发现 x``f_event.c ,怀疑 X 相关的事件都是在这里面处理的,这个也不用急着去证明,先看看 client 怎么让 server 感知本地的事件。
    • 没有头绪,只好看了一下 RAIL 的 主要协议,发现 Cli``e``nt Notify Ev``en``t
    • 怀疑托盘图标在 client 端(本地端)的事件是通过 ClientNotifyEvent 发送给 server 端的。
    • ClientNotifyEvent 相关:
      • rail_main.``c 中的 Vi``r``tualChann``e``lE``n``tryEx 应该是 RDP 中 RAIL 相关的 channel 处理的函数。

    2018-11-28

    上午继续看了 FreeRDP 的代码。

    • V``i``rtualCha``n``nelEntryEx 中给 RailClientContext 设置的哪些成员函数,有些函数(Server开头的)都是需要真正的 client 去实现的,Client 开头的函数(包括 ClientNotifyEvent)都是默认有实现,但是这些 Client 开头的函数都是在哪调用的呢? 找到重要线索:
    /**
    * The position of the X window can become out of sync with the RDP window
    * if the X window is moved locally by the window manager.  In this event
    * send an update to the RDP server informing it of the new window position
    * and size.
    */
    void xf_rail_adjust_position(xfContext* xfc, xfAppWindow* appWindow)
    {
    RAIL_WINDOW_MOVE_ORDER windowMove;
    
    if (!appWindow->is_mapped || appWindow->local_move.state != LMS_NOT_ACTIVE)
        return;
    
    /* If current window position disagrees with RDP window position, send update to RDP server */
    if (appWindow->x != appWindow->windowOffsetX ||
        appWindow->y != appWindow->windowOffsetY ||
        appWindow->width != appWindow->windowWidth ||
        appWindow->height != appWindow->windowHeight)
    {
        windowMove.windowId = appWindow->windowId;
        /*
         * Calculate new size/position for the rail window(new values for windowOffsetX/windowOffsetY/windowWidth/windowHeight) on the server
         */
        windowMove.left = appWindow->x;
        windowMove.top = appWindow->y;
        windowMove.right = windowMove.left + appWindow->width;
        windowMove.bottom = windowMove.top + appWindow->height;
        xfc->rail->ClientWindowMove(xfc->rail, &windowMove);
    }
    }
    
    • 其中有主动调用 RailClientContext 的 ClientWindowMove 函数。这个函数又是 xf_``e``v``en``t.``c 中 xf_``e``v``en``t_C``o``nfig``u``r``e``Notify 有调用,再加上这个函数的注释说明,差不多能证明所有的 X事件相关的都是在 xf_event.c 中处理的,跟之前的猜测一致。
    • 那样的话如果想发送事件到 server,应该就是在 xf_event.c 中收到我们自己创建的托盘图标的点击事件后,发送一个 ClientNofityEvent 。 尝试在收到 xf_r``a``il_``no``ti``f``y_``i``con_u``p``d``a``te 的时候主动调用一次 Cli``ent``NotifyEvent 看看会发生什么。
    RAIL_NOTIFY_EVENT_ORDER notifyEvent;
    notifyEvent.windowId = orderInfo->windowId;
    notifyEvent.notifyIconId = orderInfo->notifyIconId;
    notifyEvent.message = NIN_SELECT;
    
    xfContext* xfc = (xfContext*) context;
    xfc->rail->ClientNotifyEvent(xfc->rail, &notifyEvent);
    
    • 选择 message 为 NIN_SELECT 是因为根据 r``ail.h 里面仅有的零星注释,只能推测这个可能是针对托盘的。
    • 试了下,没有任何反应。尝试换成 NIN_KEYSELECT ,更不行。
    • 硬着头皮又翻了一下协议,发现 Notificat``i``o``n``I``c``on Info``r``mation 这段,随便翻了一下,看起来没有有用信息。
    • 偶发奇想搜了一下 select 关键字想看一下这个到底是什么意思,偶然发现 Cli``en``t Notify E``ve``nt PDU 这一节(能跟源码 r``ai``l``.h 里面的一些注释对应上),里面有 WM_LBUTTONDOWN 、 WM_LBUTTONUP 等针对托盘图标的动作定义。
    • 真是对自己做事情毛毛躁躁的行为无语了,要不是心血来潮,差点就错过这么重要的信息。
    • 把 message 改成 WM_LBUTTONDOWN 和 WM_LBUTTONUP ,满怀期待。
    • 测试还是无效果……仍旧不死心,怀疑测试程序(@Blumia 同学搞的一个音乐程序)的稳健程度。
    • 使用 TIM 再试,还是不行,不能唤出主窗口。
    • 感觉走进了死胡同。

    2018-11-29

    继续看 FreeRDP 的问题,主窗口隐藏后不能显示的问题太奇怪了,得找一个简单点的程序,排除复杂影响。

    • 让 @zccrs 写了一个简单的窗口程序,定时隐藏、显示窗口。
    • 发现程序窗口隐藏后无法再显示出来……
    • 赶紧给上游报了一个 issue ,希望上游能修复。但是也不能期望上游很快能修复这个问题,所以自己还是尝试看代码……
    • 上游回复还挺快的,但是对方好像是 FreeRDP 目前的维护者,说自己对 RAIL 这部分协议本身还不是特别熟悉。
    • 不能依赖的上游不是好上游,继续看代码,发现在窗口的显示隐藏主要是通过 WINDOW_STATE_ORDER 中的 s``h``o``wState 控制的,处理的函数是 xf_``r``ail_window_``c``o``m``mon ,里面调用了 xf_ShowWin``d``ow 这个函数,但是这个函数在该显示窗口的时候只是调整了一下窗口的最大化、最小化状态,并没有 Map 这个本地窗口。
    • 加了 XMapW``in``dow(xf``c``->di``s``pl``a``y, appWi``n``dow->ha``n``dl``e``) 这行,满心期待 bugfix。
    • 编译代码测试,发现窗口连关闭都不能关闭了……
    • xfContext 的 appWindow 是本地窗口的一个抽象表示。

    2018-12-03

    觉得这个事情没有什么太大的希望了,不过既然已经知道托盘图标的显示方式和事件的发送,但是没有实际实现,到时候”沈老板“来问,也不好说都是在脑子里,干脆先把之前测通但是没有实现的内容实现一下。

    • 托盘窗口加好了,事件也都加上了。
    • 眼看着都快要完美了,就差那么一点问题没有解决,实在是不甘心,继续死磕那个问题。
    • 尝试了各种手段调试,跟整个程序的命令传递,都没有能解决问题。

    2018-12-04

    调试了一天,一遍又一遍看窗口事件,一点一点排除事件处理函数,终于发现了上游犯的一个低级错误,我很怀疑当时作者有没有测试一下 🙁

    做了修复,提交了 PR,并且顺利合并。

    心情终于舒畅了。

    中间有事请假一天

    2018-12-06

    托盘图标也画上了,不过怎么感觉颜色有点偏。

    调了一下颜色的格式(RGBA -> BGRA),图标显示正常了。

    事情终于告一段路了。

    结束

    折腾了这么长时间,事情终于搞定了,这应该是最近一年里面时间拉的最长的 BUG 了。

    实现算是完了,也能使用。但是还有一些细节没有特别完善,已提交提交到上游 一个新PR ,希望能早日合并造福一方用户。

    感想

    感觉我之前对 wine 有偏见,一直比较拒绝使用(或者大量使用)wine 的东西,但是实际上在修复 FreeRDP 的过程中,我竟然觉得这也是一种不错的解决方案……仔细想想,还是 wine 方便一点,至少不需要依赖一个服务端。

    准备入坑 wine 啦 ~(≧▽≦)/~