首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

linux poll 驱动

Linux Poll 驱动基础概念

Poll 是 Linux 内核提供的一种 I/O 多路复用机制,允许单个进程/线程处理多个文件描述符(如套接字、管道等)的 I/O 事件。与 selectepoll 相比,poll 提供了一种相对简单的方式来监控多个文件描述符的状态变化。

优势

  1. 简洁性:相对于 selectpoll 的 API 更加简洁,不需要重新初始化文件描述符集合。
  2. 可扩展性:虽然不如 epoll 高效,但 poll 在处理大量文件描述符时仍然比 select 表现更好。
  3. 跨平台支持poll 在大多数类 Unix 系统上都有良好的支持。

类型与应用场景

  • 阻塞模式:默认情况下,poll 会阻塞调用线程直到至少一个文件描述符准备好进行 I/O 操作。
  • 非阻塞模式:通过设置文件描述符为非阻塞模式,poll 可以立即返回,即使没有文件描述符准备好。

应用场景

  • 网络服务器:处理多个客户端连接,每个连接可能有不同的 I/O 需求。
  • 实时系统:需要高效地监控多个输入源,如传感器数据、用户输入等。

示例代码

以下是一个简单的 poll 使用示例,展示如何监控一个套接字的读事件:

代码语言:txt
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/poll.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define MAX_EVENTS 10

int main() {
    int sockfd, newsockfd, portno;
    struct sockaddr_in serv_addr, cli_addr;
    socklen_t clilen;
    char buffer[256];
    int n;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        perror("ERROR opening socket");
        exit(1);
    }

    memset((char *) &serv_addr, 0, sizeof(serv_addr));
    portno = 8080;

    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = INADDR_ANY;
    serv_addr.sin_port = htons(portno);

    if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
        perror("ERROR on binding");
        exit(1);
    }

    listen(sockfd, 5);
    clilen = sizeof(cli_addr);

    struct pollfd fds[MAX_EVENTS];
    fds[0].fd = sockfd;
    fds[0].events = POLLIN;

    while (1) {
        int ret = poll(fds, MAX_EVENTS, -1);
        if (ret < 0) {
            perror("poll error");
            break;
        }

        if (fds[0].revents & POLLIN) {
            newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
            if (newsockfd < 0) {
                perror("ERROR on accept");
                continue;
            }
            fds[1].fd = newsockfd;
            fds[1].events = POLLIN;
        }

        for (int i = 1; i < MAX_EVENTS; i++) {
            if (fds[i].revents & POLLIN) {
                n = read(fds[i].fd, buffer, 255);
                if (n < 0) {
                    perror("ERROR reading from socket");
                    close(fds[i].fd);
                    fds[i] = fds[MAX_EVENTS - 1];
                    i--;
                } else {
                    buffer[n] = '\0';
                    printf("Here is the message: %s\n", buffer);
                }
            }
        }
    }

    close(sockfd);
    return 0;
}

常见问题及解决方法

问题1:poll 返回错误码

原因:可能是由于系统资源不足、文件描述符无效或其他系统级错误。

解决方法

  • 检查并释放不必要的资源。
  • 确保所有文件描述符都是有效的。
  • 使用 perrorstrerror 打印详细的错误信息以便调试。

问题2:poll 超时

原因:设置的超时时间太短或者系统负载过高导致无法及时响应。

解决方法

  • 调整超时时间,根据实际需求合理设置。
  • 优化程序逻辑,减少不必要的等待时间。

通过以上内容,你应该对 Linux poll 驱动有了全面的了解,并能够在实际开发中灵活运用。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

韦东山:Linux驱动基石之POLL机制

① APP不知道驱动程序中是否有数据,可以先调用poll函数查询一下,poll函数可以传入超时时间; ② APP进入内核态,调用到驱动程序的poll函数,如果有数据的话立刻返回; ③ 如果发现没有数据时就休眠一段时间...驱动编程 使用poll机制时,驱动程序的核心就是提供对应的drv_poll函数。...POLL机制的内核代码详解 Linux APP系统调用,基本都可以在它的名字前加上“sys_”前缀,这就是它在内核中对应的函数。...(ufds, nfds, to); …… SYSCALL_DEFINE3是一个宏,它定义于include/linux/syscalls.h,展开后就有sys_poll函数。...⑧ 如果驱动程序的poll返回有效值,则count非0,跳出循环; ⑨ 否则休眠一段时间;当休眠时间到,或是被中断唤醒时,会再次循环、再次调用驱动程序的poll。

9.1K85

Linux select poll源码剖析

