20230523驱动开发课程-epoll笔记

linux驱动开发
IO模型
阻塞IO
应用程序调用 IO 操作后,会一直阻塞等待数据的读取或写入完成。
直到数据准备就绪或写入完成,应用程序才会继续执行。
非阻塞IO
应用程序调用 IO 操作后,如果数据还没有准备好或无法立即写入,函数会立即返回而不是阻塞等待。应用程序可以继续执行其他任务,之后再次检查数据的准备情况。
IO多路复用
使用 select、poll 或 epoll 等机制,应用程序可以同时监听多个 IO 事件。当任何一个 IO 事件就绪时,应用程序会被通知,可以进行读取或写入操作。这种模型允许同时处理多个 IO 操作,提高了系统的并发性能。
相关API
1.定义等待队列头
wait_queue_head_t wq_head;
2.初始化等待队列头
init_waitqueue_head(&wq_head);
3.wait_event(wq_head, condition)  
等待某个条件满足:
当条件condition为假时,进程将被置于休眠状态,并添加到等待队列中,等待条件满足时被唤醒。
当条件condition为真时,进程将继续执行。
4.wait_event_interruptible(wq_head, condition)
功能:检查condition的真假,如果为真,则函数执行结束,如果为假,将进程切换到可中断休眠状态
参数:wq_head:等待队列头
condition:标志变量
5.wake_up(&wq_head)
功能:将不可中断休眠态的进程唤醒,当执行这个函数时如果condition为假,则进程被唤醒后会再次休眠
参数:等待队列头地址
6.wake_up_interruptible(&wq_head)
功能:将  可中断休眠态的进程唤醒当执行这个函数时如果condition为假,则进程被唤醒后会再次休眠
参数:等待队列头地址
7. __poll_t (*poll) (struct file *file, struct poll_table_struct *wait)
{
    //将等待队列头向上提交
    void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
    {
        功能:向上提交等待队列头
        参数:
        filp: 文件结构体指针
        wait_address:要提交的等待队列头首地址
        p: 将队列头向上提交的通道 
    }
    if(condition)
    	return POLLIN;//POLLIN表示发生的事件为读事件POLLOUT表示写事件
    else
    	return 0;                  
}
epoll
epoll是Linux系统中的一种高效的I/O多路复用机制,用于管理大量的文件描述符并监视它们的状态变化。它相对于传统的select和poll机制,具有更高的性能和扩展性。

epoll的核心是一个事件驱动的I/O模型,通过将文件描述符注册到内核维护的事件表中,然后通过等待事件的发生来实现非阻塞地进行I/O操作。当文件描述符上发生感兴趣的事件时,内核会通知应用程序进行相应的处理。
相关API:
1.int epoll_create(int size);
功能:创建一个新的epoll
参数:
size:大于0的整数
返回值:成功返回用于操作epoll的文件描述符,失败返回错误码
2.int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
功能:进行epoll管理
   参数:
       epfd:epoll_create生成的文件描述符
       op:管理的类型选项
            EPOLL_CTL_ADD:用于在epoll上添加文件描述符
            EPOLL_CTL_MOD:用于修改文件描述符事件类型
            EPOLL_CTL_DEL:从epoll上移除指定的文件描述符
       fd:要操作的文件描述符
       event:设置文件描述符属性的变量
           struct epoll_event {
               uint32_t     events;      /* Epoll events */
                       //EPOLLIN:读
                       //EPOLLOUT:写
               epoll_data_t data;        /* User data variable */
           };
            typedef union epoll_data {
               void        *ptr;
               int          fd;《=======使用这个
               uint32_t     u32;
               uint64_t     u64;
           } epoll_data_t;
返回值:  成功返回0,失败返回错误码 
3.int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);
功能:阻塞等待事件发生
参数:
   epfd:epoll_create生成的文件描述符
   events: 存放发生的事件的文件描述符数组的首地址
   maxevents:监听的文件描述符最大个数
   timeout:设置超时事件   毫秒级   -1表示不关注超时 >0超时事件
返回值:
    >0:发生事件的文件描述符个数
    ==0:超时时间到达
    <0:失败
举例
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/epoll.h>
#define MAX_EVENTS 10
int main(int argc,const char * argv[])
{
    char buf[128]="";
    int fd1,fd2;//设置要监听的文件描述符
    int epoll_fd,ret,i;
    struct epoll_event event1;//设备监听
    struct epoll_event event2;//鼠标监听
    struct epoll_event events[MAX_EVENTS];

    fd1=open("/dev/mycdev0",O_RDWR);
    if(fd1<0){
        printf("设备文件打开失败\n");
        return -1;
    }
    fd2=open("/dev/input/mouse0",O_RDWR);
    if(fd2<0){
        printf("鼠标文件打开失败\n");
        return -1; 
    }
    // 创建 epoll 实例
    epoll_fd=epoll_create(5);
    if(epoll_fd<0){
        printf("epoll创建失败\n");
        return -1;
    }
    // 添加感兴趣的文件描述符到 epoll 实例中
    event1.events = EPOLLIN;
    event1.data.fd = fd1; 
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd1, &event1) == -1) {
        perror("1 epoll_ctl failed\n");
        return -1;
    }
    event2.events = EPOLLIN;
    event2.data.fd = fd2; 
    if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd2, &event2) == -1) {
        perror("2 epoll_ctl failed\n");
        return -1;
    }

    while(1){
        // 等待事件发生
        ret = epoll_wait(epoll_fd,events,MAX_EVENTS,-1);
        if(ret < 0){
            printf("epoll_wait failed\n");
            return -1;
        }
        // 处理就绪的事件
        for(i=0;i<ret;i++){
            if(events[i].events & EPOLLIN){
                memset(buf,0,sizeof(buf));
                read(events[i].data.fd,buf,sizeof(buf));
                printf("buf=%s\n",buf);
            }
        }
    }
    close(fd1);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值