让wayland接管android——触摸修正与硬件加速

Original text is available at zhuanlan.zhihu.com/p/687939663

自从wayland合成器成功接管android合成器后,一直尝试处理上次未解决的问题:3D硬件加速。

缺失的 msm_drm 驱动

在处理硬件加速之前,先试着在平板上运行了一下 wayland(labwc),毕竟平板比手机更适合跑桌面软件。

显示输出很成功,但触摸有问题,光标反映的位置和实际点的位置旋转了90度,好在 labwc(wlroots) 使用的输入框架是 libinput ,可以调用 libinput_device_config_calibration_set_matrix 函数来对触摸输入执行旋转。

注释如下

c 复制代码
 * Apply the 3x3 transformation matrix to absolute device coordinates. This
 * matrix has no effect on relative events.
 *
 * Given a 6-element array [a, b, c, d, e, f], the matrix is applied as
 * @code
 * [ a  b  c ]   [ x ]
 * [ d  e  f ] * [ y ]
 * [ 0  0  1 ]   [ 1 ]
 * @endcode
.....
 * Note that any rotation requires an additional translation component to
 * translate the rotated coordinates back into the original device space.
 * The rotation matrixes for 90, 180 and 270 degrees clockwise are:
 * @code
 * 90 deg cw:		180 deg cw:		270 deg cw:
 * [ 0 -1 1]		[ -1  0 1]		[  0 1 0 ]
 * [ 1  0 0]		[  0 -1 1]		[ -1 0 1 ]
 * [ 0  0 1]		[  0  0 1]		[  0 0 1 ]
 * @endcode

但labwc没有对应的配置文件,所以添加了这个功能放在了 GitHub 上。(更新: 已合并至上游)

好不容易处理好触摸,实际使用后发现用CPU渲染的性能太糟糕了,甚至不如容器内跑 vncserver,去网上找了半天的 msm_drm 驱动,翻看了几个手机的开源内核,发现高通的 msm_drm 内核模块以及用户空间的 adreno 驱动都只提供了二进制文件。(都是安卓HAL干的好事qaq...)所以只能先休息了。


回过头来只能寄托在开源 mesa 驱动上了。

上面缺失的 drm 驱动文件,查看源码可知,可以使用 MESA_LOADER_DRIVER_OVERRIDE 环境变量强制指定同目录下别的文件

用来选择drm驱动的函数

同目录下别的驱动文件

shell 复制代码
SnowNF@localhost:~$ ls /usr/lib/aarch64-linux-gnu/dri/
armada-drm_dri.so   imx-drm_dri.so      mediatek_dri.so       r600_dri.so            sun4i-drm_dri.so
d3d12_dri.so        imx-lcdif_dri.so    meson_dri.so          r600_drv_video.so      swrast_dri.so
d3d12_drv_video.so  ingenic-drm_dri.so  mi0283qt_dri.so       radeonsi_dri.so        tegra_dri.so
etnaviv_dri.so      kgsl_dri.so         msm_dri.so            radeonsi_drv_video.so  v3d_dri.so
exynos_dri.so       kirin_dri.so        mxsfb-drm_dri.so      rcar-du_dri.so         vc4_dri.so
hdlcd_dri.so        kms_swrast_dri.so   nouveau_dri.so        repaper_dri.so         virtio_gpu_dri.so
hx8357d_dri.so      komeda_dri.so       nouveau_drv_video.so  rockchip_dri.so        virtio_gpu_drv_video.so
ili9225_dri.so      lima_dri.so         panfrost_dri.so       st7586_dri.so          vmwgfx_dri.so
ili9341_dri.so      mali-dp_dri.so      pl111_dri.so          st7735r_dri.so         zink_dri.so
imx-dcss_dri.so     mcde_dri.so         r300_dri.so           stm_dri.so

可以尝试一下 kgsl 与 msm ,他们和高通CPU关系比较大,都是主线linux上内核暴露给用户空间的接口,一个是 /dev/kgsl-3d0 还有一个是 /dev/dri/card0

不出意外,都失败了
本来想看看具体是哪里创建失败了,但想起以前看 gallium、dri、egl 和 glx 的噩梦,还是算了。

既然 wlroots 用 gles2 不行,那么 vulkan 怎么样?毕竟 vulkan 驱动很'薄', 我也用 vulkan 写过一些程序,对他也比较熟悉。

