news 2026/8/31 4:47:49

用PySide6构建窗口跟随悬浮窗:以Codex为实例

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
用PySide6构建窗口跟随悬浮窗:以Codex为实例

如果你也经常用 OpenAI Codex CLI 在终端里写代码,应该遇到过这种场景:编辑器、浏览器、训练脚本的日志窗口叠在一起,Codex 窗口被挤到角落,每次要切过去看任务状态,都得在全屏窗口里一个一个找焦点。为了减少这种来回切换的视觉成本,我做了一个很小的桌面工具:一个始终置顶、半透明、会跟着 Codex 窗口走的悬浮窗。

这个工具本身不复杂,核心只有两件事:找到目标窗口的位置,把我的小窗口移动到它旁边。真正值得沉淀的,是背后的桌面窗口遍历、进程匹配、DPI 坐标换算、无边框置顶窗设计这些很零散但很有用的知识点。下面我会从原理拆到代码,再给出一套可直接运行的 PySide6 示例,帮助你掌握“窗口跟随”这类桌面自动化能力的完整套路。

1. 这个“跟随窗口”究竟在解决什么问题

1.1 从实际场景说起

Codex CLI 这类 AI 编程工具通常运行在终端窗口里,它本身不会提供一个像 IDE 那样的侧边栏,也不会把任务进度主动钉在屏幕上。当你在几个大窗口之间来回切换时,想随时看到 Codex 的当前状态并不方便。

一个比较自然的做法,是给 Codex 窗口“挂”一个浮动信息栏。这个信息栏可以显示目标窗口的标题、当前位置,或者你想放进去的任何提示内容。它不需要用户手动拖动,因为只要检测到 Codex 窗口移动了,它就自动跟过去。

这个场景还可以继续扩大:不光是跟 Codex,你可以让它跟随任意进程的窗口。只要知道进程名或窗口标题,就能挂一个小面板在旁边。常见的应用包括:

  • 给长时间运行的训练脚本做状态浮窗;
  • 给视频录制工具做一个小的“正在录制”提示条;
  • 给远程终端窗口做快捷指令栏;
  • 给测试脚本做实时日志悬浮面板。

本质上,这是一种“基于位置关系的桌面 UI 组合”思路:两个本来没有任何关系的窗口,通过其中一个的位置去联动另一个的坐标。

1.2 技术思路:桌面窗口跟随的实现套路

实现窗口跟随,最简单也最可靠的方案是轮询。

流程大致如下:

  1. 定时(例如每 300ms)查找目标进程的主窗口句柄;
  2. 调用GetWindowRect获取目标窗口在屏幕上的坐标;
  3. 计算悬浮窗的新坐标,比如目标窗口右上角偏移 12 像素;
  4. 把悬浮窗移动到新坐标。

这套思路不依赖任何窗口管理器,也不需要在 Windows 底层实现事件钩子,只要能拿到窗口句柄,就能工作。在 Windows 平台上,核心 API 都来自user32.dll,例如EnumWindowsGetWindowThreadProcessIdGetWindowRectMoveWindow等。

1.3 为什么不选全局窗口钩子

第一次做这类工具时,我优先考虑的是 Windows 的SetWinEventHook,因为它可以监听窗口移动事件,事件来了再跟随,比轮询更实时。但实践下来,它有明显的缺点:

  • 全局钩子需要写原生代码,Python 里虽然可以用 ctypes 绕过,但回调函数的生命周期管理复杂。
  • 钩子回调频率很高,如果目标窗口在快速拖动,悬浮窗也会频繁 move,容易造成闪烁。
  • 权限和杀毒软件容易拦截此类全局钩子,导致工具在别人电脑上不可用。

所以对“跟随窗口”这种需求,定时轮询完全够用。300ms 的轮询频率人眼几乎感知不到延迟,CPU 占用也很低。

2. 环境准备与项目结构

2.1 运行环境

