views:

198

answers:

6

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 it's time drilling through layers only to determine there is no work to be done?

Well ... me.

It's related to this question; 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?

A: 

not a serious answer: you might get a program like touch :P

Charles Ma
+1  A: 

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? :)

bdonlan
+3  A: 

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
+1 hardware workarounds belong in the kernel ... but if it doesn't, and this is a very old (unmaintained) kernel, then it may be reasonable to workaround in userspace.
bdonlan
But in this case I don't actually want to write - so the windows analogy isn't applicable. I _really_ want to 'write' zero bytes. Otherwise I'm into changing the API by adding proprietary ioctl calls to an established driver.
Jamie
I don't think you *should* add a proprietary call to the driver. I think you should point this behavior out to the person maintaining that driver, and ask them for -- or provide them a patch for -- exposing this functionality. It could be called the I2C_PING function. ioctls() are one way to do this. /proc and sysctl are others.
Warren Young
Not a bad idea ... hmmmm ...
Jamie
A: 

I shudder to suggest an ioctl() but wouldn't that be a better interface for obtaining state information about the interface?

stsquad
+1  A: 

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).

Jamie
And this will help the rest of us eventually. Thank you
Tim Williscroft
A: 

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.

jakobengblom2