根本原因是串口流默认阻塞,需用stream_set_blocking($fp, false)设为非阻塞;之后用fread()读取并配合usleep(10000)防忙等,避免popen/fgets方案,并手动实现Modbus等上层协议帧解析。
PHP 读 RS485 设备时卡住(比如 fgets() 一直不返回),根本原因不是“RS485 协议问题”,而是串口文件描述符默认处于阻塞模式——只要没收到完整数据,读操作就挂起整个 PHP 进程。解决它,必须显式启用非阻塞 I/O。
stream_set_blocking() 设置串口为非阻塞PHP 操作串口(如 /dev/ttyUSB0)本质是打开一个流资源,而非直接调用系统 socket。不能用 fcntl() 或 ioctl(),必须使用 PHP 原生流控制函数:
stream_set_blocking($fp, false) 是唯一可靠方式;设为 false 后,fread()、fgets() 等读取函数在无数据时立即返回空字符串(""),而不会等待fopen() 打开串口后、任何读写前调用,顺序错误会导致设置失效启用非阻塞后,不能直接 while (fgets($fp)) { ... }——这会瞬间跑满 CPU。必须加条件控制或延时:
$data = fread($fp, 256); if ($data === false || $data === '') { usleep(10000); continue; }
usleep(0) 或空 continue:某些内核版本下会退化为忙等,usleep(10000)(10ms)是较安全的底线stream_select() 使用,单纯靠 usleep() 无法精准计时popen() + fgets() 在 RS485 场景中大概率失
败很多开发者试图用 popen('stty -F /dev/ttyUSB0 9600 raw -echo; cat /dev/ttyUSB0', 'r') 绕过 PHP 串口限制,但这会引入严重问题:
cat 默认按行缓冲,而 RS485 报文无换行符,fgets() 会永远等不到 \n,实际仍是逻辑阻塞\0 字节(fgets() 遇到 \0 就截断),Modbus/RTU 帧里常见该字节fopen() + stream_set_blocking() + fread(),配合 stream_set_timeout() 控制单次读最大等待时间真正容易被忽略的是:非阻塞只是“不卡住”,不代表“自动组帧”。RS485 是物理层,上层协议(如 Modbus RTU)的帧头识别、长度解析、CRC 校验仍需你手动实现;否则即使读到了字节,也可能是半帧或粘包数据。
# php
# linux
# 字节
# usb
# stream
# 为什么
# echo
# if
# while
# fopen
# fgets
# continue
# 字符串
# 循环
# 串口
# 设为
# 这会
# 根本原因
# 的是
# 不代表
# 仍是
# 不能用
# 而非
# 读到
相关栏目:
【
Google疑问12 】
【
Facebook疑问10 】
【
网络优化76771 】
【
技术知识130152 】
【
IDC云计算60162 】
【
营销推广131313 】
【
AI优化88182 】
【
百度推广37138 】
【
网站推荐60173 】
【
精选阅读31334 】
相关推荐:
Windows11怎样开启游戏模式_Windows11游戏模式开启攻略【方法】
php命令行怎么运行_通过CLI模式执行PHP脚本的步骤【说明】
如何在 Go 中可靠地测试含 time.Time 字段的结构体
Win11怎么关闭键盘按键音_Win11禁用打字声音反馈【教程】
MAC怎么在照片中添加水印_MAC自带编辑工具文字水印叠加【方法】
Mac如何整理桌面文件_Mac使用堆栈功能一键整理
Win11怎么关闭自动调节亮度_Windows11禁用内容自适应亮度
Windows10如何更改开机密码_Win10登录选项更改密码教程
如何在Golang中实现并发消息队列消费者_Golang channel消息消费实践
Windows10系统怎么查看已安装更新_Win10控制面板卸载补丁
Win11怎么关闭用户账户控制UAC_Windows11更改通知设置等级
微信短链接怎么还原php_用浏览器开发者工具抓包获取【方法】
Win11怎么设置开机密码_Windows11账户登录选项PIN码
php转mp4怎么设置帧率_调整php生成mp4视频帧率说明【说明】
Win11怎么关闭系统推荐内容_Windows11开始菜单布局设置
如何在Golang中写入XML文件_生成符合规范的XML数据
Windows10电脑怎么连接蓝牙设备_Win10蓝牙配对失败解决方法
Mac的“预览”如何合并多个PDF_Mac文件处理技巧【效率】
Win11怎么开启移动热点_Windows11共享网络给手机设置教程
php会话怎么开启_session_start函数的作用与使用时机【方法】
如何用正则与预处理结合精准拦截拼接式垃圾域名
Windows资源管理器总是卡顿或重启怎么办?(修复方法)
Python代码测试策略_质量保障解析【教程】
Mac自带的词典App怎么用_Mac添加和使用多语言词典【技巧】
Windows10怎么备份注册表_Windows10注册表备份步骤【教程】
php怎么下载安装后无法解析php文件_服务器配置检查【解答】
C#如何使用XPathNavigator高效查询XML
windows系统如何安装cab更新补丁_windows手动安装更新包教程
Windows怎样关闭锁屏广告_Windows关闭锁屏广告方法【教程】
Python文件和流处理指南_高效读写大体积数据文件
如何使用Golang table-driven fuzz测试_多数据随机化发现缺陷
Win11怎么设置快速访问_Windows11文件资源管理器主页
Windows10怎样设置家长控制_Windows10家长控制设置方法【指南】
Windows如何查看和管理已安装的字体?(字体文件夹)
Python安全爬虫设计_IP代理池与验证码识别策略解析
Win10系统映像怎么恢复 Win10使用系统映像还原电脑【指南】
Win11怎么设置虚拟键盘_打开Win11屏幕键盘操作指南【技巧】
php中::能用于接口静态方法吗_接口静态方法调用规则【操作】
Windows10系统怎么查看CPU核心数_Win10逻辑处理器数量查看
Win11怎么设置任务栏透明_Windows11使用工具美化任务栏
Python字符串操作教程_切片拼接与格式化详解
PHP cURL GET请求:正确设置认证与自定义请求头的完整教程
Win10系统怎么查看端口状态_Windows10 CMD查看网络连接
Win11如何设置系统声音_Win11系统声音调整教程【攻略】
Mac版Final Cut Pro入门_Mac视频剪辑基础操作【教程】
如何使用Golang recover捕获panic_防止程序崩溃并处理异常
Windows10如何更改盘符名称_Win10重命名硬盘分区卷标
Windows怎样关闭开始菜单推荐广告_Windows关闭开始菜单推荐设置【步骤】
Win11开机Logo怎么换_Win11自定义启动画面工具【高级】
Linux如何安装Tomcat应用服务器_Linux环境部署与端口修改【教程】
2026-01-01
致胜网络推广营销网专注海外推广十年,是谷歌推广.Facebook广告全球合作伙伴,我们精英化的技术团队为企业提供谷歌海外推广+外贸网站建设+网站维护运营+Google SEO优化+社交营销为您提供一站式海外营销服务。