让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)....

相关推荐
mit6.82416 分钟前
[Redis#3] 通用命令 | 数据类型 | 内部编码 | 单线程 | 快的原因
linux·redis·分布式
^Lim31 分钟前
esp32 JTAG 串口 bootload升级
java·linux·网络
小林熬夜学编程1 小时前
【Linux系统编程】第五十弹---构建高效单例模式线程池、详解线程安全与可重入性、解析死锁与避免策略,以及STL与智能指针的线程安全性探究
linux·运维·服务器·c语言·c++·安全·单例模式
玖玖玖 柒染1 小时前
windows下sqlplus连接到linux oracle不成功
linux·windows·oracle
LuckyTHP1 小时前
CentOS 9 无法启动急救方法
linux·运维·centos
Bonne journée1 小时前
centos和ubuntu有什么区别?
linux·ubuntu·centos
vvw&1 小时前
如何在 Ubuntu 22.04 上安装带有 Nginx 的 ELK Stack
linux·运维·nginx·ubuntu·elk·elasticsearch·开源项目
Linux运维老纪1 小时前
交换机配置从IP(Switch Configuration from IP)
linux·服务器·网络·安全·运维开发·ip
OneSea1 小时前
Debian源码管理
linux
加载中loading...1 小时前
C/C++实现tcp客户端和服务端的实现(从零开始写自己的高性能服务器)
linux·运维·服务器·c语言·网络