在nvme的硬盘上使用sendfile系统调用,到底需要经过哪些流程?

do_sendfile--->do_splice_direct-->splice_direct_to_actor--->do_splice_to 对于xfs,其实就是xfs_file_splice_read

xfs_file_splice_read--->generic_file_splice_read--->__generic_file_splice_read--->mapping->a_ops->readpage--->xfs_vm_readpage-->mpage_readpage--->submit_bio

在splice_direct_to_actor函数中,有一个while循环,执行一段direct_splice_actor,返回之后,就执行do_splice_from-->generic_splice_sendpage-->splice_from_pipe-->__splice_from_pipe-->

splice_from_pipe_feed-->pipe_to_sendpage-->sock_sendpage-->kernel_sendpage-->inet_sendpage-->udp_sendpage(我用的是udp)

堆栈如下:

0xffffffff816093ed : inet_sendpage+0x6d/0xe0 [kernel]
0xffffffff8156b0bb : kernel_sendpage+0x1b/0x30 [kernel]
0xffffffff8156b0f7 : sock_sendpage+0x27/0x30 [kernel]
0xffffffff812329c3 : pipe_to_sendpage+0x63/0xa0 [kernel]
0xffffffff812328be : splice_from_pipe_feed+0x7e/0x120 [kernel]
0xffffffff81232e8e : __splice_from_pipe+0x6e/0x90 [kernel]
0xffffffff8123483e : splice_from_pipe+0x5e/0x90 [kernel]
0xffffffff81234905 : generic_splice_sendpage+0x15/0x20 [kernel]
0xffffffff8123368d : do_splice_from+0xad/0xf0 [kernel]
0xffffffff812336f0 : direct_splice_actor+0x20/0x30 [kernel]
0xffffffff81233424 : splice_direct_to_actor+0xd4/0x200 [kernel]
0xffffffff812335b2 : do_splice_direct+0x62/0x90 [kernel]
0xffffffff81203518 : do_sendfile+0x1d8/0x3c0 [kernel]
0xffffffff81204b6e : SyS_sendfile64+0x5e/0xb0 [kernel]
0xffffffff816b78c9 : system_call_fastpath+0x16/0x1b [kernel]

流程真长啊。

在2.6的内核中,generic_make_request会先调用__generic_make_request,然后__generic_make_request再调用q->make_request_fn 这个回调函数,

在3.10的内核中,generic_make_request 会直接回调 q->make_request_fn,针对nvme,多队列的这种情况,使用的是 blk_mq_requeue_work.

submit_bio-->generic_make_request--->q->make_request_fn--->blk_mq_requeue_work

任务的执行:blk_mq_make_request--->blk_mq_run_hw_queue,blk_mq_map_request等。

static struct request *blk_mq_map_request(struct request_queue *q,
struct bio *bio,
struct blk_map_ctx *data)
{
struct blk_mq_hw_ctx *hctx;
struct blk_mq_ctx *ctx;
struct request *rq;
int rw = bio_data_dir(bio);
struct blk_mq_alloc_data alloc_data; blk_queue_enter_live(q);
ctx = blk_mq_get_ctx(q); /*
* This assumes per-cpu software queueing queues. They could be per-node
* as well, for instance. For now this is hardcoded as-is. Note that we don't
* care about preemption, since we know the ctx's are persistent. This does
* mean that we can't rely on ctx always matching the currently running CPU.
*/
static inline struct blk_mq_ctx *blk_mq_get_ctx(struct request_queue *q)
{
return __blk_mq_get_ctx(q, get_cpu());
}

static inline struct blk_mq_ctx *__blk_mq_get_ctx(struct request_queue *q,
unsigned int cpu)
{
return per_cpu_ptr(q->queue_ctx, cpu);
}

 

在nvme中,如何把bio插入的queue,映射为在各个cpu上运行的sq呢?利用的是blk_mq_map_queue函数,

static struct blk_mq_ops nvme_mq_admin_ops = {
.queue_rq = nvme_queue_rq,------------------指定blk-mq向驱动提交request的函数
.complete = nvme_complete_rq,---------------完成队列处理
.map_queue = blk_mq_map_queue,--------------映射函数,将software queue和hardware queue对应
.init_hctx = nvme_admin_init_hctx,----------hardware Queue创建时调用,将NVMe Queue与Hardware Queue绑定
.exit_hctx = nvme_admin_exit_hctx,
.init_request = nvme_admin_init_request,----在分配Request时调用
.timeout = nvme_timeout,--------------------发生timeout时的调用
}; static struct blk_mq_ops nvme_mq_ops = {
.queue_rq = nvme_queue_rq,
.complete = nvme_complete_rq,
.map_queue = blk_mq_map_queue,----------映射函数
.init_hctx = nvme_init_hctx,
.init_request = nvme_init_request,
.timeout = nvme_timeout,
};

queue_rq指定blk-mq向驱动提交request的函数,map_queue定义如何将software queue和hardware queue对应,init_hctx是hardware Queue创建时调用(可以在这里将NVMe Queue与Hardware Queue绑定),init_request是在分配Request时调用,timeout是发生timeout时的调用。

linux nvme的sendfile流程的更多相关文章

