V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  kuanat  ›  全部回复第 3 页 / 共 16 页
回复总数  315
1  2  3  4  5  6  7  8  9  10 ... 16  
@kuanat #18
@shalingye #16


最后再回到之前说的共享内存方案。实际上 framebuffer 的数据结构某种程度上说是硬件相关的。也就是说,即便在虚拟机和宿主机之间通过虚拟设备共享了内存,一方面要对接这个虚拟内存的读写接口,另一方面需要将 framebuffer 封装成一种统一的格式。这样在宿主机上,用于显示虚拟机内容的窗口可以直接将 framebuffer 提交给窗口管理器进行合成,即再次 DMA 到显卡。

如果我说得不是很清楚的话,可以参考 https://looking-glass.io/ 这个项目,它的核心实现是 KVMFR https://github.com/gnif/LookingGlass/blob/master/module/kvmfr.c 这个模块,基于 IVSHMEM 完成我之前说的流程。理论上 windows 上实现相同效果的原理是一样的。
@kuanat #17
@shalingye #16

我之前回复的是满足第二个要求的方法。先不考虑虚拟机里的视频信号从哪里来的,假设你已经获得了实时 framebuffer 流,可以走网络协议,同时由于宿主机和虚拟机在一起,也可以走共享内存。技术上说,所有走网络协议的方案因为存在编解码、封装,都不可能比直接内存共享延迟更低。就拿 kvm 常见的虚拟化方案来说,SPICE 是个网络协议,但与 qxl 搭配的时候,使用的是共享内存。

从原理上说,kvm 这边直接用 SPICE 就可以了。我搜了一下 vmbus 的文档,虽然提到了共享内存,但我感觉用它来共享 framebuffer 需要做的工作还很多。
@shalingye #16

如果我没理解错的话,你的需求是这样的:宿主机上运行的虚拟机,然后宿主机的某个客户端窗口,显示虚拟机的视频输出内容。

为了达到目标性能要求,一方面需要虚拟机本身能够实现高分辨率高刷新率,另一方面这个达标的显示输出能够在宿主机上正确还原,中间的通信延迟要足够低(输入设备还在宿主机上并没有直通到虚拟机)。



为了达到第一个要求,一般有两个方案:

1. 使用半虚拟化驱动设备,比如 qxl ,virgl 还有一些都属于这种,在虚拟机里面使用虚拟的显卡设备,这个设备会将渲染指令传递给宿主机,通过宿主机执行后再将结果传回虚拟机

2. 直通物理显卡或者利用 sriov 直通物理显卡虚拟出来的显卡

我对 windows 不熟悉,猜测 windows 的几个实现原理上应该都是上面两个思路。



不知道触发了什么关键词,我二分一下拆开回复。
@kuanat #68

vscode 不行哈哈,原因就是 #73 说的。
Linux 这边 virtio 也有类似的需求和实现方案。

我个人的理解是:

- 如果虚拟机内部是虚拟的 gpu ,那么就可以直接共享内存,宿主机直接访问虚拟机内虚拟 gpu 的 framebuffer

- 如果虚拟机内部有直通的 gpu ,那就只能从 framebuffer 入手抓取视频源(比如 nvfbc ),然后再共享给宿主机

应该不存在比直接内存映射更高效的 IPC 方式了。
我认为是 vscode 的锅,因为我的印象里这个功能 gopls 很早就有了,不过我现在主力是 neovim ,待我验证一下。
这是个业务或者说工程问题,不全是技术问题。因为不像 Java 用 BigDecimal 比较多,Go 这边没有习惯性做法,所以主要靠约定,剩下的是如何执行。无论哪种语言,计算这类纯技术问题都是小事,与业务结合的部分才是大事。

我这里说几个技术人员可能不太熟悉的业务需求或者是需要注意的点:

- 最理想的是用 Go 自定义数据结构,在数据结构上实现相应的运算方法。这样可以避免代码上的出错。这里比较关键的点是,计算过程肯定是高精度/整型(对应 BigDecimal ),同时一定要支持 split 操作,主要是处理类似 1 拆成 0.33+0.33+0.34 的业务需求,这种在会计、税务场景很常见。

- 根据全流程数据交换的环节来定义精度和数据格式。一般推荐的是比常见货币最小单位更精确一点,或者支持自定义。传递过程中使用字符串,做好格式转换。说到底还是靠约定,为了方便执行可以独立成库强制所有上下游都使用特定实现。

- 有需要的话提前考虑多币种支持,比如订单系统如果可以支持多币种,数据库和业务逻辑都要做 schema 调整。通常的业务需求来说,多币种就是多账本,如果最初设计成单账本后期修改会很痛苦。

