LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
LinkBack Search this Thread
Old 08-25-2008, 12:02 PM   #1
sankari27
LQ Newbie
 
Registered: Aug 2008
Posts: 3

Rep: Reputation: 0
to make the system call "read()" blocked


Hi,

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)

Thanks in advance.
 
Old 08-25-2008, 01:27 PM   #2
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: Slackware64 13.37, Kubuntu 10.04
Posts: 2,944

Rep: Reputation: Disabled
You should print out strerror(errno) to see what the error is.
ta0kira
 
Old 08-25-2008, 01:54 PM   #3
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,285
Blog Entries: 1

Rep: Reputation: 103Reputation: 103
Quote:
Originally Posted by sankari27 View Post
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);
 
Old 08-25-2008, 02:31 PM   #4
Matir
Moderator
 
Registered: Nov 2004
Location: Kennesaw, GA
Distribution: Ubuntu
Posts: 8,502

Rep: Reputation: 110Reputation: 110
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.
 
Old 08-25-2008, 04:31 PM   #5
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: Slackware64 13.37, Kubuntu 10.04
Posts: 2,944

Rep: Reputation: Disabled
Quote:
Originally Posted by David1357 View Post
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);
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 */
}
ta0kira
 
Old 08-26-2008, 05:08 AM   #6
sankari27
LQ Newbie
 
Registered: Aug 2008
Posts: 3

Original Poster
Rep: Reputation: 0
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?

Thanks.
 
Old 08-26-2008, 06:28 AM   #7
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: Slackware64 13.37, Kubuntu 10.04
Posts: 2,944

Rep: Reputation: Disabled
Nothing says a device must open in blocking mode by default (as far as I know.) If I were you, I'd set it to blocking manually with fcntl.
Code:
#include <fcntl.h>

/* ... */

if (fcntl( fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK ) == -1)
{
/* device can't be set to blocking */
}
ta0kira

Last edited by ta0kira; 08-26-2008 at 06:32 AM.
 
Old 08-26-2008, 09:45 AM   #8
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,285
Blog Entries: 1

Rep: Reputation: 103Reputation: 103
Quote:
Originally Posted by sankari27 View Post
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".
 
Old 08-26-2008, 11:51 AM   #9
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: Slackware64 13.37, Kubuntu 10.04
Posts: 2,944

Rep: Reputation: Disabled
Quote:
Originally Posted by David1357 View Post
Code:
         if ((EINTR == errno) || (EAGAIN == errno))
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
 
Old 08-26-2008, 12:30 PM   #10
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,285
Blog Entries: 1

Rep: Reputation: 103Reputation: 103
Quote:
Originally Posted by ta0kira View Post
This is a processor-hogging operation.
Not if the serial port interface has a long timeout. Have you recently written code to read from a serial port on Linux?
 
Old 08-26-2008, 06:51 PM   #11
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,285
Blog Entries: 1

Rep: Reputation: 103Reputation: 103
Quote:
Originally Posted by sankari27 View Post
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.
 
Old 08-26-2008, 07:09 PM   #12
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: Slackware64 13.37, Kubuntu 10.04
Posts: 2,944

Rep: Reputation: Disabled
Quote:
Originally Posted by David1357 View Post
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.

Last edited by ta0kira; 08-26-2008 at 07:17 PM.
 
Old 08-26-2008, 07:59 PM   #13
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,285
Blog Entries: 1

Rep: Reputation: 103Reputation: 103
Quote:
Originally Posted by ta0kira View Post
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.
 
Old 08-26-2008, 08:04 PM   #14
Mr. C.
Senior Member
 
Registered: Jun 2008
Posts: 2,529

Rep: Reputation: 57
Quote:
Originally Posted by ta0kira View Post
Nothing says a device must open in blocking mode by default (as far as I know.)
But the call to open() does not include O_NONBLOCK by default, so the default mode is blocking.
 
Old 08-26-2008, 08:10 PM   #15
David1357
Senior Member
 
Registered: Aug 2007
Location: South Carolina, U.S.A.
Distribution: Ubuntu, Fedora Core, Red Hat, SUSE, Gentoo, DSL, coLinux, uClinux
Posts: 1,285
Blog Entries: 1

Rep: Reputation: 103Reputation: 103
Quote:
Originally Posted by Mr. C. View Post
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.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
list file system linux supports "please give the command or system call" varun_shrivastava Linux - General 4 01-09-2007 07:28 AM
Edit "read-only" /etc/fstab from "System Recovery#" (without boot cd?) charlweed Linux - General 1 12-31-2006 05:57 PM
"NIM thread blocked" & "Deadman Switch (DMS) close to trigger" errors sosborne Linux - Networking 1 06-28-2006 02:07 PM
Any way to get "Alice"; "Call of Duty" series and "Descent 3" to work? JBailey742 Linux - Games 13 06-23-2006 01:34 PM


All times are GMT -5. The time now is 05:36 AM.

Main Menu
 
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: @linuxquestions
Open Source Consulting | Domain Registration