SPDK NVME

SPDK NVME

1、SPDK(APP)在启动时候会让指定绑定在那些core上运行,这样在每个core上会创建一个线程(他叫reactor),这个线程不停的做polling操作,而如果你要在这个线程上做事情,则需要注册poller( 可以理解为一个poller就是SPDK中一个事情的thread入口函数,但是),这个线程就不停的调用poller的机型函数执行你要执行的动作。

2、一个NVME的开始和结束的过程是:

2.1、probe NVME设备也就是prob发现ctrlloer.然后在给这个contrlloer创建一个IO qpair(admin qpair是在创建ctrlloer时候就创建了)。也就是创建submisson queue和completion queue.当然可以创建多个sq和一个cq的。但一般是一个sq和cq对应。创建好qpair后就可以通过qpair下发IO操作了。

2.2、一个读写请求,发到qpair的submisson queue中,这个submisson queue是一个环形队列,此时这个环形队列的tail指针++,此时再把这个 tail位置通过门铃寄存器(每个qpair一个门铃寄存器)告诉下面的盘(controller)。此时controller根据门铃寄存器记录的环形队列的尾巴知道数据最多可以取到哪里。环形队列的head指针controller也是可以知道。而且处理一个请求这个head指针++,这个head位置是controller来维护的,但是这个位置可以通过completion queue的entry记录着。没处理完一个请求,则controller会产生一个完成请求entry,然后挂在completion queue中,然后更新completion queue的head位置,然后通过中断告诉host可以取完成请求了。主机host通过head位置访问completion queue的那个entry。

 

3、SPDK中线程通信的方式:

SPDK中多个core对应多个线程。然后线程间通信是怎么进行的呢?分两步:1、分配一个event,然后将这个event添加到需要通信的core的event ring中,等待这个core来调用执行。这里产生event(spdk_event_allocate)时候需要确定三个东西,一个是coreid,也就是你要和那个core通信,一个是这个event对应的处理函数func.一个是func的参数。在调用spdk_event_call是将这个event加入到这个event指定的coreid的spdk_vring中。之所以能加入到coroid对应的vring中,是因为每个core也就是reactor或者线程是一个数组表示的。第一个coreid就能找到第几个reactor,然后就能找到他对应的vring.然后加入进去。后面目的core在自己的reactor线程中取到这个 event时候就可以执行相应的函数然后就实现了两个线程间的通信了。

SPDK NVME_第1张图片SPDK NVME_第2张图片

SPDK NVME_第3张图片

SPDK中reactor线程就是在不停的对event链表,poller链表和timer_poller三个链表进行处理。每个循环都会去取对应的请求来处理,这里的处理就是调用他们的func函数。

SPDK NVME_第4张图片

SPDK NVME_第5张图片

你可能感兴趣的:(SPDK NVME)