高端网站设计怎么样,网站用哪种语言,建设工程官方网站,wordpress小程序制作1.框架图 被称为当前时代最好用的io多路复用方式#xff1b;
核心操作#xff1a;一棵树#xff08;红黑树#xff09;、一张表#xff08;内核链表#xff09;以及三个接口#xff1b; 思想#xff1a;#xff08;fd代表文件描述符#xff09; epoll要把检测的事件…1.框架图 被称为当前时代最好用的io多路复用方式
核心操作一棵树红黑树、一张表内核链表以及三个接口 思想fd代表文件描述符 epoll要把检测的事件fd挂载到内核空间红黑树上遍历红黑树调用每个fd对应的操作方法找到发生事件的fd,如果没有发生事件的fd进程休眠如果事件发生将发生事件的fd拷贝一份放到内核链表每个节点对应一个fd最后把链表的节点信息传递到用户空间的数组中用户空间无需判断事件的发生需要判断事件类型读写等 2.代码
---pro1.c---应用程序epoll方式
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include stdio.h
#include string.h
#include unistd.h
#include stdlib.h
#include sys/ioctl.h
#include sys/select.h
#include sys/time.h
#include sys/epoll.hint main(int argc, const char *argv[])
{int fd1,fd2,epfd;char buf[128] {0};struct epoll_event event; //用于操作epollstruct epoll_event events[10]; //用户空间存放发生事件的数组//创建epoll句柄红黑树根节点epfd epoll_create(1);if(epfd 0){printf(epoll_create fail\n);exit(-1);}//打开设备文件fd1 open(/dev/input/mouse0, O_RDWR);if (fd1 0){printf(鼠标事件文件失败\n);exit(-1);}fd2 open(/dev/myled0, O_RDWR);if (fd2 0){printf(自定义事件文件失败\n);exit(-1);}//添加准备就绪事件到epollevent.events EPOLLIN; //读事件event.data.fd fd1;if((epoll_ctl(epfd,EPOLL_CTL_ADD,fd1,event)) 0){printf(epoll_ctl fd1 fail\n);}event.events EPOLLIN; //读事件event.data.fd fd2;if((epoll_ctl(epfd,EPOLL_CTL_ADD,fd2,event)) 0){printf(epoll_ctl fd2 fail\n);}//监听时间是否发生while(1){//成功接收返回时间的个数放入events数组中int ret epoll_wait(epfd,events,10,-1);if(ret 0){printf(epoll_wait fail\n);exit(-1); }int i;//循环遍历数组做事件的处理for(i0; iret; i){if(events[i].events EPOLLIN) //发生事件是读事件{read(events[i].data.fd,buf,sizeof(buf));printf(buf:%s\n,buf);memset(buf,0,sizeof(buf));}}}close(fd1);close(fd2);return 0;
}---pro2.c---应用程序模拟自定义设备数据就绪
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include stdio.h
#include string.h
#include unistd.h
#include stdlib.hint main(int argc, const char *argv[])
{char buf[128] hello world;int fd open(/dev/myled0, O_RDWR);if (fd 0){printf(打开设备文件失败\n);exit(-1);}write(fd, buf, sizeof(buf));close(fd);return 0;
}
---epoll.c---驱动程序 #include linux/init.h
#include linux/module.h
#include linux/fs.h
#include linux/io.h
#include linux/device.h
#include linux/uaccess.h
#include linux/wait.h
#includelinux/poll.hchar kbuf[128] {0};
unsigned int major;
struct class *cls;
struct device *dev;
unsigned int condition 0;// 定义一个等待队列头
wait_queue_head_t wq_head;// 封装操作方法
int mycdev_open(struct inode *inode, struct file *file)
{printk(%s:%s:%d\n, __FILE__, __func__, __LINE__);return 0;
}ssize_t mycdev_read(struct file *file, char *ubuf, size_t size, loff_t *lof)
{int ret;ret copy_to_user(ubuf, kbuf, size);if (ret){printk(copy_to_ user err\n);return -EIO;}condition 0; // 下一次硬件数据没有就绪return 0;
}
ssize_t mycdev_write(struct file *file, const char *ubuf, size_t size, loff_t *lof)
{int ret;// 从用户拷贝数据模拟硬件数据ret copy_from_user(kbuf, ubuf, size);if (ret){printk(copy_from_user err\n);return -EIO;}condition 1;wake_up_interruptible(wq_head);return 0;
}
//封装POLL方法
__poll_t mycdev_poll(struct file *file, struct poll_table_struct *wait)
{__poll_t mask 0;//向上提交等待队列头poll_wait(file,wq_head,wait);//根据事件是否发生给一个合适的返回值if(condition){mask POLLIN;}return mask;
}
int mycdev_close(struct inode *inode, struct file *file)
{printk(%s:%s:%d\n, __FILE__, __func__, __LINE__);return 0;
}struct file_operations fops {.open mycdev_open,.read mycdev_read,.poll mycdev_poll,.write mycdev_write,.release mycdev_close,
};// 入口函数
static int __init mycdev_init(void)
{//初始化等待队列init_waitqueue_head(wq_head);major register_chrdev(0, myled, fops);if (major 0){printk(字符设备驱动注册失败\n);return major;}printk(字符设备驱动注册成功:major%d\n, major);// 向上提交目录cls class_create(THIS_MODULE, MYLED);if (IS_ERR(cls)){printk(向上提交目录失败\n);return -PTR_ERR(cls);}printk(向上提交目录成功\n);// 向上提交设备节点信息int i;for (i 0; i 3; i){dev device_create(cls, NULL, MKDEV(major, i), NULL, myled%d, i);if (IS_ERR(dev)){printk(向上提交设备节点信息失败\n);return -PTR_ERR(dev);}}printk(向上提交设备节点信息成功\n);return 0;
}// 出口函数
static void __exit mycdev_exit(void)
{// 销毁设备节点信息int i;for (i 0; i 3; i){device_destroy(cls, MKDEV(major, i));}// 销毁目录信息class_destroy(cls);// 字符设备驱动注销unregister_chrdev(major, myled);
}// 声明
// 入口函数地址
module_init(mycdev_init);
// 出口函数地址
module_exit(mycdev_exit);
// 遵循的GPL协议
MODULE_LICENSE(GPL); 3.测试结果 执行pro2.c自定义事件被监听到 在ubuntu上动鼠标鼠标事件被监听