The read function in the loop of the application in the previous section is always read ; In practical applications , Is there a situation , Occasionally there is data 、 Occasionally there is no data , The answer, of course, is yes .--》poll Mechanism :Poll The mechanism is to return if there is no key for a certain time . In the past, if there was no key, it would not return   Sleep all the time .

poll call ( application layer ) :

#include <poll.h>
int poll(struct pollfd fds[], nfds_t nfds, int timeout);

struct pollfd The structure is as follows :【 In the source file poll.h In file 】

struct pollfd {
int fd;
short events;
short revents;
};

In this structure fd Represents a file descriptor ,events Represents an event that requests detection ,revents Represents the event returned after detection , If the state of a file descriptor changes ,revents The value of is not empty .

  1. fds: Store the state that needs to be detected Socket The descriptor ; And select Different (select Function after call , It empties the test socket Array of descriptors ), Every time this function is called , The system doesn't empty this array , It's going to have a state changing descriptor structure revents Variable state change , It's easy to operate ;
  2. nfds: Used to mark arrays fds Medium struct pollfd The total number of structural elements ;
  3. timeout:poll Function call blocking time , The unit is MS( millisecond )

return value:

  1. Greater than 0: Represents an array fds There is socket The state of the descriptor changes , Or can read 、 Or you can write 、 Or something wrong . And the value returned indicates that these states have changed socket The total number of descriptors ; At this time, we can do some research on fds Array traversal , To find those revents Not empty socket The descriptor , And then determine which events are in this to read the data .
  2. be equal to 0: It means that there is no socket Descriptors have state changes , And the call timed out .
  3. Less than 0: This indicates that an error has occurred , Now the global variable errno Save error code .

Kernel Implementation :

poll Mechanism summary :

1. poll > sys_poll > do_sys_poll >poll_initwait,poll_initwait Function to register the callback function __pollwait, It's our driver execution poll_wait when , The function that is actually called .

2. Next file->f_op->poll, That is, we implement it in our driver poll function

It will be called poll_wait Put yourself in a queue , This queue is also defined by our driver ;

It also determines if the device is ready .

3. If the device is not ready ,do_sys_poll It will allow the process to sleep for a certain period of time

4. The conditions for a process to wake up are 2: One is the above “ A certain time ” here we are , The second is to be awakened by the driver . When the driver finds the condition ready , Just put “ Some queue ” The process that hangs on the computer wakes up , This line , It's the front pass poll_wait Hang this process in the queue .

5. If the driver does not wake up the process , that chedule_timeout(__timeou) After a timeout , Will repeat 2、3 action , Until... Of the application poll Call the incoming time to .

Blog http://blog.csdn.net/u012719256/article/details/52663292 mention :

The kernel poll The implementation is very fixed , Here are two steps

static unsigned forth_drv_poll(struct file *file, poll_table *wait)
{
unsigned int mask = 0; // 1. take button_waitq Add to waiting queue
poll_wait(file, &button_waitq, wait); // Not immediately dormant if (ev_press) // If a key is pressed , The mask returned indicates no sleep
mask |= POLLIN | POLLRDNORM; // 2. Return mask
return mask;
}

Mark it for the time being , Now we only know the format

