第 49 / 120 课 · 并发、IPC 与异步 I/O。返回课程合集。
机制与资源关系
read、write 返回的是本次处理字节数,可能小于请求。非阻塞无数据时可能返回 EAGAIN,EINTR 则提示被信号打断。EOF、暂时不可读和真实错误必须分开;流式传输没有天然消息边界。
实际用法与观察入口
以下是操作说明;先确认执行环境、工具帮助和目标对象。设备名、PID、地址及项目名示例需要按实际替换,不能将整段命令当通用板端脚本执行。
|
输出解读与排查顺序
循环处理已完成偏移,检查返回值为零及 errno。EAGAIN 应等待就绪,不能无延时忙轮询。设备接口可能有自己的读写约定,需查对应驱动 ABI。
情境推演
请求读 100 字节只返回 12 字节是合法短读。应保留这 12 字节并继续组帧;返回 0 表示相应流结束,返回 -1 才查 errno。不能把非满长读一律当错误丢掉。
练习与参考分析
实验读取空的非阻塞 pipe,确认 EAGAIN;写入后读取数据,关闭写端后确认 EOF。参考结论:这三种状态不能合并成一次“读取失败”。
独立实验包
主机 Linux 的有界 C 实验;不访问真实外设,不代表板端时序或性能。 默认入口、源文件和实际运行记录都在下载包中。
实验:阻塞、非阻塞与短读写
查看完整代码:main.c
int main(void) {
int p[2]; CHECK(pipe2(p, O_NONBLOCK | O_CLOEXEC) == 0);
char buf[8]; errno=0;
CHECK(read(p[0], buf, sizeof(buf)) == -1 && errno == EAGAIN);
CHECK(write(p[1], "abc", 3) == 3);
CHECK(read(p[0], buf, sizeof(buf)) == 3 && memcmp(buf,"abc",3) == 0);
CHECK(close(p[1]) == 0);
CHECK(read(p[0], buf, sizeof(buf)) == 0); CHECK(close(p[0]) == 0);
puts("empty=EAGAIN; read=3 bytes; all writers closed=EOF");
return 0;
}
在项目根目录执行;下载包解压后,在解压目录执行 sh run.sh。
cd 'content/posts/驱动、bootloader、文件系统/嵌入式Linux系统工程/049-阻塞、非阻塞与短读写/code' && sh run.sh
官方资料与版本边界
内核、工具和厂商 BSP 的支持范围需分别核对。参考资料可能对应较新版本;不要据此推定旧 BSP 支持所有接口。