本文示例以 Windows 10/11 + Python 3.10+ 为例。需要用到一个轻量级 GUI 框架 PySide6,以及一个用于读取进程信息的 psutil 库。

版本要求不需要特别严格,PySide6 大版本稳定即可。如果你本机已经装过 PySide6,请留意 QT 插件版本是否匹配。程序核心逻辑不依赖某个非常新的 PySide6 API,所以兼容性比较好。

2.2 安装依赖

建议先建一个虚拟目录,避免污染全局 Python 环境。

mkdir codex-follower cd codex-follower python -m venv venv venv\Scripts\activate

然后安装依赖:

pip install PySide6 psutil

安装完成后,可以用下面命令验证 PySide6 是否能正常加载:

from PySide6.QtWidgets import QApplication print(QApplication.instance() is not None)

2.3 项目目录

本示例采用三个文件分离职责:

codex-follower/ ├── venv/ ├── src/ │ ├── window_tracker.py # Windows 窗口查找与坐标读取 │ ├── floating_window.py # 悬浮窗 UI 与跟随逻辑 │ └── main.py # 程序入口

window_tracker.py只负责底层窗口 API,floating_window.py负责界面,main.py负责组装。这样后续要扩展为“跟随任意窗口”,或者把界面换成 Tkinter,成本都很低。

3. 核心技术点拆解

3.1 如何找到 Codex 窗口句柄

一个进程可能创建多个窗口,窗口还有主窗口、子窗口、隐藏窗口之分。要找到“用户能看到的主窗口”,比较可靠的方法是这样:

  1. psutil.process_iter()遍历进程,找到名称匹配的进程,并记录它的 PID;
  2. 调用EnumWindows枚举所有顶层窗口;
  3. 对每个窗口调用GetWindowThreadProcessId,判断它是否属于目标 PID;
  4. 过滤掉不可见窗口,以及没有标题的窗口;
  5. 如果多个窗口都匹配,优先选择标题包含 “Codex” 的窗口。

这里有一个容易被坑的点:GetWindowThreadProcessId的第二个参数是一个 DWORD 指针,用来接收 PID。用 ctypes 调用时,需要先创建wintypes.DWORD,再用ctypes.byref传进去。

另外,不要只看进程名。如果 Codex 是在某个终端软件里运行的,GUI 窗口可能是终端模拟器的窗口,进程名也不一定是codex.exe。所以更通用的方式是允许用户配置“进程名”或“窗口标题关键词”。

3.2 如何读取窗口位置

拿到窗口句柄后,读取位置使用GetWindowRect

rect.left rect.top rect.right rect.bottom

这四个值分别表示窗口左上角和右下角的屏幕坐标。窗口宽度可以用right - left计算,高度用bottom - top计算。

需要注意,GetWindowRect返回的是屏幕坐标,不是相对父窗口的坐标。对于顶层窗口来说,这个坐标可以直接用于 Qt 的move(x, y)

3.3 坐标换算与 DPI 缩放

这是最容易出问题的地方。

在 Windows 上,如果系统开启了高 DPI 缩放(150%、200% 等),不同进程可能运行在不同 DPI 感知模式下。如果只在一个地方读取坐标,可能出现悬浮窗位置偏了半个屏幕的情况。

解决办法是让 Python 进程声明 DPI 感知。常见方式有两种:

  • SetProcessDpiAwareness(2),表示 Per-Monitor DPI Aware,Windows 8.1+ 推荐;
  • SetProcessDPIAware(),表示 System DPI Aware,老 API。

在 PySide6 程序中,建议在创建QApplication之前就设置 DPI 感知,这样 Qt 后续拿到的屏幕坐标才会和GetWindowRect保持同一套坐标系。

3.4 悬浮窗的形态控制

做一个“会跟着 Codex 走的小窗口”,形态上通常是:

  • 无系统边框;
  • 置顶显示;
  • 半透明或圆角背景;
  • 不抢焦点;
  • 甚至可以鼠标穿透。

