This is a very interesting topic, and this stuff affects the interaction between kernel/driver and application.
First, let's talk about this concept. When the application is blocked, the program enters the sleep state. Possible blocks are:
1. Open
2. Read
3. Write
In general, file read/write is blocked. You can use the fcntl () function to set non-blocking read/write.In addition, the driver must be used together..
Okay. Let's take a look at the snippet of a real example.
Driver part: If o_nonblock is set for this file,-eagain is returned directly.
Static ssize_t scull_p_read (struct file * filp, char _ User * Buf, size_t count,
Loff_t * f_pos)
{
Struct scull_pipe * Dev = filp-> private_data;
If (down_interruptible (& Dev-> SEM ))
Return-erestartsys;
While (Dev-> Rp = Dev-> WP) {/* nothing to read */
Up (& Dev-> SEM);/* release the lock */
If (filp-> f_flags & o_nonblock)
{
Pdebug ("nonblock version read \ n ");
Return-eagain;
}
Pdebug ("\" % s \ "reading: Going to sleep \ n", current-> comm );
If (wait_event_interruptible (Dev-> INQ, (Dev-> RP! = Dev-> WP )))
Return-erestartsys;/* signal: Tell the FS layer to handle it */
/* Otherwise loop, but first reacquire the lock */
If (down_interruptible (& Dev-> SEM ))
Return-erestartsys;
}
/* OK, data is there, return something */
If (Dev-> WP> Dev-> RP)
Count = min (count, (size_t) (Dev-> WP-Dev-> RP ));
Else/* The write pointer has wrapped, return data up to Dev-> end */
Count = min (count, (size_t) (Dev-> end-Dev-> RP ));
If (copy_to_user (BUF, Dev-> RP, count )){
Up (& Dev-> SEM );
Return-efault;
}
Dev-> RP + = count;
If (Dev-> Rp = Dev-> end)
Dev-> Rp = Dev-> buffer;/* Wrapped */
Up (& Dev-> SEM );
/* Finally, awake any writers and return */
Wake_up_interruptible (& Dev-> outq );
Pdebug ("\" % s \ "did read % Li bytes \ n", current-> comm, (long) count );
Return count;
}
Application Section:
Use fcntl () to set the o_nonblock so that the o_nonblock will be returned immediately during read.
The returned value is determined. eagain indicates that you need to try again.
# Include <stdio. h>
# Include <unistd. h>
# Include <fcntl. h>
# Include <stdlib. h>
# Include <errno. h>
Char buffer [4096];
Int main (INT argc, char ** argv)
{
Int delay = 1, n, m = 0;
Int FD;
If (argc> 1)
Delay = atoi (argv [1]);
FD = open ("/dev/scullpipe0", o_rdwr );
Fcntl (FD, f_setfl, fcntl (FD, f_getfl) | o_nonblock );
While (1 ){
N = read (FD, buffer, 4096 );
Printf ("return value from read is % d \ n", N );
If (n> = 0)
M = write (1, buffer, n);/* stdout */
If (n <0 | M <0 )&&(Errno! = Eagain))
Break;
Sleep (Delay );
}
Perror (n <0? "Stdin": "stdout ");
Exit (1 );
}