IO模型
来源:互联网 发布:健身数据统计 编辑:程序博客网 时间:2024/05/16 14:08
IO模型
阻塞
非阻塞
多路复用
信号驱动
阻塞机制
1. 使用等待队列去实现阻塞机制
等待队列
1. 头文件: <linux/wait.h>
或则 #include <linux/sched.h>
2. 等待队列头的定义
wait_queue_head_t q;
struct __wait_queue_head {
spinlock_t lock;
struct list_head task_list;
};
typedef struct __wait_queue_head wait_queue_head_t;
3. 等待队列头的初始化init_waitqueue_head(wait_queue_head_t *q)
参数 q : 等待队列的结构体指针
extern void __init_waitqueue_head(wait_queue_head_t *q, struct lock_class_key *);
#define init_waitqueue_head(q) \
do { \
static struct lock_class_key __key; \
\
__init_waitqueue_head((q), &__key); \
} while (0)
4. 定义等待队列一个节点
DECLARE_WAITQUEUE(name, tsk)
5. 把节点添加等待队列头中
void add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
q : 要添加到哪一个等待队列头
wait : 要添加等待队列的节点
6. 把节点从等待队列中移除
void remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait)
q : 要从哪一个队列中移除节点
wait : 要移除等待队列的节点
7. 等待事件的发生
wait_event(wq,condition)
#define wait_event_interruptible(wq, condition) \
wq : 是要去等的等待队列
condition : a C expression for the event to wait for
如果condition 表达为假 ,wait_event 会进入睡眠 ,等待被唤醒(被wake_up唤醒)
8. 唤醒队列 wake_up(q)
q: 唤醒等待队列 ,等待队列结构体指针
#define wake_up(x) __wake_up(x, TASK_NORMAL, 1, NULL)
IO多路复用
1. 应用程序调用poll和select函数,驱动会调用poll函数
int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
其中readfds、writefds、exceptfds分别是被select()监视的读、写和异常处理的文件描述符集合,
numfds的值是需要检查的号码最高的文件描述符加1。timeout参数是一个指向struct timeval类型的指针。
2. 驱动中实现poll函数
static unsigned int dev_poll(struct file *filp, poll_table *wait)
filp : 指向file的结构体指针
wait : 轮训的表,可以监控集合
3. 把要监控的对象加入到等待队列内 poll_wait
static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
poll_wait(filp, &dev.rq, wait); /* 把rq添加到等待队列中,该函数不阻塞*/
4. 驱动中poll函数会查寻数组的状态,是否可读
可读: mask |= POLLIN | POLLRDNORM; /*标示数据可获得*/
可写: mask |= POLLOUT | POLLWRNORM; /*标示数据可写入*/
返回当前的状态 return mask;驱动中poll函数返回,进而应用程序poll或则select返回
信号驱动IO
1. 应用程序要设置信号捕捉(处理)函数
signal(SIGIO, handler);
2. 应用程序要指定进程为文件的属主
fcntl(fd, F_SETOWN, getpid());
这句话的含义是: 把当前进程好的pid获取后赋值给驱动中的驱动中file ->f_owner = pid ,
这样驱动发送信号是,知道向这个进程发送信号
3. 通过fcntl函数设置让文件可以操作在异步模式下,因为默认文件不能操作在异步模式下
oflags = fcntl(fd, F_GETFL); //读取文件的属性
fcntl(fd, F_SETFL, oflags | FASYNC); // 设置文件的属性
在设备文件中添加FASYNC标志,驱动中就会调用hello_fasync函数。
fcntl(fd, F_SETFL, oflags | FASYNC); // 设置文件的属性
在设备文件中添加FASYNC标志,驱动中就会调用hello_fasync函数。
4.在驱动中实现异步机制函数(fasync)
static int hello_fasync(int fd, struct file *filp, int mode)
{
struct hello_device *dev = filp->private_data;
/* 设置设备文件支持fasync,即异步通知模式*/
return fasync_helper(fd, filp, mode, &dev->async_queue);
// 安装文件fd 和异步队列关联
}
5. 信号机制使用的是异步队列,因此需要创建异步队列
struct fasync_struct *async_queue;
6. 在设备可读时,发送一个可读信号
/* 产生异步读信号 向所属的进程发送一个SIGIO 信号 */
if (dev->async_queue) // 指针不为空
kill_fasync(&dev->async_queue, SIGIO, POLL_IN);
一个最重要的区别:
1)异步通知是不会造成阻塞的。
2)调用阻塞IO时如果条件不满足,会在驱动函数中的test_read或test_write中阻塞。
0 0
- IO模型
- IO模型
- IO模型
- IO模型
- IO模型
- IO模型
- IO模型
- IO模型
- IO模型
- IO模型
- IO模型
- IO模型
- IO模型
- IO模型
- IO模型
- IO模型
- IO 模型
- IO模型
- JRebel 7.x + SpringBoot 1.5.2.RELEASE BUG 启动报错解决方案
- Android app 基础开发流程
- 文章标题
- ios的UIViewController中设置强制横屏
- BZOJ 2323: [ZJOI2011]细胞
- IO模型
- REDIS安装配置手册
- maven实战(一)简单mvn构建项目详解
- SDWebImage常用方法
- 一个人的命运决定于每天晚上8点到10点之间
- Mac上安装Protobuf以及生成lua文件
- jenkins+gitlab集成
- 修改系统标题栏 高度 字体偏移 添加图片 点击事件
- 文章标题