  1. Linux查看非root流程执行

    Linux查看非root流程执行 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ ps -U root -u root -N PID TTY TIME CMD ...

  2. Linux kernel 的 sendfile 是如何提高性能的

    Linux kernel 的 sendfile 是如何提高性能的 现在流行的 web 服务器里面都提供 sendfile 选项用来提高服务器性能,那到底 sendfile 是什么,怎么影响性能的呢? ...

  3. linux独有的sendfile系统调用--“零拷贝,高效”

    参考:http://blog.csdn.net/caianye/article/details/7576198 如今几乎每个人都听说过Linux中所谓的"零拷贝"特性,然而我经常碰 ...

  4. Linux系统的启动流程

    Linux系统的启动流程: 1.通电(通常按下电源键,开始通电) 2.加载BIOS (通常看到显示器提示按F2进入主板) 3.读取MBR (MBR硬盘的入口地址,用来装载引导) 4.进入引导 (通常有 ...

  5. Linux的开机启动流程

    Linux的开机启动流程 1.开机BIOS自检                                             --> 检查CPU,硬盘等硬件信息 2.MBR[Major ...

  6. Linux操作系统-CentOS7启动流程和服务管理

    Linux操作系统-CentOS7启动流程和服务管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.systemd POST --> Boot Sequence --&g ...

  7. Linux操作系统-CentOS6启动流程和服务管理

    Linux操作系统-CentOS6启动流程和服务管理 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Linux组成 1>.Linux: kernel+rootfs ker ...

  8. linux系统的启动流程梳理

    1. 不同版本的linux系统的启动流程 1.1 centos6.x系统的启动流程 其详细启动步骤如下: 1)开机,BIOS自检,检查各个硬件是否正常 2)读取硬盘MBR信息,引导系统启动 3)加载g ...

  9. 2021年3月-第01阶段-Linux基础-Linux系统的启动流程

    Linux系统的启动流程 理解Linux操作系统启动流程,能有助于后期在企业中更好的维护Linux服务器,能快速定位系统问题,进而解决问题. 上图为Linux操作系统启动流程 1.加载BIOS 计算机 ...

随机推荐

  1. javascript进制转换

    其他进制转十进制 原理 parseInt 或者 Number.parseInt 语法 parseInt(string, radix); string 必需.要被解析的字符串. radix 可选.表示要 ...

  2. Tsung脚本中使用动态参数(一)---直接在脚本里编写Erlang代码

    杀死一个程序猿,只要改三次需求.同理,杀死一个接口自动化测试人员,只要改三次接口数据处理方式.我目前的状态,改了一次接口数据处理方式,有一种胸闷的感觉. 因为改需求,所以,要改脚本.T_T.所以,才有 ...

  3. kindeditor 上传下载文件

    jsp代码 1 <script type="text/javascript" src="${pageContext.request.contextPath}/kin ...

  4. (4程序框架)从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练

    从零开始的嵌入式图像图像处理(PI+QT+OpenCV)实战演练 1综述http://www.cnblogs.com/jsxyhelu/p/7907241.html2环境架设http://www.cn ...

  5. sql servel 报错:将 expression 转换为数据类型 int 时出现算术溢出错误。

    执行sql语句:SELECT   AVG( DATEDIFF(s,s.CreatedDate,s.SendDate)  ) AS submitTime FROM dbo.SmsSend AS s    ...

  6. 从交叉熵损失到Facal Loss

    1交叉熵损失函数的由来1.1关于熵,交叉熵,相对熵(KL散度) 熵:香农信息量的期望.变量的不确定性越大,熵也就越大,把它搞清楚所需要的信息量也就越大.其计算公式如下: 其是一个期望的计算,也是记录随 ...

  7. Vijos-P1057题解

    题目如下: https://www.vijos.org/p/1057 思路分析: 输入文件第一行为两个整数n,m(1<=n,m<=1000),接下来n行,每行m个数字,用空格隔开.0表示该 ...

  8. CTF---Web入门第九题 FALSE

    FALSE分值:10 来源: iFurySt 难度:易 参与人数:4567人 Get Flag:2144人 答题人数:2157人 解题通过率:99% PHP代码审计 hint:sha1函数你有认真了解 ...

  9. ucosii --任务就绪表

    任务就绪表的任务就是高效的找出当前优先级最高的就绪任务. 由任务就绪表OSRdyTbl和任务就绪组OSRdyGrb组成,OSRdyTbl每一个位都记录着一个任务的就绪状态, 0非就绪1就绪,OSRdy ...

  10. c#版 K线控件(Stock)

    K线起源于日本米市交易,它的基本用途就是为了寻找"买卖点".股市及期货市场中的K线图的画法包含四个数据,即开盘价.最高价.最低价.收盘价,所有的k线都是围绕这四个数据展开,反映大势 ...