Poll operation of Linux drivers

Source: Internet
Author: User
Tags array length readable volatile

Poll operation


1, poll operation process:

Poll is a system call, and its kernel entry function for Sys_poll,sys_poll almost no matter what processing directly calls the Do_sys_poll,do_sys_poll run process can be divided into three parts:

1, copy the user's incoming POLLFD array to the kernel space due to the copy operation and array length correlation. Time this is an O (n) operation, this step of the code in Do_sys_poll contains the part from the beginning of the function to the call to Do_poll.


2, query each file describes the status of the corresponding device, assuming that the device is not ready, add an entry in the waiting queue for the device and continue to query the status of the next device.

After querying the complete device, it is assumed that none of the devices are ready, then the current process waits are suspended. Until the device is ready or timed out, the suspend operation is performed by calling Schedule_timeout. After the device is ready, the process is notified to continue execution, and then traverses all the devices again to find the ready device. This step is due to traverse all devices two times. The time complexity is also O (n), where the face does not contain the wait time. The relevant code is in the Do_poll function.
3, the acquisition of data to the user space and run the release of memory and the stripping wait queue, such as the aftermath of work, to the user space copy data and stripping wait queue operations such as the time complexity of the same is O (n), the detailed code contains the Do_sys_poll function in the call Do_poll to the end of the section.


2, code Writing 1, in the file_operations structure to add poll

static struct file_operations button_sdv_fops ={.owner = This_module,.open  = Button_dev_open,.read = Button_dev_ Read,.release = Button_dev_close,.poll= Button_dev_poll,};

2, complete Button_dev_poll function

