When using socket or serial port, application code often uses select to determine whether data is received or not. What processing does the driver need? Can the application-layer users correctly determine whether data is received and read? Using select can monitor the changes in the file descriptor we need to monitor-read/write or exception.
First, a simple model is created. The application uses select to monitor whether the device is readable. When the device reads the data, it continues to listen. There is already a process that listens to the readable status of the device. You also need to open the terminal and use echo XXX>/dev/moddev60 to write data to the device. After the device driver receives the data, it controls the device to become readable, the Select process's select function returns a query that reads data from a readable device. The Code simplifies and does not handle concurrent Errors for demonstration.
Let's take a look at the application C code.
# Include <stdio. h> # include <fcntl. h> unsigned char rdbuf [1024]; int main (int * argc, char ** argv) {int FD, Res; fd_set fset; fd_zero (& fset ); FD = open ("/dev/moduledev60", o_rdwr); If (FD <0) {printf ("Open devices error \ n"); Return-1 ;} while (1) {fd_zero (& fset); fd_set (FD, & fset); Res = select (FD + 1, & fset, null, null ); if (RES =-1) {close (FD); Return-1;} else if (RES = 0) break; else {/* select returns a readable result */If (fd_isset (FD, & fset) {read (FD, rdbuf, 1024); printf ("read data: % s \ n ", rdbuf) ;}} close (FD); Return 0 ;}
Drive key code
struct file_operations ops={ .owner=THIS_MODULE , .read =fileops_read , .write=fileops_write, .poll =fileops_poll};
Declare_wait_queue_head (rdwait); // use static unsigned char rdbuf [1024] In poll_wait; // test the function of writing data from the read/write cache and reading data with the end of 0 static unsigned char rdflag = 0; // read Mark 0 unreadable cache no data 1 readable ssize_t fileops_read (struct file * filp, char _ User * buff, size_t count, loff_t * OFFP) {unsigned int Len; if (rdflag = 0) return 0; // return Len = strlen (rdbuf) directly if it is not readable; // read the cache string length. This model only serves as a string (0 ends) copy_to_user (buff, rdbuf, Len); // rdflag = 0; // clear flag return l En;} ssize_t fileops_write (struct file * filp, const char _ User * buff, size_t count, loff_t * OFFP) {copy_from_user (rdbuf, buff, count ); // rdbuf [count] = 0; // The End mark of the supplemented string is rdflag = 1; // The Readable poll function detects the mark wake_up_interruptible (& rdwait ); /* The fileops_poll function uses poll_wait to join the rdwait waiting queue. After execution, fileops_poll will be called, if you do not use the waiting queue fileops_poll, you only execute the SELECT statement once when the application calls the SELECT statement. Otherwise, the */return count;} unsigned int fileops_poll (struct File * Filp, poll_table * Wait) {/* The Readable mark processed only can be added here */INT mask = 0; poll_wait (filp, & rdwait, wait ); // This function is not blocked. When the status changes, the function should be awakened to call the new status again. If (rdflag) {mask = Pollin | pollrdnorm;} return mask ;}
After compilation, the test result runs the application first and listens to whether the device is readable [root @ localhost ctest] #. /main open another terminal, write Data [root @ localhost ctest] # echo eeee>/dev/moduledev60 [root @ localhost ctest] # echo eeee>/dev/moduledev60 [root @ localhost ctest] # echo eeee> the/dev/moduledev60 application reads the data after judging it is readable [root @ localhost ctest] #. /main read data: eeeeread data: eeee