Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is a brief introduction to the linux driver poll mechanism?

2025-02-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

This article is to share with you about the linux-driven poll mechanism is a brief introduction, the editor thinks it is very practical, so share with you to learn, I hope you can get something after reading this article, say no more, follow the editor to have a look.

# include # include static struct class * forthdrv_class;static struct class_device * forthdrv_class_dev;volatile unsigned long * gpfcon;volatile unsigned long * gpfdat;volatile unsigned long * gpgcon;volatile unsigned long * gpgdat;static DECLARE_WAIT_QUEUE_HEAD (button_waitq); / * interrupt event flag, which is set by the interrupt service program to clear it 0 * / static volatile int ev_press = 0 Struct pin_desc {unsigned int pin; unsigned int key_val;}; / * key value: when pressed, 0x01, 0x02, 0x03, 0x04 * / * key value: 0x81, 0x82, 0x83, 0x84 * / static unsigned char key_val when released Struct pin_desc pins_desc [4] = {{S3C2410_GPF0, 0x01}, {S3C2410_GPF2, 0x02}, {S3C2410_GPG3, 0x03}, {S3C2410_GPG11, 0x04},}; / * * determine the key value * / static irqreturn_t buttons_irq (int irq, void * dev_id) {struct pin_desc * pindesc = (struct pin_desc *) dev_id; unsigned int pinval / / how do you know which pin triggered the interrupt here? It is not determined which key caused the interrupt. If you want to get the current interrupt number, you can print the irq parameter to see pinval = s3c2410_gpio_getpin (pindesc- > pin). / / this function returns the value of GPxDAT. For example, GPF9 returns 0X100 (the remaining bits are mask) instead of 1 if (pinval) {/ * release * / key_val = 0x80 | pindesc- > key_val;} else {/ * Press * / key_val = pindesc- > key_val } ev_press = 1; / * indicates that an interrupt has occurred * / wake_up_interruptible (& button_waitq); / * Wake up the dormant process * / return IRQ_RETVAL (IRQ_HANDLED) } static int forth_drv_open (struct inode * inode, struct file * file) {/ * configure GPF0,2 as input pin * / / * configure GPG3,11 as input pin * / request_irq (IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE, "S2", & pins_desc [0]); request_irq (IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE, "S3", & pins_desc [1]) Request_irq (IRQ_EINT11, buttons_irq, IRQT_BOTHEDGE, "S4", & pins_desc [2]); request_irq (IRQ_EINT19, buttons_irq, IRQT_BOTHEDGE, "S5", & pins_desc [3]); return 0 } ssize_t forth_drv_read (struct file * file, char _ _ user * buf, size_t size, loff_t * ppos) {if (size! = 1) return-EINVAL; / * if there is no key action, hibernate * / wait_event_interruptible (button_waitq, ev_press) / * if there is a key action, return key value * / copy_to_user (buf, & key_val, 1); ev_press = 0; return 1;} int forth_drv_close (struct inode * inode, struct file * file) {free_irq (IRQ_EINT0, & pins_desc [0]); free_irq (IRQ_EINT2, & pins_desc [1]) Free_irq (IRQ_EINT11, & pins_desc [2]); free_irq (IRQ_EINT19, & pins_desc [3]); return 0;} static unsigned forth_drv_poll (struct file * file, poll_table * wait) {unsigned int mask = 0; poll_wait (file, & button_waitq, wait) / / if (ev_press) mask will not sleep immediately | = POLLIN | POLLRDNORM; return mask } static struct file_operations sencod_drv_fops = {.owner = THIS_MODULE, / * this is a macro, the _ _ this_module variable * / .open = forth_drv_open, .read = forth_drv_read, .release = forth_drv_close, .poll = forth_drv_poll,}; int major created automatically when the module is compiled Static int forth_drv_init (void) {major = register_chrdev (0, "forth_drv", & sencod_drv_fops); forthdrv_class = class_create (THIS_MODULE, "forth_drv"); forthdrv_class_dev = class_device_create (forthdrv_class, NULL, MKDEV (major, 0), NULL, "buttons"); / * / dev/buttons * / gpfcon = (volatile unsigned long *) ioremap (0x56000050, 16) Gpfdat = gpfcon + 1; gpgcon = (volatile unsigned long *) ioremap (0x56000060, 16); gpgdat = gpgcon + 1; return 0;} static void forth_drv_exit (void) {unregister_chrdev (major, "forth_drv"); class_device_unregister (forthdrv_class_dev); class_destroy (forthdrv_class); iounmap (gpfcon); iounmap (gpgcon); return 0 } module_init (forth_drv_init); module_exit (forth_drv_exit); MODULE_LICENSE ("GPL"); / * steps performed by poll: poll analysis: application: poll sys_poll do_sys_poll poll_initwait (& table) init_poll_funcptr (& pwq- > pt, _ _ pollwait) > > table- > pt- > qproc = _ _ pollwait It is said that the last thing poll_wait in the xxx_fops- > xxx_drv_poll tone calls is the _ _ pollwait function. How can you tell? Do_poll (nfds, head, & table, timeout) / / traverses all the descriptors passed in for (;;) {/ / mask = file- > poll-> poll (file, pwait) The poll here is the xxx_drv_poll (struct file * file, poll_table * wait) in the driver, and mask is the return value if (do_pollfd (pfd, pt)) {count++; pt = NULL in the driver. } / / if the driver is ready and returns a non-zero value, then jump out of the loop if (count | |! * timeout | | signal_pending (current)) break / / hibernate schedule_timeout (_ _ timeout) if it is not ready or time is not up;} routine execution procedure: call poll 1. Registering _ _ pollwait first is the content of the final call of the poll_wait function in xxx_drv_poll. Then call do_poll to iterate through the incoming descriptor. Do_pollfd is called xxx_drv_poll, which adds the process to the waiting queue set by the driver and determines whether it can jump out of the do_poll loop according to the return value. If it is not ready and does not time out, the process sleeps. If an interrupt occurs, set the interrupt flag and wake up the sleep process. After waking up, it is still executed from the dead loop of do_poll, and the xxx_drv_poll in the driver is executed again, and the non-0 mask value is returned smoothly if it is readable. If it is a timeout then the implementation of xxx_drv_poll still does not have a valid do_poll value, but you can jump out of the mask cycle directly, the application does processing according to different mask values * / the above is a brief introduction of the linux driver poll mechanism, Xiaobian believes that there are some knowledge points that we may see or use in our daily work. I hope you can learn more from this article. For more details, please follow the industry information channel.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report