- 推荐使用 event driven 架构来做 cqrs ,即用事务的方式持久化变动,实时状态由历史计算推导得出。类似银行卡只记录进出,余额是算出来的。好处一方面能和通常的消息队列架构方便对接,另一方面整个业务的可靠性、灾难恢复都好做。有 olap 需求也容易改造。
我在过去几年的代码库里检索了一下,只找到了一种涉及到 defer 里面修改返回值操作的反例。严格来说,这个代码编写方式是 named return 的问题,而不是 defer 的问题。

前面提到的 defer 里修改返回值的情况是:

// fn 函数签名 fn() (err error)

defer func() {
err = writer.Close()
}()

这样就会覆盖掉原本 err ,所以还要新增变量特殊处理一下。

defer func() {
closeErr := writer.Close()
if closeErr != nil {
// 特殊处理
}
}()

这样看起来就很蠢对吧,所以代码规范里就直接禁止了在 defer 里写逻辑。我确实想象不出来正常的业务代码里有什么一定非要在 defer 里处理的逻辑不可。个人的观点是,这个和三元逻辑操作符差不多,都是不适合工程上团队协作使用的。



当然我这里的规范还有一条,interface 写 named return ,这样注释可以对应到参数名。

我印象有个说法是 go 早期是手搓编译器,named return 能方便代码生成。其实我觉得这个特性除了支持 naked return 之外没什么意义,属于某种设计失误,但也有可能是我没理解到位。
71 天前
回复了 nativeBoy 创建的主题 浏览器 火狐不争气啊
作为多年 Linux 用户,我支持 Firefox 的主要原因就是不想让 Chrome 一家独大,至少 uBlock Origin 在 Firefox 是全功能的。

性能方面 Firefox 确实离 Chrome 有点差距,不止体现在 benchmark 里面,体感就够了。比较明显的就是 bili 播放弹幕比较多的视频,都是硬件加速的情况下,Chrome 对 gpu 的利用要好很多。(准确说是 chromium ,官方 chrome 是不支持硬件加速的)

使用方面 Firefox debug 可比 Chrome 舒服太多了。
71 天前
回复了 yadam 创建的主题 Linux 分享一个 Linux 下的改键工具
@yadam #6

关于 2 中你的处理原则是合理的,ctrl down 一定要在用户按下的时候就响应,而不是等到再按下其他键的时候才发送按下事件。这里主要的问题是,很多软件会希望获得 modifier 的状态,或者 modifier key 的按下释放事件。比较常见的除了 alt 触发菜单,还有把 ctrl 或者空格当作 push-to-talk ,把 ctrl+alt 作为虚拟机的跳出按键,你在设计的时候可以思考一下,因为历史遗留原因和软件开发的多样性,软件到底是检测 modifier 状态,还是检测按键事件,或者是检测 keysym 可能需要不同的处理方式。

我在 AHK 那边看到过一个处理逻辑,就是交叉释放,比如你在 alt+h 这个场景,正常逻辑是先发送 alt down ,再拦截 h ,发送 alt up ,发送 left 这样,在发送 alt up 之前插入 ctrl down ,然后 alt up ,ctrl up 这样,就不会被认为是按下了 alt 键又松开。可能目前只有这样的 hack 方式才能解决。



配置文件方面,我更倾向于把改键应用分为两类,当前语境下的映射类建议用静态配置文件,自动化意义上的 AHK 建议用 DSL 自定义语法。后者的话工作量比较大,因为有 quickjs 的存在,我觉得反倒很适合直接拿来用。如果主程序是 c 的话,lua 是个不错的选项。

映射类的配置文件,我个人比较喜欢 keyd 的 ini 方式。重点不在格式上,而是 keyd 对于 layer 功能实际上是有默认的,就是配置里没有写的,直接 fallback 到原始按键上。本质上这些配置还是存在的,只是不需要使用者去写了。你看 #5 那个写法,符合直觉而且好写好懂。如果你要设计的话,可以提前想象一下,类似长短按,按下生效一次,按下自动重复,按下切换 layer 需要什么样的语法。我之前尝试过,无一例外都把自己绕晕了……