mesa 上实现高通的 vulkan 驱动叫做 turnip,他支持 kgsl 与 msm 两种模式

mesa的meson_options.txt配置文件

使用 kgsl 模式,会因为不支持 VK_EXT_physical_device_drm 扩展而被丢弃,这个很正常,毕竟 kgsl 和 drm(/dev/dri/card0)没有多大关系

shell 复制代码
SnowNF@localhost:~$ WLR_RENDERER=vulkan labwc -d
00:00:00.000 [../src/main.c:139] using config dir (/home/SnowNF/.config/labwc)

00:00:00.000 [../src/config/rcxml.c:1418] cannot read (/home/SnowNF/.config/labwc/rc.xml)
00:00:00.000 [../src/config/rcxml.c:1237] load default key bindings
00:00:00.000 [../src/config/rcxml.c:1242] load default mouse bindings
00:00:00.000 [../src/config/rcxml.c:1137] Loaded 32 merged mousebinds
00:00:00.000 [../src/config/rcxml.c:1284] load default window switcher fields
00:00:00.000 [../src/main.c:153] LABWC_PID=31120
.....
00:00:00.155 [render/vulkan/vulkan.c:111] Vulkan instance extension VK_LUNARG_direct_driver_loading v1
00:00:00.262 [render/vulkan/vulkan.c:258] Vulkan device: 'Turnip Adreno (TM) 725'
00:00:00.262 [render/vulkan/vulkan.c:259]   Device type: 'integrated'
00:00:00.262 [render/vulkan/vulkan.c:260]   Supported API version: 1.3.274
00:00:00.262 [render/vulkan/vulkan.c:261]   Driver version: 24.0.2
00:00:00.262 [render/vulkan/vulkan.c:349]   Driver name: turnip Mesa driver (Mesa 24.0.2)
00:00:00.262 [render/vulkan/vulkan.c:353]   Ignoring physical device "Turnip Adreno (TM) 725": VK_EXT_physical_device_drm not supported

使用 msm 模式,会因为 drm 设备不兼容而自我丢弃 (不会出现在vkEnumeratePhysicalDevices中) 在这里,使用了 TU_DEBUG=all 显示全部日志才能看见丢弃信息。

shell 复制代码
SnowNF@localhost:~$ TU_DEBUG=all WLR_RENDERER=vulkan labwc -d
00:00:00.000 [../src/main.c:139] using config dir (/home/SnowNF/.config/labwc)

00:00:00.000 [../src/config/rcxml.c:1418] cannot read (/home/SnowNF/.config/labwc/rc.xml)
00:00:00.000 [../src/config/rcxml.c:1237] load default key bindings
00:00:00.000 [../src/config/rcxml.c:1242] load default mouse bindings
00:00:00.000 [../src/config/rcxml.c:1137] Loaded 32 merged mousebinds
00:00:00.000 [../src/config/rcxml.c:1284] load default window switcher fields
00:00:00.000 [../src/main.c:153] LABWC_PID=26567
.....
00:00:00.069 [render/vulkan/vulkan.c:111] Vulkan instance extension VK_KHR_portability_enumeration v1
00:00:00.069 [render/vulkan/vulkan.c:111] Vulkan instance extension VK_LUNARG_direct_driver_loading v1
TU: info: TU_DEBUG=0x3fffffb
TU: info: Created an instance
TU: info: TU_DEBUG=0x3fffffb
TU: info: Created an instance
TU: error: ../src/freedreno/vulkan/tu_knl.cc:232: device /dev/dri/renderD128 (msm_drm) is not compatible with turnip (VK_ERROR_INCOMPATIBLE_DRIVER)
TU: error: ../src/freedreno/vulkan/tu_knl.cc:232: device /dev/dri/renderD128 (msm_drm) is not compatible with turnip (VK_ERROR_INCOMPATIBLE_DRIVER)
00:00:00.103 [render/vulkan/vulkan.c:258] Vulkan device: 'llvmpipe (LLVM 17.0.6, 128 bits)'

所以为什么会不兼容呢,翻看源码可知,drm 节点名称对不上

这里判断的是 msm 而不是 msm_drm

按照这种方法修改几次后,还是不能运行,几乎都失败在 drmCommandWriteRead 函数上,而他操作的对象,则是在这里打开的 fd

获取方式为 drm_device->nodes[DRM_NODE_RENDER] 设备上的路径为 /dev/dri/renderD128

