原理:
1)select /poll:
准备将 文件描述符给添加到集合里面,检测文件描述符是否准备就绪,去除未准备的描述符,开始准备实现相关功能和操作
2)epoll:
文件描述符添加到根节点epfd的二叉树中,如果有准备好的文件描述符,将其放入集合中,实现相关功能与操作
3)select:
1/创建一个集合放入检测的文件描述符,通过select函数,等待事情发生,如果事件发生,则读取数据
2/在内核和用户层之间存在一个虚拟文件系统层,当用户层调用select函数后,虚拟文件系统层会调用sys_select()函数,该函数会实现相应功能:
(1)内核中申请内存,来保护用户表,通过copy_from_user将用户表从用户空间拷贝到这块内存
(2)从表中获取描述符fd->fd_arry[fd]->struct file->f_op指针->poll()函数
(3)文件描述符对应的poll()返回值都为0,的话,进程进入可中断的休眠状态
(4)虚拟文件系统层收到唤醒条件触发后,再次遍历文件描述符,找到准备好的文件描述符,拷贝到用户空间
#include<linux/init.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/cdev.h>
#include<linux/uaccess.h>
#include<linux/slab.h>
#include<linux/io.h>
#include<linux/device.h>
#include<linux/poll.h>
//定义字符设备驱动结构体对象指针
struct cdev* cdev;
char kbuf[128]={0};
dev_t devno;//设备号
unsigned int minor=0;//次设备号
int count=3;//设备数量
struct class* cls;//指向设备目录的指针
struct device* dev;//指向设备节点的指针
#if 1
unsigned int major=0;//进行动态申请设备号
#else
unsigned int major=500;//进行静态指定设备号
#endif
//定义等待对列头
wait_queue_head_t wq_head;
unsigned int condition=0;
int mycdev_open(struct inode *inode,struct file *file)
{
printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);
return 0;
}
ssize_t