另外有些功能在 de/wm 阶段处理 keysym 可能更容易,gnome 的话有 keyboard shortcuts 可以自定义,只是可以绑定的功能比较有限。如果你用过类似 sway 这样的纯窗口管理器,会发现 keysym 触发特定功能能满足大部分 AHK 的常见需求。
dmesg 里面找 checksum error ,大概是这么个字符串,因为我这好久没出过错记得不是很清楚了。
71 天前
回复了 yadam 创建的主题 Linux 分享一个 Linux 下的改键工具
我大致看了一下你的实现,讲道理你是个狠人啊……你不仅给 libevdev 做了 binding ,还内嵌了 quickjs 用来做配置自定义。因为我经常给自己的设备做固件写驱动,所以改键这部分还算比较熟悉,随便说一点想法。

1.
通过 uinput 虚拟输入设备,拦截物理设备事件(独占),映射完成后通过虚拟设备输出事件,这是唯一正确的做法。另一个我认为哲学上不那么正确的做法是,原物理设备不管,只重新映射事件。更准确的说法是这是处理两种不同需求的做法,前者的重点在于映射,后者的应用场景是脚本化、自动化,比如 AHK 这种,两者有重合的地方,但实际上是两种不同的设计方向。

2.
在这个“正确”的设计下,需要处理很多 corner cases ,我随便举一个类似方案很容易踩的坑:很多 gui 应用响应 alt 呼出菜单,假如有个改键逻辑是 alt+h 映射为 left ,当用户按下 alt 的时候,需要原样输出 alt 按下,同时设置 modifier ,之后按下 h ,此时以完全拦截,然后重新映射的视角来看,应该先释放 alt ,然后插入 left 。这时就会触发 alt 按下又释放的事件,就会被 gui 应用响应到。同时用户也没有办法再输入 alt+j 这个组合,这就给如何设计配置文件语法带来了挑战。

3.
配置文件用 js 这样的动态语言是一个可选的方向,但我不确定是不是个好的做法,比较直观的缺陷就是可读性和 debug 。以我对现有的各个实现的观察来看,应用提供 sane defaults 是非常重要,它可以极大简化配置文件的编写。特别是当你想实现类似 qmk layer 之类的功能的时候,全拦截重映射实际上要求每个按键都是重映射过的,配置文件如果要把所有逻辑都写一遍体验会不太好。

4.
获得当前活动窗口的名字是个看起来简单实际上复杂的事情,首先底层是 xorg 还是 wayland 要区分一次,xorg 稍微好解决一点,wayland 要做全兼容,大概主流的 mutter/kwin/wlroots 都要兼顾。各个实现对于 foreign-toplevel-manager 这个协议的态度差别很大。要么对 gnome 用 dbus ,对 kde 用 script api 一个一个适配,要么等各家支持相关协议。

5.
ctrl+c/v/x 映射到 ctrl+insert/shift+insert/shift+delete 是一个思路,但不是唯一的思路,比如你可以直接 super+c/v/x 映射到 XF86 的 copy/paste/cut ,更接近 mac 的逻辑。这方面 sway 这样的 wm 比起 gnome 这样的 de 要容易。另外 linux 的 clipboard 目前也是 wayland 协议的一部分,除此之外还有 primary selection 能用,可以发挥想象力。

6.
在这种系统调用层面上,go/rust 或者其他语言都差不多,只有不是 c 都会有 ffi 的问题。我只是单纯觉得,binding 都写了,不如直接写 c 了。另外不用 c 的话 IPC 带来的延迟会比较明显。




PS

下面写给对改键这个事情感兴趣的人看的。

首先明确几个概念 scancode/keycode/keysym ,scancode 是设备产生的硬件信号,经过内核 udev/evdev 之后转化为 keycode ,keycode 由内核空间传递到用户空间后,由桌面/窗口管理根据键盘 layout 转换为 keysym ,也就是应用程序获得的输入。

现在能够接触到的键盘类设备,只要不想专门做驱动,都会按照 linux headers 头文件( input-event-codes.h )定义的 keycode 去做,不然就是给自己找麻烦。当然像笔记本、游戏设备就需要自定义使用头文件里没有的 scancode/keycode 映射了。

以当前的 linux 生态来说,整个按键输入流程是这样的,硬件产生 scancode ,在内核空间经过 udev/evdev 处理映射为 keycode ,通过 /dev/input/eventX 暴露给用户空间。用户空间有 xorg/wayland 两个大的框架,对应的实现分别是 xorg-input-evdev 和 libinput ,注意前者虽然名字有 evdev 但实际上是用户空间的,意思是它利用 evdev 机制,此二者都是操作内核暴露的 /dev/input/eventX 接口,然后根据环境 locale/layout ,将 keycode 转换为 keysym 。由于目前 xorg 的实现也都过渡到 xf86-input-libinput 上面了,所以可以认为,用户空间就是 libinput 。此阶段之后,上层的桌面/窗口管理器可以获得特定的 keysym ,进一步传递给活动窗口应用。



