如何使read(2)调用强制返回EINVAL以模拟pidfd特性?
背景
我正在编写代码,在不支持pidfds的平台(旧版Linux、其他Unix系统)上模拟pidfds的某一项特性。
我做这件事的目的:一是为了在老旧平台上测试pidfd相关代码,二是作为个人挑战,主要是出于乐趣。
我明确不会重新实现pidfd的全部功能;我根本不关心进程、/proc或PID。我只想模拟pidfd文件描述符的三个行为之一:
- 若以阻塞模式打开,read调用会阻塞。
- 若以非阻塞模式打开或通过
fcntl设置为非阻塞模式,read调用返回EWOULDBLOCK。 - read调用明确返回
EINVAL。
第三点是难点,也是当前pidfds的一个特殊之处(很少有其他对象会为read()故意返回EINVAL)。
问题
我希望在其他类型的文件描述符上实现该行为(类型不限)。具体来说,我需要这样的文件描述符:
- 默认情况下遵循常规的
O_NONBLOCK(或非O_NONBLOCK)行为。 - 在对其执行某操作后,所有原本不会返回错误的
read(2)调用都将返回EINVAL,无论read(2)的参数如何。
事实证明这出奇地棘手。
已尝试方案
read(2)的手册页指出,在以下情况会返回EINVAL:
fd关联的对象不适合读取;或者文件以O_DIRECT标志打开,且buf指定的地址、count指定的值或文件偏移未正确对齐。
……或者在timerfd上调用read(2)时传入无效的缓冲区大小。
timerfd和O_DIRECT的情况都不满足我的要求,因为它们仅在向read(2)传入特定参数时才返回EINVAL,而我需要在所有非错误场景下都返回该值。
我还尝试了signalfds(未找到read返回EINVAL的情况)、inotify文件描述符(同样未找到),以及强制close(2)或shutdown(2)管道、FIFO和匿名套接字的各种组合。
不过我对POSIX的细节不太熟悉,所以完全有可能我遗漏了某些点,能让我已测试过的文件描述符类型返回EINVAL。
如果有能在BSD/MacOS上运行的解决方案更佳,不过任何方案都可以,哪怕是Linux专属或特定内核版本的方案。
我尝试了其他问题中的一些技巧,但它们大多生成EINVAL以外的错误码。
内容的提问来源于stack exchange,提问作者Zac B