static unsigned int button_dev_poll (struct file *file, poll_table * wait) {unsigned int mask =0;poll_wait (file, &button _wait_q, wait);//Hang the current process into the queue, not immediately hibernate if (ev_press) Mask |=pollin | Pollrdnorm;return Mask;}

Ev_press is the interrupt event occurrence flag in the previous blog post, assuming that the interrupt action occurred, the mask value will be told to the kernel. The meaning of the value of mask:

Constant Description
Pollin Normal or priority with data-readable
Pollrdnorm Plain Data readable
Pollrdband Priority with data-readable
Pollpri High-priority data readable
Pollout Plain data can be written
Pollwrnorm Plain data can be written
Pollwrband Priority with data writable
Pollerr Error occurred
Pollhup Occurs pending
Pollnval Descriptive narrative word is not an open file

3. Test program Writing

RET = Poll (FDS, 1, 3000);

Poll function Prototypes:

int poll (struct POLLFD *fds, nfds_t nfds, int timeout);

Among them: The POLLFD structure is:

struct POLLFD {               int   fd;         /* File descriptor */short               events;     /* Requested events */short               revents;    /* Returned events * *           };
FD is the device to query. Events is expected to get the event, here we set him to: Pollin

FDS defines an array that stores all the devices that need to be poll. The poll operation will query these devices at the same time.

Nfds the number of files to query

Timeout is time-out


Driver Complete code:

#include <linux/init.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h > #include <asm/io.h> #include <linux/cdev.h> #include <linux/device.h> #include <linux/irq.h > #include <asm/uaccess.h> #include <asm/irq.h> #include <mach/regs-gpio.h> #include <mach/ irqs.h>//this in/opt/embedsky/linux-2.6.30.4/arch/arm/mach-s3c2410/include/mach path # include <linux/interrupt.h > #include <linux/poll.h>module_license ("Dual BSD/GPL"); static struct class *buttondrv_class;static struct Class_devices *buttondrv_class_dev;/* */static declare_wait_queue_head (BUTTON_WAIT_Q);/* Interrupt event Flag, interrupt service program will set him 1, The read function resets 0*/static volatile int ev_press =0;volatile unsigned long *gpfcon = null;volatile unsigned long *gpfdat = null;st atic unsigned keyval;struct pin_desc{unsigned int pin;unsigned int key_value;};/ * When the button is pressed: 0x01 0x02 0x03 0x04*//* When the button is released: 0x81 0x82 0x83 0x84*/struct pin_desc pins_desc[4] ={{s3c2410_gpf1,0x01},{s3c2410_ gpf4,0x02},{s3c2410_gpf2,0x03},{s3c2410_gpf0,0x04},};/* * Determine key value */static irqreturn_t buttons_irq (int irq,void *dev_id) {struct Pin_desc * Pindesc = (struct Pin_desc *) dev_id;unsigned int pinval;pinval = S3c2410_gpio_getpin (Pindesc-pin); if (pin val)//Loosen {keyval = 0x80|pindesc->key_value;} Else{keyval = Pindesc->key_value;} Ev_press =1;//interrupt occurs wake_up_interruptible (&button_wait_q);p rintk ("button is pressed:%d \ n", IRQ); return irq_ HANDLED;} The static int button_dev_open (struct inode *inode, struct file* file) {//Configure the PIN gpf0,1,2,4 for the key to the input pin REQUEST_IRQ (irq_eint1, BUTTONS_IRQ, Irq_type_edge_both, "Key1", &pins_desc[0]); REQUEST_IRQ (IRQ_EINT4,BUTTONS_IRQ, IRQ_TYPE_EDGE_BOTH, "Key2", &pins_desc[1]); REQUEST_IRQ (IRQ_EINT2,BUTTONS_IRQ, Irq_type_edge_both, "Key3", &pins_desc[2]); REQUEST_IRQ (IRQ_EINT0,BUTTONS_IRQ, Irq_type_edge_both, "Key4", &pins_desc[3]); return 0;} ssize_t button_dev_read (struct file *file,char __user *buf,size_t size,loff_t *ppos) {if (size!=1) {return-einval;} /* Assume that no keystroke action occurs on the Hibernate */waIt_event_interruptible (button_wait_q,ev_press);/* Assuming that a keystroke action occurs, return directly to */copy_to_user (buf,&keyval,1); ev_press = 0; return 0;} int button_dev_close (struct inode* inode, struct file *file) {FREE_IRQ (irq_eint1,&pins_desc[0]); FREE_IRQ (irq_ EINT4,&AMP;PINS_DESC[1]); FREE_IRQ (irq_eint2,&pins_desc[2]); FREE_IRQ (irq_eint0,&pins_desc[3]); return 0;} static unsigned int button_dev_poll (struct file *file, poll_table * wait) {unsigned int mask =0;poll_wait (file, &button _wait_q, wait);//Hang the current process into the queue, not immediately hibernate if (ev_press) Mask |=pollin | Pollrdnorm;return Mask;} static struct file_operations button_sdv_fops ={.owner = This_module,.open = Button_dev_open,.read = Button_dev_read,.re Lease = button_dev_close,.poll= button_dev_poll,};int major;static int button_dev_init (void)//Entry function {major = Register_ Chrdev (0, "Button_drv", &button_sdv_fops); buttondrv_class = Class_create (This_module, "button_drv"); if (IS_ERR ( Buttondrv_class)) return Ptr_err (Buttondrv_class); buttondrv_class_dev= device_create (buttondrv_class,nUll,mkdev (major,0), NULL, "Wq_button"), if (Unlikely (Is_err)) return Buttondrv_class_dev (Ptr_err dev);/* Map Physical Address */gpfcon = (volatile unsigned long *) Ioremap (0x56000050, +); Gpfdat = Gpfcon + 1;return 0;} static void Button_dev_exit (void) {Unregister_chrdev (Major, "Button_drv");d Evice_unregister (Buttondrv_class_dev); Class_destroy (Buttondrv_class); Iounmap (Gpfcon);} Module_init (Button_dev_init); Module_exit (Button_dev_exit);

Test procedure complete code:

#include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdio.h> #include <poll.h>int Main (int argc, char **argv) {int ret=0;int cnt=0;int fd;unsigned char key_val;struct pollfd fds[1];fd = O Pen ("/dev/wq_button", O_RDWR), if (fd<0) {printf ("can ' t open \ n");} FDS[0].FD   = fd;fds[0].events = Pollin;while (1) {ret = poll (FDS, 1, +); if (ret = = 0) {printf ("Time Out \ n");} Else{read (fd,&key_val,1);p rintf ("Key_val = 0x%x\n", key_val);}} return 0;}









Poll operation of Linux drivers

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.