为什么就他会失败呢? 观察源代码发现,基本上都是用它来发送渲染命令,再结合 DRM_NODE_RENDER 这个名字可以推测,这个 dri/renderD128 是专门用来 渲染 的,而 dri/card0 是用来 输出呈现 的。依据这个猜测,分别在 GNU/Linux 和 Android 上进行了测验

shell 复制代码
$ sudo lsof /dev/dri/card0
COMMAND    PID   USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
systemd      1   root  191u   CHR  226,0      0t0  356 /dev/dri/card0
Xorg      1206   root   19u   CHR  226,0      0t0  356 /dev/dri/card0
Xorg      1206   root   20u   CHR  226,0      0t0  356 /dev/dri/card0
kwin_wayl 1531 snownf   18u   CHR  226,0      0t0  356 /dev/dri/card0
.....
$ sudo lsof /dev/dri/renderD128
COMMAND     PID   USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
Xwayland   1565 snownf   12u   CHR 226,128      0t0  355 /dev/dri/renderD128
Xwayland   1565 snownf   14u   CHR 226,128      0t0  355 /dev/dri/renderD128
ksmserver  1586 snownf    9u   CHR 226,128      0t0  355 /dev/dri/renderD128
kded5      1588 snownf   16u   CHR 226,128      0t0  355 /dev/dri/renderD128
kded5      1588 snownf   17u   CHR 226,128      0t0  355 /dev/dri/renderD128
fcitx5-pl  1603 snownf   15u   CHR 226,128      0t0  355 /dev/dri/renderD128
plasmashe  1658 snownf   17u   CHR 226,128      0t0  355 /dev/dri/renderD128
krunner    2285 snownf   17u   CHR 226,128      0t0  355 /dev/dri/renderD128
java       2416 snownf  101u   CHR 226,128      0t0  355 /dev/dri/renderD128
konsole    3312 snownf   13u   CHR 226,128      0t0  355 /dev/dri/renderD128
qq         3709 snownf   24u   CHR 226,128      0t0  355 /dev/dri/renderD128
.....

可见 GNU/Linux 上使用 card0 进行呈现(被wayland合成器、Xorg等占用),使用 renderD128 进行渲染。

shell 复制代码
diting:/ # lsof /dev/dri/card0                                                                                         
COMMAND     PID       USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
composer-servic  1306     system    9u      CHR              226,0       0t0       1449 /dev/dri/card0
composer-servic  1306     system   17u      CHR              226,0       0t0       1449 /dev/dri/card0
composer-servic  1306     system   20u      CHR              226,0       0t0       1449 /dev/dri/card0
composer-servic  1306     system   21u      CHR              226,0       0t0       1449 /dev/dri/card0
composer-servic  1306     system   22u      CHR              226,0       0t0       1449 /dev/dri/card0
composer-servic  1306     system   24u      CHR              226,0       0t0       1449 /dev/dri/card0
.....
diting:/ # lsof /dev/dri/renderD128
diting:/ # lsof /dev/kgsl-3d0                                                                                          
COMMAND     PID       USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
surfaceflinger  1478     system  mem       CHR              505,0                 1315 /dev/kgsl-3d0
surfaceflinger  1478     system  mem       CHR              505,0                 1315 /dev/kgsl-3d0
.....

而 Android 则使用 card0 进行呈现,使用 kgsl 执行渲染。

那么只要一些修改,把 renderD128 的操作改到 kgsl 上就可以了,修改后的 mesa 代码也放到了 GitHub

然后编译安装修改过的mesa

shell 复制代码
SnowNF@localhost:~/source$ git clone https://github.com/snownf/mesa
SnowNF@localhost:~/source$ cd mesa
SnowNF@localhost:~/source/mesa$ meson setup build
......
SnowNF@localhost:~/source/mesa$ cd build
SnowNF@localhost:~/source/mesa/build$ ninja
SnowNF@localhost:~/source/mesa/build$ ninja install
[1/2] Installing files.
Installing subprojects/lua-5.4.6/liblua.so.5.4.6 to /usr/local/lib/aarch64-linux-gnu
Installation failed due to insufficient permissions.
Attempt to use /usr/bin/sudo to gain elevated privileges? [y/n] y
Installing subprojects/lua-5.4.6/liblua.so.5.4.6 to /usr/local/lib/aarch64-linux-gnu
Installing src/freedreno/vulkan/libvulkan_freedreno.so to /usr/local/lib/aarch64-linux-gnu
Installing src/freedreno/vulkan/freedreno_icd.aarch64.json to /usr/local/share/vulkan/icd.d
Installing /home/SnowNF/source/mesa/src/util/00-mesa-defaults.conf to /usr/local/share/drirc.d
Installing symlink pointing to liblua.so.5.4.6 to /usr/local/lib/aarch64-linux-gnu/liblua.so.5.4
Installing symlink pointing to liblua.so.5.4 to /usr/local/lib/aarch64-linux-gnu/liblua.so

