• 首页
  • 加入
  • RSS
  • Tuesday, September 8, 2020

    今年的七夕,我老婆给我买了一台surface laptop 2代,8G内存 + 256G存储版本,我也成功的用上了田牌的机器。

    2020/09/17更新: 不知道为啥,反正是开了对内核签名以后,哪怕是BIOS关闭了安全启动,仍然出现mkinitcpio会卡在autodetect上,无奈全部都删掉重来了,没有弄签名,希望各位看到本文章以后解决了这个问题能回复一下,谢谢。

    surface默认是开启了安全启动(Microsoft签名)和bitlocker来保障设备和系统安全,我作为一个linux系统的开发者,当然是需要在surface上装一个linux了,但是前两年zccrs已经踩过坑了,linux不识别surface键盘,同样的触摸、网卡、声卡等设备也工作的不是很正常,本来以为我要开启远程开发的生活了,还特意写了一篇《使用VSCode远程开发DDE》,来给公司里有同样烦恼的人,让他们也感受一下远程开发的魅力。

    苍天不负有心人,我成功的!

    我成功的使用上了ArchLinux,并且工作的十分良好。这多亏了github上的一个组织linux-surface,有这么一些人,他们付出劳动来让手里的surface设备也用上linux,并且要和普通的x86兼容机一样工作,感谢他们的付出,也让我吃上了螃蟹,安装的过程我就不在这里详细说了,其实非常简单。

    首先因为surface只有一个usb口,而键盘并不能工作,所以需要一个usb的扩展器。先按fn+f6进bios关闭掉安全启动,修改引导顺序为usb优先,之后就是正常的安装系统,但是不需要安装仓库里的内核,我们需要安装linux-surface提供的仓库里的内核。

    这些都是非常正常的步骤,linux-surface提供了自己的仓库和内核,我们正常使用即可。

    这里开始就是我研究了半天的内容, 开启安全模式!

    首先我看了一下arch wiki上有关于安全启动的内容,写的挺详细的,就是看不懂。讲了各种的知识点,各种签名的方式,但是真正到我开始用的时候,我是一直失败的,失败的方式我就不说了,直接说我如何成功的。

    首先我放弃了grub,一个原因是grub的安全启动我一直没有尝试成功,另外一个是我只有一个系统,没必要用grub。我换成了rEFInd来作为我的bootloader,首先安装rEFInd的引导。

    yay -S refind shim-signed sbsigntools
    sudo refind-install --shim /usr/share/shim-signed/shimx64.efi --localkeys

    来解释一下上面两条明令。第一个是安装必要的软件包,refind是bootloader本体,shim-signed是aur里面的用于安全启动的包,shim提供了一种并行的安全启动验证功能,我们使用它来启动refind的efi,再通过refind的efi启动内核,达到终极套娃启动。sbsigntools是用于给文件签名的工具,我们安装完refind以后,refind会帮助我们生成一份默认的key,我们需要使用这个key来为内核进行签名。

    在执行第二条明令以后,会有几次询问,都选择Y回车就行。

    然后使用sbsigntools来对内核进行签名。

    sudo sbsign --key /etc/refind.d/keys/refind_local.key --cert /etc/refind.d/keys/refind_local.crt --output /boot/vmlinuz-linux-surface /boot/vmlinuz-linux-surface

    准备工作已经进行一半了,我们只需要写一下refind的配置文件,就可以启动了。

    refind的配置文件有两个地方,一个是boot分区下面的refind_linux.conf,还有一个是在efi分区里的EFI/refind/refind.conf,我们需要修改的是后者。

    默认配置文件都是注释的,其实我们全部删了就可以了,有需要修改的地方去看原始文件或者文档就行了。

    添加一个menuentry,就可以启动系统了。

    also_scan_dirs +,ArchFS/boot
    dont_scan_dirs ESP:/EFI/boot,EFI/boot
    dont_scan_files shim.efi,MokManager.efi,fbx64.efi,mmx64.efi,shimx64.efi
    scan_all_linux_kernels false

    menuentry "Arch Linux" {
    icon /EFI/refind/icons/os_arch.png
    volume 8B131F77-62D7-4B4A-82D4-B60D7ACA2F6C
    loader /ArchFS/boot/vmlinuz-linux-surface
    initrd /ArchFS/boot/intel-ucode.img
    initrd /ArchFS/boot/initramfs-linux-surface.img
    options "root=UUID=9f8f9556-8ec1-4feb-9519-435beac8376f rw rootflags=subvol=ArchFS loglevel=3 quiet add_efi_memmap"
    submenuentry "Boot using fallback initramfs" {
    initrd /ArchFS/boot/initramfs-linux-surface-fallback.img
    }
    submenuentry "Boot to terminal" {
    add_options "systemd.unit=multi-user.target"
    }
    }

    我用的是btrfs文件系统,所以配置文件有点罗嗦。解释一下上面的内容。

    also_scan_dirs是指定扫描某个目录,因为我是btrfs文件系统,必须使用这个才能让refind扫描到内核文件,否则会无法启动。

    dont_scan_dirs是跳过指定的目录,因为refind默认是会扫描所有的efi文件,我们自己提供了emnuentry,所以不需要让它扫描了。

    dont_scan_files是跳过指定的文件,这里是防止其他目录出现对应的efi也被扫描到。

    scan_all_linux_kernels是扫描所有linux内核,这样所有的内核就会出现在启动列表里,我们同样也是不需要的。

    menuentry里面需要修改的地方有,volume是分区的partuuid,我因为这个uuid就测试了好几次,最后才反应过来不是filesystem uuid,要求的是partition uuid. 所有遇到ArchFS的地方都是不需要的,因为btrfs支持字卷,我的系统是在一个叫ArchFS的卷里面的,如果不是btrfs的文件系统,这个是不需要的,同样options里的rootflags选项也是不需要的,这是传递给内核的参数,让内核可以正确的加载根分区。

    这样就算完工了,重启系统,然后进bios里把安全启动改成Microsoft & 3rd party CA,然后重新启动。

    当第一次加载rEFInd的时候,因为我们的证书是才生成的,主板并没有存储对应的签名,rEFInd会启动mmx64.efi来让我们加载证书,证书的位置在/etc/refind.d/keys下,选择refind_local.cer导入,然后选择重启,重新进入系统就可以了。

    导入证书这部分我其实不太确定,因为我除了使用shim方案,我还测试了preloader方案,那个方案会一开始就启动一个MOK的工具进行证书导入,我记不太清shim到底需不需要手动导入了,如果出现了,那就导入一下就行了,没出现的话就能正常的看到引导界面和进入系统了。

    还有一个后续的动作需要处理,就是内核升级以后,我们需要对内核重新签名,否则会被bios拒绝启动。

    编辑/etc/pacman.d/hooks/99-secureboot.hook,并写入以下配置:

    [Trigger]
    Operation = Install
    Operation = Upgrade
    Type = Package
    Target = linux
    Target = linux-surface
    Target = systemd

    [Action]
    Description = Signing Kernel for SecureBoot
    When = PostTransaction
    Exec = /usr/bin/sh -c "/usr/bin/find /boot/ -type f \( -name 'vmlinuz-*' -o -name 'systemd*' \) -exec /usr/bin/sh -c 'if ! /usr/bin/sbverify --list {} 2>/dev/null | /usr/bin/grep -q \"signature certificates\"; then /usr/bin/sbsign --key /etc/refind.d/keys/refind_local.key --cert /etc/refind.d/keys/refind_local.crt --output {} {}; fi' \;"
    Depends = sbsigntools
    Depends = findutils
    Depends = grep

    享受安全启动吧~

    图片图片图片

    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,方便你我。