PDA

View Full Version : open(filePath, O_RDONLY) not blocking?



lsad
01-19-2011, 01:23 PM
I'm trying to block on a character device file until it becomes available. The kernel side appears to be working but in my process I call open(filePath, O_RDONLY) and it returns -1.
I though the open command should block until the file is available.

I tried polling the file with the open command and that works but uses to much cpu.

Anyone encountered this problem? Any suggestions? I was thinking I could block on a read, does anyone know how to make reads available on the kernel side?
Linux kernel 2.6.21.7.

Thanks.

anduril462
01-19-2011, 01:31 PM
Mods, I think this belongs on the Linux Programming board...

open should block unless you pass the O_NONBLOCK or O_NODELAY parameter. What is errno when open returns -1? This might give you a hint of what the problem is.

open doesn't guarantee that it will wait for a successful open however. If it determines that there is a problem other than "I'm not ready yet", it will happily return ASAP with a -1. Maybe the fact that the device isn't ready is treated like a general failure instead of "I'm not ready yet".

itCbitC
01-19-2011, 01:54 PM
Mode O_RDONLY implies that the character device is opened in blocking mode.
So as suggested try to get at the errno, which may clue you in on the problem.

lsad
01-19-2011, 03:49 PM
The errno is 6 which i think is ENXIO so it says 'no such device or address'. I guess the way I'm going about this is not going to work.

Do you know how to block on a read? Or any ideas for me to block on a character device from the user process and wake up when a condition is set in the kernel?

anduril462
01-19-2011, 04:06 PM
The errno is 6 which i think is ENXIO so it says 'no such device or address'. I guess the way I'm going about this is not going to work.
Yes, ENXIO is 6, and that's the right description. Have you read the man page for open? Here is what mine says:


ENXIO
O_NONBLOCK | O_WRONLY is set, the named file is a FIFO and no process has the file open for reading. Or, the file is a device special file and no corresponding device exists.


It looks like your device just isn't up and running.


Do you know how to block on a read?
All operations (open, read, write, close) will block by default unless you set the O_NONBLOCK or O_NODELAY flags when opening. That is the default behavior, so simply open the device without those flags to block on read or write.


Or any ideas for me to block on a character device from the user process and wake up when a condition is set in the kernel?
Unfortunately, device programming in Linux is not my strongest suit, but I think it depends on how is this mystery character device attached. Standard serial ports for example have no way of notifying the kernel there is something attached and ready. Some peripherals like USB do (at least, in my very simple understanding of it), but whether your program can take advantage of that, I don't know.

You could use a poll loop with a sleep or usleep in there to keep it from slamming the processor with IO requests. You can also look at using non-blocking file descriptors and the select function to achieve this "wait for something to happen" goal.

brewbuck
01-19-2011, 06:31 PM
It is up to the driver what happens here. Supposedly, unless you are using O_NONBLOCK, the driver should block until the open request can be satisfied. A driver could have a bug, though.

ENXIO sounds like maybe you're opening it in the wrong mode. Even if all you're going to do is read data, I've encountered devices where you had to open with O_RDWR. None of this is very strongly defined, anyway.

If you have source to the driver in question, grep for ENXIO and you should be able to figure out why it doesn't like your open() request.

itCbitC
01-20-2011, 11:24 AM
Here's what the manpge of open() has on my system:


[ENXIO]
O_NONBLOCK is set, the named file is a FIFO, O_WRONLY is set, and no process has the file open for reading.
[ENXIO]
The named file is a character special or block special file, and the device associated with this special file does not exist.

Methinks! the issue may be that the device, the character file maps to, may not be plugged in.

brewbuck
01-20-2011, 11:42 AM
I'd put very little stock in the man pages when it comes to devices, especially obscure ones. The Linux kernel doesn't have a formal driver acceptance test, which means there are zillions of drivers out there that don't behave quite how the manuals say they should.