然后使用vulkan后端渲染

shell 复制代码
SnowNF@localhost:~$ export WLR_RENDERER=vulkan
SnowNF@localhost:~$ labwc -d
00:00:00.000 [../src/config/session.c:71] read environment file /etc/xdg/labwc/environment
00:00:00.000 [../src/config/tablet.c:93] Adding button map for 0x140 with 0x110
00:00:00.000 [../src/config/tablet.c:93] Adding button map for 0x14b with 0x111
00:00:00.000 [../src/config/tablet.c:93] Adding button map for 0x14c with 0x112
.....
00:00:00.039 [render/vulkan/vulkan.c:117] Vulkan instance extension VK_KHR_portability_enumeration v1
00:00:00.039 [render/vulkan/vulkan.c:117] Vulkan instance extension VK_LUNARG_direct_driver_loading v1
00:00:00.050 [render/vulkan/vulkan.c:253] Vulkan device: 'Turnip Adreno (TM) 650'
00:00:00.050 [render/vulkan/vulkan.c:254]   Device type: 'integrated'
00:00:00.050 [render/vulkan/vulkan.c:255]   Supported API version: 1.3.277
00:00:00.050 [render/vulkan/vulkan.c:256]   Driver version: 24.0.99
00:00:00.050 [render/vulkan/vulkan.c:344]   Driver name: turnip Mesa driver (Mesa 24.1.0-devel (git-cbd7bacb6a))
00:00:00.050 [render/vulkan/vulkan.c:358] Found matching Vulkan physical device: Turnip Adreno (TM) 650
00:00:00.050 [render/vulkan/vulkan.c:443] Vulkan device extension VK_KHR_16bit_storage v1
.....

最后合成器就有了基于 vulkan 的硬件加速

mc 与 sfwbar

chromium、wlroots 与 wvkbd-mobintl

此时 /dev/dri/card0 /dev/dri/renderD128 /dev/kgsl-3d0 均有容器内软件在使用

shell 复制代码
olivine:/ # lsof /dev/dri/card0                                                                                        
COMMAND     PID       USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
seatd      9262       root    7u      CHR              226,0       0t0      13486 /data/data/com.termux/files/home/debian/dev/dri/card0
labwc      9481     system   13u      CHR              226,0       0t0      13486 /data/data/com.termux/files/home/debian/dev/dri/card0
labwc      9481     system   14u      CHR              226,0       0t0      13486 /data/data/com.termux/files/home/debian/dev/dri/card0
composer-servic  9483     system    6u      CHR              226,0       0t0      13486 /dev/dri/card0
composer-servic  9483     system    8u      CHR              226,0       0t0      13486 /dev/dri/card0
composer-servic  9483     system    9u      CHR              226,0       0t0      13486 /dev/dri/card0
composer-servic  9483     system   10u      CHR              226,0       0t0      13486 /dev/dri/card0
.....
olivine:/ # lsof /dev/dri/renderD128                                                                                   
COMMAND     PID       USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
labwc      9481     system   16u      CHR            226,128       0t0       1625 /data/data/com.termux/files/home/debian/dev/dri/renderD128
labwc      9481     system   18u      CHR            226,128       0t0       1625 /data/data/com.termux/files/home/debian/dev/dri/renderD128
labwc      9481     system   19u      CHR            226,128       0t0       1625 /data/data/com.termux/files/home/debian/dev/dri/renderD128
labwc      9481     system   21u      CHR            226,128       0t0       1625 /data/data/com.termux/files/home/debian/dev/dri/renderD128
labwc      9481     system   22u      CHR            226,128       0t0       1625 /data/data/com.termux/files/home/debian/dev/dri/renderD128
olivine:/ # lsof /dev/kgsl-3d0                                                                                       
COMMAND     PID       USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
labwc      9481     system  mem       CHR              506,0                 5371 /data/data/com.termux/files/home/debian/dev/kgsl-3d0
labwc      9481     system  mem       CHR              506,0                 5371 /data/data/com.termux/files/home/debian/dev/kgsl-3d0
labwc      9481     system  mem       CHR              506,0                 5371 /data/data/com.termux/files/home/debian/dev/kgsl-3d0
labwc      9481     system  mem       CHR              506,0                 5371 /data/data/com.termux/files/home/debian/dev/kgsl-3d0
labwc      9481     system  mem       CHR              506,0                 5371 /data/data/com.termux/files/home/debian/dev/kgsl-3d0
labwc      9481     system  mem       CHR              506,0                 5371 /data/data/com.termux/files/home/debian/dev/kgsl-3d0
labwc      9481     system  mem       CHR              506,0                 5371 /data/data/com.termux/files/home/debian/dev/kgsl-3d0
......