PySide6 中通过WindowFlags组合实现:

Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint | Qt.WindowType.Tool

Tool标志很关键,它让窗口不在任务栏显示,也不抢焦点。WindowTransparentForInput可以实现鼠标点击穿透,悬浮窗下面的窗口仍然可以正常交互。

不过鼠标穿透是一把双刃剑。如果点击穿透,用户就无法点击悬浮窗上的退出按钮。实际工具一般会提供一个快捷键来切换穿透模式。

4. 完整实战案例:做一个会跟着 Codex 走的悬浮窗

下面进入完整代码阶段。示例项目命名为codex-follower,实现效果如下:

  • 找到codex.exe进程的主窗口;
  • 悬浮窗出现在目标窗口右上角,偏移 12 像素;
  • 每 300ms 同步一次位置;
  • 悬浮窗显示目标窗口标题、当前位置和跟随状态;
  • 默认开启鼠标穿透;
  • F2切换鼠标穿透模式,按Esc退出程序。

4.1 编写窗口工具类

先创建src/window_tracker.py,封装 Windows 窗口查找和坐标读取。

# 文件路径:src/window_tracker.py import ctypes from ctypes import wintypes import psutil user32 = ctypes.windll.user32 WNDENUMPROC = ctypes.WINFUNCTYPE( wintypes.BOOL, wintypes.HWND, wintypes.LPARAM, ) class RECT(ctypes.Structure): _fields_ = [ ("left", ctypes.c_long), ("top", ctypes.c_long), ("right", ctypes.c_long), ("bottom", ctypes.c_long), ] def _find_pid_by_process_name(process_name: str): target_name = process_name.lower() for proc in psutil.process_iter(["pid", "name"]): try: if proc.info["name"] and proc.info["name"].lower() == target_name: return proc.info["pid"] except (psutil.NoSuchProcess, psutil.AccessDenied): continue return None def find_window_by_process_name(process_name: str, keyword: str = ""): """根据进程名和窗口标题关键词查找顶层窗口。 返回 (hwnd, title),找不到时返回 (None, None)。 """ pid = _find_pid_by_process_name(process_name) if pid is None: return None, None matches = [] def enum_handler(hwnd, lparam): if not user32.IsWindowVisible(hwnd): return True window_pid = wintypes.DWORD() user32.GetWindowThreadProcessId(hwnd, ctypes.byref(window_pid)) if window_pid.value != pid: return True length = user32.GetWindowTextLengthW(hwnd) if length == 0: return True buf = ctypes.create_unicode_buffer(length + 1) user32.GetWindowTextW(hwnd, buf, length + 1) title = buf.value if keyword and keyword.lower() not in title.lower(): return True matches.append((hwnd, title)) return True enum_proc = WNDENUMPROC(enum_handler) user32.EnumWindows(enum_proc, 0) if not matches: return None, None # 优先返回标题包含关键词的窗口 for hwnd, title in matches: if keyword and keyword.lower() in title.lower(): return hwnd, title return matches[0][0], matches[0][1] def get_window_rect(hwnd): """返回窗口的 (x, y, width, height),失败返回 None。""" if not hwnd: return None rect = RECT() ok = user32.GetWindowRect(hwnd, ctypes.byref(rect)) if not ok: return None x = rect.left y = rect.top width = rect.right - rect.left height = rect.bottom - rect.top return x, y, width, height def is_window_minimized(hwnd): """判断窗口是否最小化。""" return bool(user32.IsIconic(hwnd))

这里的关键点有两个。一是枚举回调里把enum_proc赋值给变量,避免回调函数对象被垃圾回收。二是通过GetWindowTextLengthW过滤空标题窗口,因为很多后台窗口没有标题但可见。

4.2 编写悬浮窗

接下来创建src/floating_window.py,这是整个项目的 UI 主体。

