软raid /proc/mdstat内核实现 -- mdstat_poll

一、mdstat_poll内核函数实现

static const struct seq_operations md_seq_ops = {
   
	.start  = md_seq_start,
	.next   = md_seq_next,
	.stop   = md_seq_stop,
	.show   = md_seq_show,
};

static int md_seq_open(struct inode *inode, struct file *file)
{
   
	struct seq_file *seq;
	int error;

	error = seq_open(file, &md_seq_ops);
	if (error)
		return error;

	seq = file->private_data;
	// 文件打开时将当前md_event_count的值赋值给poll_event.
	// poll_evnet和当前md_event_count计数不一致时事件mask将会被标记为EPOLLERR和EPOLLPRI
	seq->poll_event = atomic_read(&md_event_count);
	return error;
}

static int md_unloading;
static __poll_t mdstat_poll(struct file *filp, poll_table *wait)
{
   
	struct seq_file *seq = filp->private_data;
	__poll_t mask;
	// md_exit时会将md_unloading的值置为1
	if (md_unloading)	
		return EPOLLIN|EPOLLRDNORM|EPOLLERR|EPOLLPRI;
    // 函数用于将当前进程添加到md_event_waiters等待队列中,以便在有新的RAID事件时被唤醒。
	poll_wait(filp, &md_event_waiters, wait);

	/* always allow read */
    // 可读事件,
	mask = EPOLLIN | EPOLLRDNORM;

    // 初始poll_event值与当前md_event_count计数不一致。
    // 时间类型始终会被打上EPOLLERR | EPOLLPRI标记。
    // seq->poll_event在什么时候被赋值?
	if (seq->poll_event != atomic_read(&md_event_count))
		mask |= EPOLLERR | EPOLLPRI;
	return mask;
}
1.1 常见监控的错误类型
  • EPOLLIN: 表示文件描述符可读(有数据可读)。当有数据到达,可以进行读取操作时,该事件会被触发。
  • EPOLLPRI: 表示有紧急数据可读。这通常用于终端设备,当有“out-of-band”数据时触发。
  • EPOLLOUT: 表示文件描述符可写(可以进行写入操作)。当缓冲区有空间,可以写入更多数据时,该事件会被触发。
  • EPOLLERR: 表示文件描述符发生了错误。当 I/O 操作因为错误而无法进行时,该事件会被触发。
  • EPOLLHUP: 表示挂起(hang up)。当远程端关闭了连接,或者在流式网络连接中检测到一个挂起事件时,该事件会被触发。
  • EPOLLNVAL: 表示文件描述符无效。当 epoll_ctl 操作添加了一个不存在的文件描述符到 epoll 实例时,该事件会被触发。
  • EPOLLRDNORM: 表示有正常的读取数据。这个事件与 EPOLLIN 类似,但是用于区分不同类型的数据到达。
  • EPOLLRDBAND: 表示有带外数据可读。这通常用于检查是否有带外数据到达,例如网络接口的紧急数据。
  • EPOLLWRNORM: 表示有正常的写入数据。这个事件与 EPOLLOUT 类似,但是用于区分不同类型的数据写入。
  • EPOLLWRBAND: 表示有带外写入数据。这通常用于检查是否有带外数据可以写入。
  • EPOLLMSG: 表示有消息队列数据可读。这个事件用于 msgget 系统调用获取的 IPC(Inter-Process Communication)消息队列。
  • EPOLLRDHUP: 表示读取时检测到挂起。当读取操作检测到流式网络连接的另一端关闭了连接时,该事件会被触发。

poll_wait函数,什么叫做poll_table?该结构体包含一个函数指针_qproc_key

static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
{
   
	if (p && p->_qproc && wait_address)
		p->_qproc(filp, wait_address, p);	// 调用poll_table注册的函数指针
}

/* 
 * structures and helpers for f_op->poll implementations
 */
typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *);

/*
 * Do not touch the structure directly, use the access functions
 * poll_does_not_wait() and poll_requested_events() instead.
 */
typedef struct poll_table_struct {
   
	poll_queue_proc _qproc;
	__poll_t _key;
} poll_table;

_qproc函数指针是在什么时候初始化呢? - - 用户态在调用poll系统调用时被初始化。

|- do_sys_poll()
    |- poll_initwait()
    	|- init_poll_funcptr()
static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc)
{
   
	pt->_qproc = qproc;	// _qroc 被初始化为函数__pollwait
	pt->_key   = ~(__poll_t)0; /* all events enabled */
}

/*
 * Ok, Peter made a complicated, but straightforward mu
  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值