用起来比之前流畅多了,但还是没有高刷就很遗憾。具体来说,这个平板 (骁龙870) wlroots 从 DRM 获取到的刷新率本身就没有高刷,而较新的手机 (骁龙8+Gen1) 就正常。


后记:

vulkan + wayland 的组合下,turnip 驱动暂不支持 "kgsl_bo_export_dmabuf" 特性,使得渲染的每一帧都要"复制"到 vulkan 缓冲区,无法直接映射,相比于现代 wayland 直接映射还是差那么一点。

shell 复制代码
SnowNF@localhost:~$ TU_DEBUG=all vkcube-wayland
TU: info: TU_DEBUG=0x3fffffb
TU: info: Created an instance
TU: info: TU_DEBUG=0x3fffffb
TU: info: Created an instance
TU: error: ../src/freedreno/vulkan/tu_knl.cc:232: device /dev/dri/renderD128 (msm_drm) is not compatible with turnip (VK_ERROR_INCOMPATIBLE_DRIVER)
TU_MOD: info: select kgsl drm
TU: info: Found compatible device '/dev/dri/renderD128' (msm_drm).
Selected GPU 0: Turnip Adreno (TM) 650, type: IntegratedGpu
PIPE_FORMAT_B8G8R8A8_UNORM: 500x500x1@4x1:       0: stride=2048, size=1048576,  8192, aligned_height=512, offset=0x2000,0x0, layersz 1048576, 8192 UBWC
TU: error: ../src/freedreno/vulkan/tu_knl_kgsl_drm.cc:176: FINISHME: stub kgsl_bo_export_dmabuf
vkcube-wayland: ./cube/cube.c:1369: demo_prepare_buffers: Assertion `!err' failed.
已放弃

临时的解决方案便是使用 MESA_VK_WSI_DEBUG=sw 环境变量进行复制缓冲区再展示, vulkan + x11 也只能这么做

shell 复制代码
SnowNF@localhost:~$ MESA_VK_WSI_DEBUG=sw TU_DEBUG=startup vkcube-wayland
TU: info: TU_DEBUG=0x1
TU: info: Created an instance
TU: info: TU_DEBUG=0x1
TU: info: Created an instance
TU: error: ../src/freedreno/vulkan/tu_knl.cc:232: device /dev/dri/renderD128 (msm_drm) is not compatible with turnip (VK_ERROR_INCOMPATIBLE_DRIVER)
TU_MOD: info: select kgsl drm
TU: info: Found compatible device '/dev/dri/renderD128' (msm_drm).
Selected GPU 0: Turnip Adreno (TM) 650, type: IntegratedGpu
^C
SnowNF@localhost:~$ MESA_VK_WSI_DEBUG=sw TU_DEBUG=startup vkcube
TU: info: TU_DEBUG=0x1
TU: info: Created an instance
TU: info: TU_DEBUG=0x1
TU: info: Created an instance
TU: error: ../src/freedreno/vulkan/tu_knl.cc:232: device /dev/dri/renderD128 (msm_drm) is not compatible with turnip (VK_ERROR_INCOMPATIBLE_DRIVER)
TU_MOD: info: select kgsl drm
TU: info: Found compatible device '/dev/dri/renderD128' (msm_drm).
Selected GPU 0: Turnip Adreno (TM) 650, type: IntegratedGpu
^C

对于纯软件渲染来说,都不是问题

shell 复制代码
SnowNF@localhost:~$ VK_DRIVER_FILES=/usr/share/vulkan/icd.d/lvp_icd.aarch64.json vkcube
Selected GPU 0: llvmpipe (LLVM 17.0.6, 128 bits), type: Cpu
^C
SnowNF@localhost:~$ VK_DRIVER_FILES=/usr/share/vulkan/icd.d/lvp_icd.aarch64.json vkcube-wayland 
Selected GPU 0: llvmpipe (LLVM 17.0.6, 128 bits), type: Cpu
^C

所以有时候软件渲染(llvmpipe)会比使用 turnip 渲染更快

OpenGL + EGL + Wayland 的情况下,会使用 zink , 但因为 turnip 缺少 dmabuf 特性,无法运行。

缺少 kgsl_bo_export_dmabuf 以及 FINISHME
那么尝试软件渲染呢?

环境变量联合施法后,仍然无法运行,但屏幕上确实显示了一帧
OpenGL + EGL/GLX +Xwayland 可以使用 zink + turnip + 环境变量施法,让他支持硬件加速渲染

MESA_VK_WSI_DEBUG=sw 用来创建vulkan界面,LIBGL_KOPPER_DRI2=true 用来让zink在DRI2环境下也能渲染

不过转这么多层,对于渲染任务较小的程序,远不如 llvmpipe/lavapipe 速度快。

总的来说,turnip 驱动完善后,是可以达到运行主线linux的性能,不过还要先解决部分旧设备无法高刷的问题。

后后记:

根据评论区提供的 termux 补丁,让 turnip 实现了 dmabuf, 对应修改后的 mesa 也放到了 main-termux 分支。

然后可以使用 zink 来运行 labwc, 并让他启动带有 DRI3 支持的 xwayland

shell 复制代码
SnowNF@localhost:~$ WLR_RENDERER=gles2 MESA_LOADER_DRIVER_OVERRIDE=zink labwc -d  # 这两个都可以
SnowNF@localhost:~$ WLR_RENDERER=vulkan MESA_LOADER_DRIVER_OVERRIDE=zink labwc -d # 但我更喜欢vulkan
00:00:00.000 [../src/config/session.c:54] read environment file /etc/xdg/labwc/environment
00:00:00.000 [../src/config/tablet.c:93] Adding button map for 0x140 with 0x110
00:00:00.000 [../src/config/tablet.c:93] Adding button map for 0x14b with 0x111
00:00:00.000 [../src/config/tablet.c:93] Adding button map for 0x14c with 0x112
00:00:00.000 [../src/config/rcxml.c:1600] read config file /home/SnowNF/.config/labwc/rc.xml
......

此时 wayland 程序可以使用 dmabuf 直接映射到 vulkan 缓冲区, xwayland 也有现代的 DRI3 加速。

vkcube(左) 与 vkcube-wayland, 均使用 --present_mode 1 并且都选择了 Turnip Adreno (TM) 650

eglgears_x11(左) 与 eglgears_wayland, 均使用 zink 和 Turnip Adreno (TM) 650, 其中 xwayland 默认开启了垂直同步,只能以60帧显示

现在的性能水平终于和现代 Linux 差不多了 (好累啊qwq)....

相关推荐
即将头秃的程序媛1 小时前
centos 7.9安装tomcat,并实现开机自启
linux·运维·centos
fangeqin2 小时前
ubuntu源码安装python3.13遇到Could not build the ssl module!解决方法
linux·python·ubuntu·openssl
爱奥尼欧3 小时前
【Linux 系统】基础IO——Linux中对文件的理解
linux·服务器·microsoft
超喜欢下雨天3 小时前
服务器安装 ros2时遇到底层库依赖冲突的问题
linux·运维·服务器·ros2
tan77º4 小时前
【Linux网络编程】网络基础
linux·服务器·网络
笑衬人心。5 小时前
Ubuntu 22.04 + MySQL 8 无密码登录问题与 root 密码重置指南
linux·mysql·ubuntu
chanalbert6 小时前
CentOS系统新手指导手册
linux·运维·centos
星宸追风7 小时前
Ubuntu更换Home目录所在硬盘的过程
linux·运维·ubuntu
热爱生活的猴子7 小时前
Poetry 在 Linux 和 Windows 系统中的安装步骤
linux·运维·windows
myloveasuka7 小时前
[Linux]内核如何对信号进行捕捉
linux·运维·服务器