在读select、poll源码前,需要先了解的知识点: 等待队列 文件系统(主要是进程的打开文件描述符表以及struct file) poll机制 资源注册监听poll() -> poll_wait(...select()/poll()调用对应一个struct poll_wqueues 一个监听事件对应一个struct poll_table_entry Common poll机制是所有多路转接的共性;调用控制块.../* * Structures and helpers for sys_poll/sys_poll */ struct poll_wqueues { poll_table pt; struct...实际linux内核设计: * 每个wait_queue_t的private字段指向同一个poll_wqueues,然后 * 共用的poll_wqueues中保存了指向调用进程...被封装在了poll_wqueues结构体中,以便之后向资源 * 注册监听的时候,能够用poll_table得到对应的poll_wqueues * * 初始化poll_wqueues

3.2K20
  • linux poll机制《Rice linux 学习笔记》

    举例:用户以阻塞的方式访问设备,若设备的资源不能获取,驱动程序的xxx_read()、xxx_write()等操作中将进程阻塞直到资源可以获取才返回; 非阻塞:非阻塞操作的进程在不能进行设备操作时,并不挂起...举例:若用户以非阻塞的方式访问设备文件,则当设备资源不可获取时,设备驱动的xxx_read()、xxx_write()等操作应立即返回,read()、write()等系统调用也随即被返回,应用程序收到-...系统调用分析: poll系统调用在内核中的入口函数是sys_poll(); 分析内核源码,可以看出它的调用关系: sys_poll() do_sys_poll() do_poll() for (;;...然后调用do_pollfd,通过do_pollfd函数可以看出,调用了驱动的poll的方法。然后返回其poll方法的返回值。如果返回非0,则count为非0值。...驱动代码:增加poll的方法。

    1.2K10

    多进程、协程、事件驱动及select poll epoll

    事件驱动型程序比多线程程序更容易推断出行为,因为程序员不需要关心线程安全问题。...信号驱动I/O(signal driven IO) 5....异步I/O(asynchromous IO) 注意:信号驱动I/O(signal driven IO)在实际中不常用 阻塞I/O(blocking IO) 在linux中,默认情况下所有的socket都是...poll 和select在本质上没有多大差别,但是poll没有最大文件描述符数量的限制 poll和select同样存在一个缺点就是,包含大量文件描述符的数组被整体复制于用户态和内核的地址空间之间,而不论这些文件描述符是否就绪...另外,select()和poll()将就绪的文件描述符告诉进程后,如果进程没有对其进行IO操作,那么下次调用select()和poll()的时候将再次报告这些文件描述符,所以它们一般不会丢失就绪的消息,

    2.2K90

    【Linux】高级IO --- 多路转接,select,poll,epoll

    IO模型分为五种,分别是阻塞式IO,非阻塞IO,信号驱动IO,多路转接IO,异步IO。下面我们讲一个例子先来浅浅谈一下这5个模型IO的做法。...只不过三者等待的方式是不同的,阻塞是一直在进行等待,而非阻塞可能会使用轮询的方式来进行等待,在等待的时间段内,非阻塞可能还会做一些其他的事情,信号驱动和非阻塞一样,在等待的时间段内,信号驱动会做一些其他的事情...所以从IO的效率角度来讲,这三种IO并无差别,因为IO的过程分为等待和数据拷贝,三者在这个工作上的效率都是一样的,只不过非阻塞和信号驱动的等待方式与阻塞IO不同。...信号驱动只不过是被动的等待,阻塞和非阻塞都是主动的等待,当信号到来时,信号驱动IO会通过回调的方式来处理就绪的事件。 2....虽然说epoll是作了改进的poll,但在接口的使用和底层实现上,epoll和poll天差地别,在linux内核2.5.44版本时,就引入了epoll接口,而现在主流的linux内核版本已经是3点几了。

    36330

    8.中断按键驱动程序之poll机制(详解)

    所以do_pollfd(pfd, pt)就执行了我们驱动程序里的.poll(pfd, pt)函数(第2小节开始分析.poll函数) 1.4.2当poll进入休眠状态后,又是谁来唤醒它?...这就要分析我们的驱动程序.poll函数(第2小节开始分析.poll函数) 2写驱动程序.poll函数,并分析.poll函数: 在上一节驱动程序里添加以下代码: #include linux/poll.h...third_poll()函数, 所以当我们有按键按下时, 驱动函数third_poll()就会返回mask非0值,然后在内核函数do_poll里的count就++,poll机制并退出睡眠. 2.2分析在内核中...poll机制如何被驱动里的中断唤醒的  在驱动函数third_poll()里有以下一句: poll_wait(fp, &button_wait, wait); ?...函数, 3.改进测试程序third_poll_text.c(添加poll函数) 在linux中可以通过man poll 来查看poll函数如何使用 poll函数原型如下(#include poll.h

    1.8K60

    Linux驱动之网卡驱动剖析

    Linux 网络设备驱动架构 驱动架构自上而下分为4层: 协议接口层 设备接口层 设备驱动功能层 网络设备与媒介层 协议接口层 协议接口层主要功能是给上层协议提供接收和发送的接口。...传递的数据被描述为套接字缓冲区,用struct sk_buff结构描述,该结构体定义位于include/linux/skbuff.h中,用于在Linux网络子系统中的各层之间传输数据,该结构在整个网络收发过程中贯穿始终...源码分析 笔者基于的是 S5PV210 的 DM9000 驱动,会大体上对 DM9000 的驱动源码进行分析, 分析源码位于DM9000 源码 platform 框架分析 DM9000 的驱动是基于 platform..., dm9000_poll_work); 该部分为 struct net_device 和 struct board_info 结构体申请内存,struct board_info定义在 DM9000 的驱动文件中....ndo_poll_controller = dm9000_poll_controller, #endif }; dm9000 open 过程分析 当用户执行命令ifconfig eth0 up后会调用网卡驱动的

    56.4K20

    Linux驱动开发: USB驱动开发

    四、 linux内核下USB相关的API函数与数据结构 前面介绍了USB相关一些基础概念与重要的数据结构,接下来就分析在linux内核中如何编写一个USB 驱动程序,编写与一个USB设备驱动程序的方法和其他总线驱动方式类似...\n"); } //定义USB驱动结构体 static struct usb_driver usbtest_driver = { .name = "linux_usb_drv", .id_table...(中断传输方式) 5.1 USB驱动注册框架代码 #include linux/init.h> #include linux/module.h> #include linux/usb.h> /*...[root@wbyq linux-3.5]# make menuconfig 由于内核自带了usb鼠标驱动,所以需要去除: Device Drivers ---> HID support...#include linux/hid.h> /* 本程序为USB鼠标驱动程序,要安装本驱动,需要先将内核自带的USB驱动程序卸载掉 */ //定义USB的IDTAB 24ae:2002 static

    70.1K20
    领券