# 文件路径:src/floating_window.py from PySide6.QtCore import Qt, QTimer from PySide6.QtGui import QShortcut, QKeySequence from PySide6.QtWidgets import ( QLabel, QPushButton, QVBoxLayout, QWidget, ) from window_tracker import ( find_window_by_process_name, get_window_rect, is_window_minimized, ) class FloatingWindow(QWidget): def __init__( self, process_name: str = "codex.exe", keyword: str = "codex", offset_x: int = 12, offset_y: int = 12, passthrough: bool = True, ): super().__init__() self.process_name = process_name self.keyword = keyword self.offset_x = offset_x self.offset_y = offset_y self.passthrough = passthrough self.target_hwnd = None self.setFixedSize(280, 96) self._apply_window_flags() self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground) layout = QVBoxLayout(self) self.title_label = QLabel("等待 Codex 窗口...") self.position_label = QLabel("位置: --") self.status_label = QLabel("状态: 已启用鼠标穿透") layout.addWidget(self.title_label) layout.addWidget(self.position_label) layout.addWidget(self.status_label) self.toggle_btn = QPushButton("F2: 切换鼠标穿透 / Esc: 退出") layout.addWidget(self.toggle_btn) QShortcut(QKeySequence("F2"), self, self.toggle_passthrough) QShortcut(QKeySequence("Esc"), self, self.close) self.timer = QTimer(self) self.timer.timeout.connect(self.sync_position) self.timer.start(300) self.sync_position() def _apply_window_flags(self): flags = ( Qt.WindowType.FramelessWindowHint | Qt.WindowType.WindowStaysOnTopHint | Qt.WindowType.Tool ) if self.passthrough: flags |= Qt.WindowType.WindowTransparentForInput self.setWindowFlags(flags) def toggle_passthrough(self): """切换鼠标穿透模式。""" self.passthrough = not self.passthrough self._apply_window_flags() self.show() self.status_label.setText( "状态: 已启用鼠标穿透" if self.passthrough else "状态: 已禁用鼠标穿透" ) def sync_position(self): """轮询目标窗口位置并移动悬浮窗。""" hwnd, title = find_window_by_process_name(self.process_name, self.keyword) if hwnd is None: self.target_hwnd = None self.hide() return self.target_hwnd = hwnd self.title_label.setText(f"目标: {title[:24] if title else 'No Title'}") # 最小化时不跟随,隐藏自身 if is_window_minimized(hwnd): self.hide() return rect = get_window_rect(hwnd) if rect is None: self.hide() return x, y, width, height = rect new_x = x + width + self.offset_x new_y = y + self.offset_y self.move(new_x, new_y) self.position_label.setText( f"位置: ({x}, {y}) 尺寸: {width}x{height}" ) self.show()

这段代码的核心逻辑在sync_position()中。每 300ms 执行一次:

  1. 查找目标窗口;
  2. 如果找不到就隐藏悬浮窗;
  3. 如果目标窗口最小化也隐藏;
  4. 读取窗口矩形并计算出新坐标;
  5. 调用move()移动悬浮窗。

键盘快捷键用QShortcut实现,即使鼠标穿透,键盘事件仍然可以被窗口接收。F2用于切换鼠标穿透,Esc用于退出程序。

4.3 编写主程序

最后创建src/main.py,负责 DPI 初始化和启动 Qt 事件循环。

# 文件路径:src/main.py import ctypes import sys from PySide6.QtWidgets import QApplication from floating_window import FloatingWindow def enable_dpi_awareness(): """开启高 DPI 感知,保证坐标读取和窗口显示一致。""" try: ctypes.windll.shcore.SetProcessDpiAwareness(2) except AttributeError: ctypes.windll.user32.SetProcessDPIAware() except Exception: # 部分环境下 SetProcessDpiAwareness 可能被拒绝,忽略即可 pass def main(): enable_dpi_awareness() app = QApplication(sys.argv) win = FloatingWindow( process_name="codex.exe", keyword="codex", offset_x=12, offset_y=12, passthrough=True, ) win.show() sys.exit(app.exec()) if __name__ == "__main__": main()

