linux内核分析--异步io(二)

简介:

该分析sys_io_submit函数了,这个函数有点复杂,但是条理很清晰,先说一句就是提交异步io,具体怎么提交呢?我们知道,对于异步io,一次性可以提交多个请求,那么可以想象的就是在sys_io_submit中会把我们用户程序的多个请求分解成一个一个的请求,依次提交,这是很合理的假设,内核实际上也是这么做的,刚才的建立异步io的阶段只是建立了一个可以让异步io表演的大的环境,现在的提交请求和将来的读取数据便是大戏了,准备好了吗?马上开演!

asmlinkage long sys_io_submit(aio_context_t ctx_id, long nr,
struct iocb __user * __user *iocbpp)
{
struct kioctx *ctx;
long ret = 0;
int i;
if (unlikely(nr < 0))
return -EINVAL;
if (unlikely(!access_ok(VERIFY_READ, iocbpp, (nr*sizeof(*iocbpp)))))
return -EFAULT;
ctx = lookup_ioctx(ctx_id);//这里查找我们刚才建立的kioctx
if (unlikely(!ctx)) {

for (i=0; i<nr; i++) {//这个循环实质上分解了用户请求
struct iocb __user *user_iocb;
struct iocb tmp;
if (unlikely(__get_user(user_iocb, iocbpp + i))) {
ret = -EFAULT;
break;
}
if (unlikely(copy_from_user(&tmp, user_iocb, sizeof(tmp))))


ret = io_submit_one(ctx, user_iocb, &tmp);//一次提交一个,直到全部提交完毕
if (ret)
break;
}
put_ioctx(ctx);
return i ? i : ret;
}

上面的函数提到了查找kioctx结构,这个函数猜也能猜到怎么实现的,就是在进程的mm中的ioctx_list中寻找id和sunmit参数的id相 同的kioctx,说了半天,到底什么是kioctx,它到底有什么用?它实际上正如前面说的那样,是一个大舞台,提供了一个工作体,提供了一个运行队列 等等,所有属于这个大舞台的请求必须纳入它的管理范畴,它的字段决定了谁应该被调度,以及调度后应该做甚。下面来看看完成实际工作的io_submit_one函数:

1476 int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
struct iocb *iocb)
{
struct kiocb *req;
struct file *file;
ssize_t ret;
/* enforce forwards compatibility on users */
if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2 ||

/* prevent overflows */
if (unlikely(
(iocb->aio_buf != (unsigned long)iocb->aio_buf) ||
(iocb->aio_nbytes != (size_t)iocb->aio_nbytes) ||
((ssize_t)iocb->aio_nbytes < 0)
)) {

file = fget(iocb->aio_fildes);
req = aio_get_req(ctx); /* returns with 2 references to req */
if (unlikely(!req)) {

req->ki_filp = file;
ret = put_user(req->ki_key, &user_iocb->aio_key);
if (unlikely(ret)) {
dprintk("EFAULT: aio_key/n");
goto out_put_req;
}
req->ki_obj.user = user_iocb;
req->ki_user_data = iocb->aio_data;
req->ki_pos = iocb->aio_offset;
req->ki_buf = (char __user *)(unsigned long)iocb->aio_buf;
req->ki_left = req->ki_nbytes = iocb->aio_nbytes;
req->ki_opcode = iocb->aio_lio_opcode;
init_waitqueue_func_entry(&req->ki_wait, aio_wake_function);//注册唤醒时的回调函数
INIT_LIST_HEAD(&req->ki_wait.task_list);
req->ki_retried = 0;
ret = aio_setup_iocb(req);//设置retry回调函数
if (ret)
goto out_put_req;
spin_lock_irq(&ctx->ctx_lock);
aio_run_iocb(req);//首先先执行一次,没准一次就能成功,要不怕做无用功,内核真是精打细算啊
if (!list_empty(&ctx->run_list)) {
/* drain the run list */
while (__aio_run_iocbs(ctx))//如果当前异步上下文的运行队列有请求,执行之!
;
}
spin_unlock_irq(&ctx->ctx_lock);
aio_put_req(req); /* drop extra ref to req */
return 0;

}
我们来看看aio_run_iocb函数,实际上__aio_run_iocbs(ctx)最终也是要调用aio_run_iocb函数的:
static ssize_t aio_run_iocb(struct kiocb *iocb)
{
struct kioctx *ctx = iocb->ki_ctx;
ssize_t (*retry)(struct kiocb *);
ssize_t ret;
if (iocb->ki_retried++ > 1024*1024) {

}
if (!(iocb->ki_retried & 0xff)) {
}
if (!(retry = iocb->ki_retry)) {

}
kiocbClearKicked(iocb);
iocb->ki_run_list.next = iocb->ki_run_list.prev = NULL;
spin_unlock_irq(&ctx->ctx_lock);
/* Quit retrying if the i/o has been cancelled */
if (kiocbIsCancelled(iocb)) {

}
BUG_ON(current->io_wait != NULL);
current->io_wait = &iocb->ki_wait;//以下3行很重要,如果当前请求未果,则可能睡眠在io_wait,当被唤醒的时候执行aio_wake_function
ret = retry(iocb);
current->io_wait = NULL;
if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) {

}

}
注意aio_wake_function是唤醒回调函数,这个函数本质上也是执行将上下文挂入工作队列的任务,为什么呢?为何不让它直接把任务完成呢?因为它可能在中断上下文中,这又很多限制,比如不能睡眠,于是乎就把任务挂入一个工作队列,这样就有了进程的上下文,一切变得明朗!到这基本上就完事了,不用用户进程操心了,到了实在闲来无事的时候来取数据吧!如果实在觉得这篇文章到此意尤未尽,那么请看《linux工作队列和异步io 》下面将要进行的就是取数据了。一会回来,更精彩!



本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1274055

相关文章
|
3天前
|
监控 安全 Linux
启用Linux防火墙日志记录和分析功能
为iptables启用日志记录对于监控进出流量至关重要
|
21天前
|
算法 Linux
深入探索Linux内核的内存管理机制
本文旨在为读者提供对Linux操作系统内核中内存管理机制的深入理解。通过探讨Linux内核如何高效地分配、回收和优化内存资源,我们揭示了这一复杂系统背后的原理及其对系统性能的影响。不同于常规的摘要,本文将直接进入主题,不包含背景信息或研究目的等标准部分,而是专注于技术细节和实际操作。
|
21天前
|
存储 缓存 网络协议
Linux操作系统的内核优化与性能调优####
本文深入探讨了Linux操作系统内核的优化策略与性能调优方法,旨在为系统管理员和高级用户提供一套实用的指南。通过分析内核参数调整、文件系统选择、内存管理及网络配置等关键方面,本文揭示了如何有效提升Linux系统的稳定性和运行效率。不同于常规摘要仅概述内容的做法,本摘要直接指出文章的核心价值——提供具体可行的优化措施,助力读者实现系统性能的飞跃。 ####
|
22天前
|
监控 算法 Linux
Linux内核锁机制深度剖析与实践优化####
本文作为一篇技术性文章,深入探讨了Linux操作系统内核中锁机制的工作原理、类型及其在并发控制中的应用,旨在为开发者提供关于如何有效利用这些工具来提升系统性能和稳定性的见解。不同于常规摘要的概述性质,本文将直接通过具体案例分析,展示在不同场景下选择合适的锁策略对于解决竞争条件、死锁问题的重要性,以及如何根据实际需求调整锁的粒度以达到最佳效果,为读者呈现一份实用性强的实践指南。 ####
|
22天前
|
缓存 监控 网络协议
Linux操作系统的内核优化与实践####
本文旨在探讨Linux操作系统内核的优化策略与实际应用案例,深入分析内核参数调优、编译选项配置及实时性能监控的方法。通过具体实例讲解如何根据不同应用场景调整内核设置,以提升系统性能和稳定性,为系统管理员和技术爱好者提供实用的优化指南。 ####
|
24天前
|
负载均衡 算法 Linux
深入探索Linux内核调度机制:公平与效率的平衡####
本文旨在剖析Linux操作系统内核中的进程调度机制,特别是其如何通过CFS(完全公平调度器)算法实现多任务环境下资源分配的公平性与系统响应速度之间的微妙平衡。不同于传统摘要的概览性质,本文摘要将直接聚焦于CFS的核心原理、设计目标及面临的挑战,为读者揭开Linux高效调度的秘密。 ####
34 3
|
27天前
|
负载均衡 算法 Linux
深入探索Linux内核调度器:公平与效率的平衡####
本文通过剖析Linux内核调度器的工作机制,揭示了其在多任务处理环境中如何实现时间片轮转、优先级调整及完全公平调度算法(CFS),以达到既公平又高效地分配CPU资源的目标。通过对比FIFO和RR等传统调度策略,本文展示了Linux调度器如何在复杂的计算场景下优化性能,为系统设计师和开发者提供了宝贵的设计思路。 ####
40 6
|
26天前
|
消息中间件 安全 Linux
深入探索Linux操作系统的内核机制
本文旨在为读者提供一个关于Linux操作系统内核机制的全面解析。通过探讨Linux内核的设计哲学、核心组件、以及其如何高效地管理硬件资源和系统操作,本文揭示了Linux之所以成为众多开发者和组织首选操作系统的原因。不同于常规摘要,此处我们不涉及具体代码或技术细节,而是从宏观的角度审视Linux内核的架构和功能,为对Linux感兴趣的读者提供一个高层次的理解框架。
|
28天前
|
缓存 并行计算 Linux
深入解析Linux操作系统的内核优化策略
本文旨在探讨Linux操作系统内核的优化策略,包括内核参数调整、内存管理、CPU调度以及文件系统性能提升等方面。通过对这些关键领域的分析,我们可以理解如何有效地提高Linux系统的性能和稳定性,从而为用户提供更加流畅和高效的计算体验。
30 2
|
28天前
|
缓存 网络协议 Linux
深入探索Linux操作系统的内核优化策略####
本文旨在探讨Linux操作系统内核的优化方法,通过分析当前主流的几种内核优化技术,结合具体案例,阐述如何有效提升系统性能与稳定性。文章首先概述了Linux内核的基本结构,随后详细解析了内核优化的必要性及常用手段,包括编译优化、内核参数调整、内存管理优化等,最后通过实例展示了这些优化技巧在实际场景中的应用效果,为读者提供了一套实用的Linux内核优化指南。 ####
45 1

热门文章

最新文章