You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ubuntu 20.04下pyserial如何正确实现串口设备独占打开

Ubuntu 20.04 下 pyserial 串口独占问题解答

前两种方案不生效的核心原因

  • 关于pyserial内置的exclusive=True参数
    这个参数在Linux平台底层是调用ioctl(fd, TIOCEXCL)给串口设备设置内核级排他标记,设计逻辑是阻止非root进程后续重复open该设备,这个机制本身就不会在/var/lock下生成任何锁文件。它失效的常见场景有三个:

    • 其他访问串口的进程是root身份运行:TIOCEXCL标记不会拦截root用户的open调用,只要用sudo启动的串口程序就能直接绕过这个限制打开设备
    • 部分USB转串口芯片的驱动对TIOCEXCL的支持存在缺陷,标记设置成功但没有实际拦截效果
    • 使用的pyserial版本低于3.0,该版本之前根本没有实现POSIX平台下的exclusive逻辑,传了参数也不生效
  • 关于fcntl.flock加文件锁的方案
    你贴的代码首先存在语法错误(except Exception a e是非法写法,正确写法是except Exception as e),但就算修正语法也不会达到预期效果,核心原因是:flock()实现的是劝告性锁,不是内核强制锁。只有所有访问串口的程序都主动调用flock检查锁状态时,互斥才会生效。绝大多数串口工具打开设备时根本不会去检查这个flock锁,直接读写设备文件,你的锁自然拦不住任何操作,同样这个机制也不会生成/var/lock下的锁文件。另外flock锁会在进程退出、文件描述符关闭时被内核自动释放,不会留残留。

手动创建/var/lock锁文件是不是通用独占方案

这是传统Unix/Linux串口生态里长期沿用的用户态君子协定,不是内核级强制的通用方案:

  • 这个约定最早来自UUCP通信套件,规则是程序打开串口前先检查/var/lock/LCK..<设备名>是否存在,如果存在就读取文件内存储的PID,判断对应进程是否存活,存活则拒绝打开,进程不存在则清理旧锁再创建自己的锁。minicom、picocom等传统串口工具默认遵守这个约定。
  • 它的局限性非常明显:
    • 不遵守该约定的程序完全无视锁文件,照样可以打开串口读写,没有任何强制拦截能力
    • 你当前写的锁逻辑有明显缺陷:没有提前检查锁文件是否存在、没有校验锁内PID的存活状态,直接覆盖写入文件,很容易破坏其他正常程序创建的锁,起不到互斥作用
    • Ubuntu 20.04下/var/lock是/run/lock的兼容软链接,普通用户虽然有权限创建文件,但如果锁文件权限设置不当,其他用户运行的程序无法读取锁内容,要么直接绕过锁开串口,要么误报权限错误

脚本退出时是否需要手动删除锁文件

必须手动删除,而且不能只在正常退出逻辑里处理:

  • 这类用户态锁文件不会因为进程退出被系统自动清理,如果不主动删除,会残留无效锁文件,后续遵守锁约定的串口工具检测到锁文件存在,会直接判定串口被占用无法打开。
  • 不能依赖其他程序帮你清理残留锁:虽然部分实现完善的工具会检查锁文件内的PID是否存活,自动清理死进程留下的锁,但你不能保证所有访问串口的程序都有这个逻辑,自己创建的锁自己清理是最稳妥的方案。
  • 清理逻辑需要覆盖所有退出场景:正常执行完成、抛出异常崩溃、被SIGINT/SIGTERM等信号强制终止时,都要触发锁文件删除操作,避免残留。
  • 额外注意:写入锁文件时建议将文件权限设置为0644,保证所有用户的进程都能读取到锁内的PID信息,避免权限问题导致锁机制失效。

内容的提问来源于stack exchange,提问作者yyuankm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.03 07:57:28