这里把SetProcessDpiAwareness(2)放在QApplication创建之前,是因为 Qt 会读取当前进程的 DPI 感知状态,如果晚了可能出现坐标系统不一致。

4.4 运行与验证

src目录下运行:

python main.py

正常情况你会看到一个小悬浮窗出现在 Codex 窗口的右侧。手动拖动 Codex 窗口,悬浮窗会在很短时间跟着移动。

如果当前没有 Codex 进程,悬浮窗会直接隐藏,不会在桌面上残留。这是一种比较安全的行为,避免程序启动后出现一个“无处可跟”的空白窗口。

4.5 扩展:跟随任意窗口

如果你并不想跟 Codex,而是想跟 Chrome、VS Code、记事本等任意窗口,只需要修改主程序的参数即可:

win = FloatingWindow( process_name="Code.exe", keyword="Visual Studio Code", offset_x=12, offset_y=12, passthrough=True, )

由于查找逻辑按“进程名 + 窗口标题关键词”过滤,支持范围很广。需要注意,进程名可能不叫Code.exe,以你的版本实际进程名为准。

5. 常见问题与排查思路

在实际运行时,很多问题不一定出在 Python 逻辑上,而更多是 Windows 窗口机制本身的特性。下面把高频问题整理成一张表,再做具体说明。

问题现象常见原因解决思路
悬浮窗不出现找不到目标进程或窗口标题不匹配用任务管理器确认进程名,放宽 keyword 关键词
悬浮窗位置偏了半个屏幕DPI 缩放导致坐标不一致在 QApplication 创建前设置 DPI 感知
跟随有延迟轮询间隔太长将 QTimer 间隔降到 200ms,但避免低于 100ms
拖动目标窗口时悬浮窗闪烁窗口频繁 show/hide 或 move 太频繁优化隐藏逻辑,只在需要时更新坐标
鼠标点击穿透后无法关闭窗口仍然拦截不到鼠标事件用快捷键 Esc 关闭,或用托盘菜单
目标窗口最小化后悬浮窗不消失没有检查最小化状态调用 IsIconic 判断并隐藏悬浮窗
找错窗口,跟随到另一个同名进程多个同进程实例,标题过滤不严谨增加 PID 指定或更精确的窗口标题匹配

5.1 悬浮窗不出现

这是最常见的问题。原因通常是codex.exe并不是运行 Codex CLI 的进程。如果你是在 Windows Terminal、VS Code 集成终端里运行 Codex,那么真正的窗口进程是WindowsTerminal.exeCode.exe,而不是codex.exe

排查方法:

  • 在命令行执行tasklist | findstr codex,看进程是否真实存在;
  • 用 Spy++ 或任务管理器查看具体进程名;
  • keyword改成窗口标题里稳定出现的单词。

如果进程名确实不是codex.exe,但窗口标题里有 “codex”,也可以只按标题过滤。你可以把_find_pid_by_process_name改成返回None,然后枚举窗口时直接过滤标题,就能实现“无进程名限制,只看标题”的跟随模式。

5.2 位置偏移与 DPI

如果你在 100% 缩放的电脑上开发,在 150% 缩放的电脑上运行,就会踩到 DPI 问题。核心原因就是 Qt 和GetWindowRect使用了不同坐标体系。

解决办法已经写在enable_dpi_awareness()里。如果仍然偏移,检查 Windows 显示设置里的“更改文本、应用等项目的大小”是否是 100% 以上,并确认SetProcessDpiAwareness(2)有没有被异常吞掉。

5.3 点击穿透与快捷键冲突

开启WindowTransparentForInput后,悬浮窗本身接收不到鼠标点击,但键盘快捷键仍能生效。如果你的 Esc 或 F2 被其他软件占用,快捷键可能失效。此时可以改用全局热键库或托盘图标,但不建议为了一个小工具引入过重依赖。

5.4 多显示器负坐标场景

