ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
I have a program that reads from the serial port.
The program works fine but the read() is not blocked, i.e. if there is nothing to read it returns with -1.
Now I want that read() is blocked, and the function does not return until
something is read.
How can I do it?
I have tried with different open configurations and always the read returns when I want that remains waiting for something
fd=open("/dev/ttyS0", O_RDWR|O_NOCITY)
I have a program that reads from the serial port.
The program works fine but the read() is not blocked, i.e. if there is nothing to read it returns with -1. Now I want that read() is blocked, and the function does not return until something is read.
ta0kira is correct, you should check errno if you get a -1 from read. It it normal for read to set errno to EINTR. If this is the case, you can simply retry the read. For example
Code:
int iResult;
do
{
iResult = read(fd, buffer, size);
if (-1 == iResult)
{
if (EINTR == errno)
{
// Skip to the end of the do loop
continue;
}
// Handle real errors
}
} while (!condition);
Unless you supply O_NONBLOCK, read() calls always block. If you are in blocking mode and getting -1 from read, that indicates another error. Most likely, a -1 on a regular file that is being read in blocking mode will never recover. Check the errno, and try to resolve the cause of it.
int iResult;
do
{
iResult = read(fd, buffer, size);
if (-1 == iResult)
{
if (EINTR == errno)
{
// Skip to the end of the do loop
continue;
}
// Handle real errors
}
} while (!condition);
GNU has a built-in for this:
Code:
#define __USE_GNU
#include <unistd.h>
/* ... */
ssize_t read_size = -1;
TEMP_FAILURE_RETRY(read_size = read(/* ... */));
if (read_size == (ssize_t) -1)
{
/* process for error */
}
The strange thing is that "read(fd,buffer,size)" returns -1
and the errno is EAGAIN when I am not using O_NONBLOCK in:
fd= open("/dev/ttyS0",O_RDWR|O_NOCTTY).
As Matir says if I do not open with the O_NONBLOCK flag, read() should not
return until data are coming, is not it?
What I want is exactly that: that read() blocks until data is coming.
What flags should I use in open() to make the read() is blocked until data is coming?
The strange thing is that "read(fd,buffer,size)" returns -1 and the errno is EAGAIN when I am not using O_NONBLOCK in:
fd= open("/dev/ttyS0",O_RDWR|O_NOCTTY).
The "EAGAIN" means the serial port interface timed out and that you should read the serial port again if you want more data. Then the polling loop would look like this
Code:
int iResult;
do
{
iResult = read(fd, buffer, size);
if (-1 == iResult)
{
if ((EINTR == errno) || (EAGAIN == errno))
{
// Skip to the end of the do loop
continue;
}
// Handle real errors
}
} while (!condition);
Even if you forcibly set the file descriptor to block using ta0kira's scheme, the serial port interface can still time out. We do a lot of serial port interfacing at work and we have to deal with these issues.
Last edited by David1357; 08-26-2008 at 12:31 PM.
Reason: Remove "not" before "block".
This is a processor-hogging operation. I can't think of any time where you'd use the bolded statement in a loop unless you provide some sort of timing control with nanosleep, etc.
ta0kira
The strange thing is that "read(fd,buffer,size)" returns -1 and the errno is EAGAIN when I am not using O_NONBLOCK in:
fd= open("/dev/ttyS0",O_RDWR|O_NOCTTY).
Are you using termios to set the proper baud rate and cfmakeraw to make the interface to allow single character reads?
The more I thought about your problem, the more I started thinking that you opened a serial port like it was a simple file and tried to read it. You may still have some work ahead of you to achieve your goal.
Not if the serial port interface has a long timeout. Have you recently written code to read from a serial port on Linux?
No I haven't, but what guarantee do you have that the device will have a long timeout, or for that matter, will have any delay before returning? You can't guarantee anything from the user-space program other than that what you're opening is a character device. I would at the very least check the time difference with the first iteration to make sure EAGAIN actually involved a timeout rather than just assume that it does. You're making an assumption about the behavior of a device based on a standard implementation and a standard device name, but nothing says that it must be that way (unlike e.g. the specifications for POSIX functions,) and though the possibility of it being otherwise is slight, you should still take that into account somehow.
ta0kira
PS That pretty much goes without saying for every while loop that doesn't have any inherent finiteness to it. You can reiterate past EINTR because POSIX is very specific with its usage and it clears every iteration, and blocking provides timing control. EAGAIN can reappear indefinitely within a finite period of time and is not effected by the number of retries but it's also explicitly associated with a lack of blocking, so even a remote possibility of uncontrolled iteration should be mitigated.
No I haven't, but what guarantee do you have that the device will have a long timeout, or for that matter, will have any delay before returning?
You can't guarantee anything, but I wrote a simple example program that opened "/dev/ttyUSB0" and tried to read from it. It blocked completely. Usually that is the case.
As I said in my most recent post, the symptoms sankari27 described stink like an improperly setup serial port. Also, I forgot that EAGAIN sometimes means that you passed in a buffer that is too small to handle the data from the read.
Serial port programming is usually a lot of trial and error because not all drivers work the same way. That's why it's best not to shoot your mouth of if you have never done it.
But the call to open() does not include O_NONBLOCK by default, so the default mode is blocking.
I tried to find a reference that would back up that assertion. However "K&R 2nd Ed" and "Advanced Programming in the Unix Environment 2nd Ed" failed to produce such a reference. I was reluctant to begin digging through glibc source to prove my point.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.