综合上面的背景信息,可以说理论上有三个,但实践中只有两个可以做改键的位置。第一个是在内核空间通过 udev 规则改写 scancode 和 keycode 的映射,说它没有实践意义是因为这是设备厂家要做的事情。剩下两个有实践意义的,一个是 keycode 转 keysym 的阶段,另一个是 keysym 传递给应用窗口的阶段。

如果继续观察市面上已有的各种改键工具,会发现在 keycode 转 keysym 的阶段完成映射的方式,传统基于 xorg-input-evdev 的实现都只能支持 xorg ,而基于 libinput 的可以同时支持 xorg/wayland 。

至于为什么 keysym 传递给应用窗口这个实现也会存在,原因很简单,用户有针对特定应用改键的需求,而这个需求是前一种方式不能独立完成的。

所以现在改键就剩一种方式了,就是虚拟 uinput ,然后拦截物理设备事件做映射。区别就是要不要识别当前应用,以及如何识别。至于在 keysym 传递过程做映射,只有纯 wm 能实现,一般 de 是不开放这个自定义的。
136 天前
回复了 cosmain 创建的主题 程序员 关于自动升级和更新
部署和配置更新可以考虑 ansible ,中心式管理没有更简单的了,有 ssh 就行,没有性能需求。

ip 变动的话一般要靠设备主动汇报,一般负责心跳的模块顺便就做了。我这里之前用的方案是 ansible inventory 是通过外部接口调取的。
再补充一点,bios 里的选项位置是固定的,所以并不需要 OCR 之类的手段。多数时间只需要判断对应位置的选项是不是有高亮或者反色即可,即只需要判断当前光标是否选中了目标。
我给两个思路,OP 的判断是没问题的,常规自动化处理不了这种视频流内的信息。

1.
如果设备 bmc 比较新,我记得好几年前多数 bmc 都支持 redfish 协议了,那么你在 bios 里面要测试的项目可能多数可以直接走 bmc 的 redfish api 接口来实现。

2.
如果设备 bmc 比较老,那就通过 web 页面先抓一下输出的视频流,这个大概率是类似固定摄像机那种 mjpeg 流,本质上就是固定间隔的截图。这样可以省去在 web 界面上截图的逻辑。
然后就是逆向一下 web 界面发送按键序列的接口,用来做控制。这里需要注意的是,大概率还是要通过截图来判断状态,因为 bmc 那边接收到按键请求,但 bmc 把按键请求传递给主机这个环节不一定能 100% 正确响应。
再之后就是自动化的事情了。
144 天前
回复了 gtheone1 创建的主题 Android 小区门禁是 ID 卡,手机不能模拟吗
物理层面 ID 卡因为频率标准不一样,是没有办法模拟的。

某些情况下,可以用 IC 卡第一个扇区直接写 ID 卡号码,Big/Little Endian 可以都试一下。

原理是这些门禁设备硬件上是双频率的,也就是同时有 ID/IC 支持,软件写得不好,会把 IC 读取的结果当作 ID 序列号来判定。虽然比较少见,但我确实见过,当时我觉得匪夷所思,验证过之后才发现设备是双频率的。
@iv8d #105

JSX 是对 JS 语法的扩展,所以不是在 JS 里面写 HTML ,JSX 还是在写 JS ,只是这个 JS 扩展出来的语法部分非常像 HTML 。

JSX 里面像 HTML 的部分实际上就是在执行 JS ,并不是生成 HTML 代码,而是调用 DOM API 来达到和 HTML 代码一样效果。

所以最初在 JSX 里面要写 className ,因为这是 DOM API ,而不是直接用 HTML class 属性。
152 天前
回复了 lbbdefy 创建的主题 Linux 求助 ubuntu24.04 怎么创建虚拟屏幕当副屏幕
如果用 sway/hyprland 可以参考我这个帖子 https://v2ex.com/t/1046504

你上面的报错估计是因为你用的不是 sway/wlroots 。

Gnome/mutter 实现了一个 XDP 就是基于虚拟桌面的:

gsettings set org.gnome.desktop.remote-desktop.rdp screen-share-mode

我很久都不用 gnome 了,你需要搜一下上面这个配置项找下 gnome 的文档。
1  2  3  4  5  6  7  8  9  10 ... 16  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2637 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 28ms · UTC 13:05 · PVG 21:05 · LAX 06:05 · JFK 09:05
Developed with CodeLauncher
♥ Do have faith in what you're doing.