Code :

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <linux/interrupt.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <linux/poll.h>
#define DEVICE_NAME "mybutton" /* After loading mode , perform ”cat /proc/devices” Command to see the device name */
static struct class *button_class;
static struct class_device *button_dev_class;
int major; static volatile int press_cnt=;/* The number of times a key has been pressed ( To be exact , It's the number of interruptions ) */ static DECLARE_WAIT_QUEUE_HEAD(button_waitq);// Define the waiting queue /* Interrupt event flag , Interrupt the service program and set it to 1,s3c24xx_buttons_read Clean it up 0 */
static volatile int ev_press = ; static irqreturn_t buttons_interrupt(int irq, void *dev_id)
{
// volatile int *press_cnt = (volatile int *)dev_id;
press_cnt =press_cnt + ; /* Key count plus 1 */
ev_press = ; /* Indicates that an interrupt has occurred */
wake_up_interruptible(&button_waitq); /* Wake up the dormant process */
return IRQ_RETVAL(IRQ_HANDLED);// The interrupt handler should return a value , Used to indicate whether an interrupt was actually handled , If the interrupt routine finds that its device does have to handle , You should go back to IRQ_HANDLED, // Otherwise, we should return to IRQ_NONE, We can use this macro to generate the return value , Not the interrupt of this device should return IRQ_NONE }
/* Application to device files /dev/xxx perform open(...) when ,
* Will call button_open function
* Will call button_open function
*/
static int button_open (struct inode *inode, struct file *filep)
{
int err;
err=request_irq(IRQ_EINT2,buttons_interrupt,IRQF_TRIGGER_FALLING,"KEY3",NULL); if (err) {
// Release the registered interrupt
free_irq(IRQ_EINT2, NULL);
return -EBUSY;
} return ;
} /* Application to device files /dev/buttons perform close(...) when ,
* Will call buttons_close function
*/
static int buttons_close(struct inode *inode, struct file *file)
{ free_irq(IRQ_EINT2, NULL);
return ;
} ssize_t button_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{
unsigned long err; /* If ev_press be equal to 0, Sleep */
wait_event_interruptible(button_waitq, ev_press);// Blocking
/* When it's done here ,ev_press be equal to 1, Clean it up 0 */
ev_press = ;
/* Copy the key status to the user , He Qing 0 */
err = copy_to_user(buf, (const void *)&press_cnt, count);
//memset((void *)&press_cnt, 0, sizeof(press_cnt));
return err ? -EFAULT : ;
} static unsigned buttons_poll(struct file *file, poll_table *wait)
{
unsigned int mask = ;
poll_wait(file, &button_waitq, wait); // Not immediately dormant Hook the process to button_waitq In line
/* When no key is pressed , That is, it will not enter the key interrupt processing function , here ev_press = 0
* When the key is pressed , It will enter the key interrupt processing function , here ev_press Set to 1
*/
if(ev_press)
{
mask |= POLLIN | POLLRDNORM; /* POLLIN Indicates that there is data to read POLLRDNORM Indicates that there is common data to read */
}
/* If a key is pressed ,mask |= POLLIN | POLLRDNORM, otherwise mask = 0 */
return mask;
} /* This structure is the core of the character device driver
* Called when an application operates on a device file open、read、write Such as function ,
* Finally, the corresponding function specified in this structure will be called
*/
static struct file_operations button_ops=
{
.owner = THIS_MODULE, /* This is a macro , It's automatically created when the module is compiled __this_module Variable */
.open = button_open,
.read = button_read,
.release = buttons_close,
.poll = buttons_poll,
}; /*
* perform insmod This function is called when the command is executed
*/ static int button_init(void)
{ /* Register character device
* The parameter is the main equipment number 、 Device name 、file_operations structure ;
* such , The main device number is related to the specific file_operations The structure is connected ,
* The main operation equipment is LED_MAJOR Device file , Will call s3c24xx_leds_fops Related member functions in
* LED_MAJOR Can be set as 0, Indicates that the kernel automatically assigns the master device number
*/
major = register_chrdev(, DEVICE_NAME, &button_ops);
if (major < )
{
printk(DEVICE_NAME " can't register major number number::%d\n",major);
return ;
}
printk(DEVICE_NAME " initialized1\n");
button_class = class_create(THIS_MODULE, "button");
if (IS_ERR(button_class))
return PTR_ERR(button_class);
button_dev_class = class_device_create(button_class, NULL, MKDEV(major, ), NULL, "my_button"); /* /dev/my_button */ return ; } /*
* perform rmmod This function is called when the command is executed
*/
static void button_exit(void)
{
class_device_unregister(button_dev_class);
class_destroy(button_class);
/* Uninstall driver */
unregister_chrdev(major, DEVICE_NAME);
} /* These two lines specify the initialization function and the unload function of the driver */
module_init(button_init);
module_exit(button_exit); /* Some information describing the driver , It's not necessary */
MODULE_AUTHOR("http://www.100ask.net");// The author of the driver
MODULE_DESCRIPTION("S3C2410/S3C2440 LED Driver");// Some descriptive information
MODULE_LICENSE("GPL"); // Agreement to be followed

test.c

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <poll.h> int main(int argc,char**argv)
{
int fd;
int cnt = 0;
int ret; struct pollfd fds[1];/* every last pollfd Structure specifies a monitored file descriptor */ // Turn on the device
fd = open("/dev/my_button",O_RDWR); if(fd<0)
{
perror("open fail \n");
return -1;
} fds[0].fd=fd;
fds[0].events=POLLIN;
while(1)
{
/*poll The function returns 0 when , Express 5s time out , And during this time , No incidents " Data can be read " */
ret=poll(fds,1,5000); if (ret==0)
{
printf("time out\n");
}
else /* If there is no timeout , Then read out the key value */
{
read(fd,&cnt, sizeof(cnt)); //read()
printf("button has been pressed %d timea\n",cnt);
}
}
close(fd);
return 0;
}

result :

Reference resources :

http://blog.csdn.net/lwj103862095/article/details/17536069

http://blog.csdn.net/u012719256/article/details/52663292

http://www.cnblogs.com/mylinux/p/5090264.html

http://blog.csdn.net/ruoyunliufeng/article/details/24188693

linux Key driven poll More articles about

  1. linux Character driven poll Mechanism key driven

    In the last section , We explained how to create device nodes automatically , Realize a key driver in interrupt mode . Although interrupt driven , The efficiency is quite high , But did you find out , The read function in the application's dead loop is always read : In practical applications , Is there such a feeling ...

  2. Linux Key driver design -- From simple to not simple 【 turn 】

    Reprinted from :http://blog.csdn.net/coding__madman/article/details/51399353 Hybrid device driver model : 1. Hybrid device description stay Linux In the system , There is one ...

  3. Linux Key driver design details --- From simple to not simple 【 turn 】

    from :http://blog.csdn.net/coding__madman/article/details/51399353 Copyright notice : This article is an original blog article , No reprint without the permission of the blogger . Hybrid device driver model : ...

  4. ( Twelve )Linux Kernel driven poll and select

    Use non blocking  I/O  Our applications often use  poll, select,  Each allows a process to decide whether it can read or write one or more files without blocking .  These calls can also block the process until the file descriptors of any given set can be used to read or write .  ...

  5. The embedded Linux Driving learning ( Twelve ) Key driven -poll Mechanism

    The function is to read the key information , If no button is generated , Then the program sleeps in read Function , utilize poll Mechanism , You can let the program exit automatically without quitting . The following program is when reading the key information , If 5000ms There are no buttons inside ...

  6. Entry level key driven —— Key driven notes poll Mechanism - Asynchronous notification - Synchronous mutex blocking - Timer anti shake

    The article corresponds to the second part of the video 12 course , The first 5.6.7.8 section . Before that, there is the driver writing of query mode , Interrupt mode driver writing , There is no such content in this article for the time being . But this article is based on these , If you have time to fill in the preceding contents . Key driven —— Press the button , ...

  7. Based on waiting queue and poll Mechanism of key driven code analysis and test code

    Key driven analysis : #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> ...

  8. Linux Driving poll Understanding and simple use of mechanism

    Before that Linux Driver of the key driver to write ( Interrupt mode ) Driver written in , If no key is pressed .read A function never returns a value , Now you want to do it even if you don't press the button , There will be a return value after a certain period of time . To do this function , have access to po ...

  9. linux Key driver of input subsystem

    In the last section , We explained Linux  input The framework of the subsystem , In the kernel source code, the separation and layered framework of the input subsystem are analyzed in detail . Link to the previous section :http://blog.csdn.net/lwj103862095/ar ...

Random recommendation

  1. Cocos Engine developer's Guide (1-5)

    Cocos Engine developer's Guide English original :http://www.cocos2d-x.org/docs/programmers-guide/1/ At noon :http://www.cocos.com/doc/t ...

  2. nodejs,node Build instance of native server

    nodejs,node Build instance of native server

  3. Linux vsftpd Specific explanation of service configuration

    [ background ] In recent days, . A friend dominoserver To upgrade . transfer , Set the linux Test system , Also on vsftpd service , But the configuration is ftp account number , The program cannot download the attachment normally . [ Problem tracking ] adopt ftpclient Connect ...

  4. spring boot Log in to register demo ( One )

    Welcome to Spring Boot The code structure src/main/java Next controller layer , Routing functions dao layer , Database access domain,bean Storage of service, The business layer appl ...

  5. Oracle Data file migration

    background Make one these two days oracle Database migration , Used to exp.imp Come and go , This time I used expdp.impdp, There are some advantages , But at the same time, I also think of the migration method of copying data files , In fact, this method is not often used for migration , More on disk ...

  6. Failed to start component [StandardEngine[Tomcat].StandardHost[localhost].StandardContext[]]

    When testing project code today , stay idea Middle configuration tomcat7 After the plug-in runs, it always reports the following error : Solution : After reading online, most of the methods are modification xml File configuration , It doesn't feel right , Finally, we can see that the explanation is as follows : pom.xml in jar It's a package ...

  7. 201521123014《Java Programming 》 The first 1 Weekly learning summary

    201521123014 java The first week concludes 1. This week's learning summary Just met this new language , I'm full of curiosity , Want to see Java And I've learned C Language ,C++ What's the difference? . In this week's study , I realize , For beginners ,Java ...

  8. Effective C++ Clause 08: Don't let exceptions escape destructors

    1. Don't let exceptions escape the cause of destructors <Effective C++> In the Third Edition 08 It is not recommended to throw an exception in a destructor , as a result of C++ The exception mechanism cannot handle two or more exceptions at the same time . When multiple exceptions exist at the same time , ...

  9. Bosch sensor debugging notes ( One )---- Acceleration sensor BMA253

    The company is bosch Agent of , Recently, we have been developing sensors in our company demo On board debugging bosch sensor device . The devices involved are 7,8 paragraph , Types include gravitational acceleration . Geomagnetism . gyroscope . temperature . humidity . Atmospheric pressure sensor, etc . In the debug ...

  10. Linux command ( Add )

    1. View the port of the started service : netstat -tulnp |grep 80 ss -tulnp|grep 80 2. View all started ports :netstat -tulnp 3. View current directory :pwd 4. Turn off ...