如果目标窗口从主屏幕拖到了左侧扩展屏,窗口坐标可能是负数,比如(-1920, 100)GetWindowRect和 Qt 的move()都能处理负坐标,不会出问题。但如果你的悬浮窗宽度计算不当,可能把窗口移出屏幕边界。建议在代码里增加一个屏幕边界钳制逻辑。

from PySide6.QtWidgets import QApplication def clamp_to_screen(self, x, y): screen = QApplication.primaryScreen().availableGeometry() if x < screen.left(): x = screen.left() if y < screen.top(): y = screen.top() return x, y

这里只是示例思路,实际多显示器环境还要考虑不同屏幕的 DPI 单独设置。

6. 工程化与最佳实践

6.1 性能与轮询节奏

窗口跟随工具对实时性要求并不高。300ms 间隔已经非常流畅,且 CPU 占用几乎可以忽略。如果你要跟的是一个快速移动的窗口,比如录屏软件,可以降到 150ms;再低就容易出现拖动时悬浮窗“抖动”的效果。

不建议用while True + sleep代替 QTimer。原因有两个:

  • Qt 事件循环需要时间处理 move、show 等界面操作,阻塞循环会导致界面卡顿;
  • QTimer 能自然与 Qt 的绘制周期对齐,减少闪烁。

如果以后要同时跟随多个窗口,可以用一个 QTimer 遍历多个进程,而不是为每个窗口创建独立线程。

6.2 处理目标窗口关闭与最小化

从健壮性角度看,必须处理以下情况:

  • 目标窗口不存在;
  • 目标窗口存在但最小化;
  • 目标窗口被关闭后重新打开;
  • 多个目标窗口同时存在。

示例代码里用hide()而不是close()处理目标窗口隐藏,这样目标窗口再次出现时,悬浮窗还能继续复用。不要每次销毁重建 QWidget,那会增加不必要的复杂度。

6.3 日志记录

桌面小工具最容易出现“本地能跑、别人电脑上不能跑”的问题。建议使用 Python 标准库logging记录关键路径:

import logging logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(message)s") logging.info("target window not found, process=%s", self.process_name)

这样在用户反馈“悬浮窗没出现”时,可以直接看日志判断是进程名问题还是窗口标题过滤问题。

6.4 授权与安全边界

这类工具本质上是“读取其他进程窗口信息”并“移动自己的窗口”,属于常规桌面自动化,不涉及注入、Hook、密码读取等敏感行为。但作为工程实践,仍要遵守几个边界:

  • 只读取窗口标题和矩形坐标,不读取目标进程内部数据;
  • 不做键盘记录、鼠标模拟、后台监听;
  • 不在未授权环境中部署;
  • 发布给别人使用时,建议标明工具用途和运行权限要求。

如果要读取的窗口属于管理员权限进程,普通权限的 Python 进程可能拿不到句柄,需要以管理员身份运行。这里不推荐让工具主动请求管理员权限,应该在文档中说明。

6.5 打包分发

如果要给同事用,可以用PyInstaller打包成独立 exe:

pip install pyinstaller pyinstaller -F -w src/main.py --name codex-follower

其中-w表示不显示控制台窗口。打包后注意测试 DPI 感知是否仍然生效,因为某些打包方式会改变进程的 DPI 设置。

7. 总结与后续优化方向

这个小工具解决的核心问题,是让一个悬浮窗始终跟随另一个窗口移动。背后涉及的桌面 API 和 UI 细节不算难,但组合起来却非常实用。

通过本文,你已经掌握:

  • 用 psutil 查找目标进程 PID;
  • 用 EnumWindows 遍历顶层窗口并匹配 PID;
  • 用 GetWindowRect 读取窗口坐标;
  • 用 PySide6 创建无边框、置顶、可点击穿透的悬浮窗;
  • 用 QTimer 做低频轮询和位置同步;
  • 用 DPI 感知解决多缩放环境下的坐标偏差。

