以零长度调用 write() 会产生什么后果?
在 Linux write()
函数中相当高的级别,它会过滤掉写入 0 长度缓冲区的请求。 这是有道理的。 谁愿意操作系统浪费时间钻探各层只是为了确定没有任何工作要做?
嗯……我。
它与 Linux 内核中的 I2C 写入确认轮询有关; 并且发现,如果握手错误,地址(在数据之前在总线上发送)将给出错误,则位绑定的 I2C 驱动程序将给出潜在有用的返回代码。
人们可以在地址之后发送虚拟数据,但不能使用我正在使用的设备。 (也许我会尝试阅读......)。
所以问题是:如果内核允许零 (0) 长度写入,将会释放什么样的地狱?
At fairly high level in the Linux write()
function, it filters out requests for writing 0 length buffers. Which makes sense. Who'd want to the OS wasting its time drilling through layers only to determine there is no work to be done?
Well ... me.
It's related to I2C write acknowledge polling in Linux Kernel; and the discovery that the bit-banged I2C driver will give a potentially useful return code if the address (sent on the bus before data) will give an error if the handshaking is wrong.
One could send dummy data after the address, but not with the device I'm using. (Perhaps I'll try a read ...).
So the question is: What sort of hell would be unleashed if the kernel were to allow zero (0) length writes?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
您所描述的内容本质上与感染多个需要不可预测的内存量的 Windows API 的邪恶行为相同。 实践是在没有缓冲区来放置工作的情况下调用它们,它们无论如何都会完成工作,不存储结果,而是计算沿途所需的字节数。 然后分配该大小的缓冲区,并在知道大小的情况下再次使用该缓冲区调用该函数。
这是无法形容的邪恶。 这是相当于腐朽的官僚机构的计算机编程,每个部门都要求您填写一份表格,其中的信息与您提供给前一个部门的信息大部分相同,但由于每个表格上都有一些不同的信息,他们不会只是拿走你给其他人的表格的副本。 噗!
程序员的时间很昂贵,CPU 的时间很便宜。 要求程序员编写相同的 API 调用 N 次,以弄清楚 API 本身可以自行解决的某种世界状态,试图颠覆这一现状。
那么,最佳实践是让驱动程序尽一切努力确保 write() 成功。 如果可以通过检查世界的某些状态来提前预测它不会成功,那么也许应该是 ioctl()。
What you're describing amounts to essentially the same sort of evil that infests several Windows APIs that need unpredictable amounts of memory. The practice is to call them with no buffer to place their work in, they do the work anyway, without storing the results, but counting the number of bytes they'd need along the way. Then you allocate a buffer of that size, and call the function again with the buffer, knowing the size.
This is indescribably evil. It's the computer programming equivalent of a decayed bureaucracy, where each department requires you to fill out a form that has most of the same information on it as the one you gave to the previous department, but since there is some different info on each form, they won't just take a copy of the form you gave the other guys. Ptui!
Programmer time is expensive, CPU time is cheap. Requiring programmers to write the same API call N times to suss out some world state that the API itself could work out on its own tries to flip this on its head.
Best practice, then, is to have the driver do everything it can to make sure your write() succeeds. If it's possible to predict in advance that it cannot succeed by checking some state of the world, maybe that should be an ioctl().
只是为了结束,我同意 Warren Young 更新驱动程序并发布补丁的想法(当我得到一轮tuit)。
Just for the sake of closure, I'm going with Warren Young's idea of updating the driver and publishing the patch (when I get a round tuit).
我认为很少 - 如果在某些驱动程序中写入的缓冲区也具有零可用空间,那么零长度写入可能会被阻塞。 在这种情况下,禁止零长度写入可以使事情变得更简单 - 并避免大量浪费的工作。
为什么不直接删除该检查,看看到底会发生什么样的地狱呢? :)
Very little, I'd think - it might be possible that a zero-length write would block if the buffer it's writing to has zero available space as well, in some drivers. Disallowing zero-length writes could make things simpler in cases like that - as well as avoiding a lot of wasted work.
Why not just remove that check and see what kind of hell actually breaks loose? :)
这不是一个严肃的答案:你可能会得到一个类似 touch 的程序:P
not a serious answer: you might get a program like touch :P
我不寒而栗地建议使用 ioctl() 但这不是一个更好的接口来获取有关接口的状态信息吗?
I shudder to suggest an ioctl() but wouldn't that be a better interface for obtaining state information about the interface?
零长度写入意味着什么? 一般来说,写入意味着数据传输......并且我确信如果不检查它并因此捕获驱动程序的大多数错误输入会导致更多问题。 y
如果您需要的是单比特信息“执行此操作”调用,我认为 ioctl 是可行的方法。 这并不漂亮,但是你能做什么呢?
或者,采用核选项,使用 mmap() 并将整个内容移至用户空间。 开销低,您可以编写经典的 Poke 代码,例如“将 X 写入此寄存器”,这几乎看起来就是您所需要的。
What would a zero-length write mean? In general, write means transfer of data... and I am sure more problems would be caused by not checking for it and thus catching most lots of bad input to drivers. y
if it is a single-bit-of-information "do this" call you are after, I think ioctl is the way to go. It is not pretty, but what can you do?
Alternatively, take the nuclear option, use mmap() and move the whole thing into user-space. Low overhead, and you can write classic poke code like "write X to this register" which almost seems it is what you need.