后续如果想继续完善,可以往这几个方向扩展:

  • 给悬浮窗增加可配置文本,例如显示当前环境变量、最近一条命令执行状态;
  • 支持配置文件,把进程名、关键词、偏移量、是否穿透放到一个config.json中;
  • 增加托盘图标,让悬浮窗在无目标窗口时也能从托盘恢复;
  • 增加多目标跟随能力,比如同时跟随 Codex 窗口和测试日志窗口;
  • 做跨平台适配,macOS 上可以使用 Quartz 窗口 API,Linux 上则可以借助 X11 的_NET_CLIENT_LIST

如果你在终端环境里经常需要盯着多个窗口的状态,这个跟随悬浮窗的思路可以给你省下不少切换焦点的时间。动手改一改参数,让它变成你自己的生产力小工具,会比直接下载一个现成的软件更有意思。欢迎在评论区分享你的扩展玩法。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/31 4:45:45

小波变换在局部放电信号去噪与特征提取中的工程实践

简介&#xff1a;本资源是一份面向电力系统高年级本科生、研究生及绝缘检测工程师的局部放电&#xff08;PD&#xff09;信号小波去噪实践方案&#xff0c;聚焦高压设备绝缘状态评估中的关键信号处理难题。采用Daubechies 5&#xff08;db5&#xff09;小波进行5层多尺度分解&a…

作者头像 李华
网站建设 2026/8/31 4:45:27

EMIF接口设计实战:从时序配置到DSP+FPGA调试避坑指南

简介&#xff1a;本资源为面向FPGA开发初学者与中级工程师的EMIF&#xff08;外部存储器接口&#xff09;实战设计案例&#xff0c;聚焦Xilinx平台下SRAM/DRAM类存储器的可靠通信实现&#xff0c;解决FPGA系统中高速外存接入这一核心工程问题。压缩包共含多个关键文件&#xff…

作者头像 李华
网站建设 2026/8/31 4:45:08

浩鲸科技校招研发岗笔试复盘:题型分布、高频考点与编程题解法

又是一年秋招季&#xff0c;不少同学在群里问浩鲸科技的笔试该怎么准备。我翻到自己当年整理的那份浩鲸科技2019校招普通研发类笔试题复盘&#xff0c;发现很多内容放到现在依然有参考价值。这家公司的前身是中兴软创&#xff0c;后来引入阿里投资更名浩鲸科技&#xff0c;主做…

作者头像 李华
网站建设 2026/8/31 4:43:13

22、功耗调试工具:使用 Perf 进行功耗事件采样、使用 Trace32 进行功耗问题定位、使用 HW 功耗仪(如 Monsoon)进行实测

上一讲我们聊了软件层的功耗抓取工具,这一讲咱们来点硬核的。说白了,就是当你发现系统功耗不对劲,但又不知道是哪段代码在捣鬼时,该拿什么武器去定位。 我个人习惯把功耗调试分成三个层次:事件级、指令级、物理级。Perf 负责事件级,Trace32 负责指令级,Monsoon 这类硬件…

作者头像 李华
网站建设 2026/8/31 4:41:51

Atlas:用自构建智能体驱动运营可观测性

这次我们来看一个很有意思的开源项目&#xff1a;Atlas。它不是又一个监控告警系统&#xff0c;而是把observability&#xff08;可观测性&#xff09;和self-building agents&#xff08;自构建智能体&#xff09;结合到一起&#xff0c;面向初创公司运营场景的观测工具。简单…

作者头像 李华
网站建设 2026/8/31 4:40:03

心智世界模型:从预测像素到预测意图的AI新路线

世界模型之后&#xff0c;下一个方向是心智世界模型&#xff1f;牛津、NUS给出了一条新路线如果你最近在关注 AI 前沿&#xff0c;大概率会反复看到一个词&#xff1a;世界模型。从自动驾驶、机器人操作到视频生成&#xff0c;几乎所有强调"AI 要理解物理世界"的工作…

作者头像 李华