0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ImageKnife简介

OpenAtom OpenHarmony 来源:OpenAtom OpenHarmony 作者:OpenAtom OpenHarmony 2022-06-17 11:53 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

图片是 UI 界面的重要元素之一,图片加载速度及效果直接影响应用体验。ArkUI 开发框架提供了丰富的图像处理能力,如图像解码、图像编码、图像编辑及基本的位图操作等,满足了开发者日常开发所需。但随着产品需求的日益增长,基本的图像处理能力已不能胜任某些比较复杂的应用场景,如无法直接获取缓存图片、无法配置占位图、无法进行自定义 PixelMap 图片变换等。为增强 ArkUI 开发框架的图像处理能力,ImageKnife 组件应运而生,本期我们将为大家带来 ImageKnife 的介绍。

一、ImageKnife简介

ImageKnife 是一个参考 Glide 框架进行设计,并基于 eTS 语言实现的图片处理组件,让开发者能轻松且高效地进行图片开发。而 Glide 是一个快速高效的图片加载库,它注重于平滑的滚动,提供了易用的 API,高性能、可扩展的图片解码管道,以及自动的资源池技术。

功能方面,ImageKnife 提供了自定义图片变换、占位图等图片处理能力,几乎满足了开发者进行图片处理的一切需求。性能方面,ImageKnife 采用 LRU 策略实现二级缓存,可灵活配置,有效减少内存消耗,提升了应用性能。使用方面,ImageKnife 封装了一套完整的图片加载流程,开发者只需根据 ImageKnifeOption 配置相关信息即可完成图片的开发,降低了开发难度,提升了开发效率。如图 1 所示,是 ImageKnife 加载图片的整体流程。

503b9a54-d6ac-11ec-bce3-dac502259ad0.jpg

图1 ImageKnife加载图片整体流程

二、ImageKnife实现原理

下面我们将为大家介绍 ImageKnife 加载图片过程中每个环节的实现原理,让大家更深刻地认识 ImageKnife 组件。图 2 是 ImageKnife 加载图片的时序图:

504d2bc0-d6ac-11ec-bce3-dac502259ad0.jpg

图2 ImageKnife加载图片的时序图

2.1 用户配置信息

在加载图片前,用户需根据自身需求配置相应的参数,包括图片路径、图片大小、占位图及缓存策略等。ImageKnife 提供了 RequestOption 类,用于封装用户配置信息的接口,如图 3 所示列举了部分接口供大家参考:

50a4202e-d6ac-11ec-bce3-dac502259ad0.jpg

图3 用户配置参数

通过 imageKnifeExecute() 方法获取用户配置信息,然后执行 ImageKnife.call(request),正式启动图片加载任务。相关实现代码如下:


imageKnifeExecute() {  // 首先需要确保获取ImageKnife单例对象  if(ImageKnife){  }else{    ImageKnife = globalThis.exports.default.data.imageKnife;  }  // 生成配置信息requestOption  let request = new RequestOption();  // 配置必要信息和回调  this.configNecessary(request);  // 配置缓存相关信息     this.configCacheStrategy(request);  // 配置显示信息和回调   this.configDisplay(request);  // 启动ImageKnife执行请求  ImageKnife.call(request);}

2.2 加载图片

加载图片过程是 ImageKnife 组件的核心部分,如图 4 所示,包含占位图填充、缓存实现及图片解码三个环节。下面我们将为大家分别介绍每个环节的实现。

50df29b2-d6ac-11ec-bce3-dac502259ad0.jpg

图4 图片加载过程

2.2.1 占位图填充

占位图就是图片加载过程中页面上的过渡效果,通常表现形式是在页面上待加载区域填充灰色的占位图,可以使得页面框架不会因为加载失败而变形。ImageKnife 提供了占位图功能,开发者可在 RequestOption 中配置是否启动占位图任务。如图 5 所示是占位图工作流程,执行图片加载任务后,占位图会填充加载页面。如果图片解析成功则将页面上填充的占位图替换为待加载的图片。如果图片解析失败,则将页面上填充的占位图替换为“图片解析失败占位图”。

50f9905e-d6ac-11ec-bce3-dac502259ad0.jpg

图5 占位图工作流程

相关实现代码如下:


// 占位图解析成功placeholderOnComplete(imageKnifeData: ImageKnifeData) {// 主图未加载成功,并且未加载失败  显示占位图  主图加载成功或者加载失败后=>不展示占位图  if (!this.loadMainReady && !this.loadErrorReady && !this.loadThumbnailReady) {        this.placeholderFunc(imageKnifeData)  }}// 加载失败 占位图解析成功errorholderOnComplete(imageKnifeData: ImageKnifeData) {  // 如果有错误占位图 先解析并保存在RequestOption中 等到加载失败时候进行调用  this.errorholderData = imageKnifeData;  if (this.loadErrorReady) {    this.errorholderFunc(imageKnifeData)}

2.2.2 缓存实现

缓存是图片加载过程中最关键的环节,缓存机制直接影响了图片加载速度及图片滚动效果,开发者可通过以下方法来灵活配置缓存策略。

5115f8b6-d6ac-11ec-bce3-dac502259ad0.jpg

图6 缓存策略API

为了保障图片的加载速度,ImageKnife 通过使用 Least Recently Used(最近最少使用)清空策略来实现内存缓存及磁盘缓存。如图 7 所示,在图片加载过程中,CPU 会首先读取内存缓存中的数据,如果读取到图片资源则直接显示图片,否则读取磁盘缓存数据。如果在磁盘缓存上仍然没有读取到数据,则可判定为该图片为网络图片,这时需要将网络图片解码后再进行显示(后面章节会详细介绍),并将解码后的图片文件缓存至磁盘。

5164b046-d6ac-11ec-bce3-dac502259ad0.jpg

图7 图片缓存过程

下面我们将分别介绍两种缓存机制的具体实现。

(1)内存缓存

内存缓存,就是指当前程序运行内存分配的临时存储器,当我们使用 ImageKnife 加载图片时,这张图片会被缓存到内存当中,只要在它还没从内存中被清除之前,下次再加载这张图片都会直接从内存中读取,而不用重新从网络或硬盘上读取,大幅度提升图片的加载效率。ImageKnife 内存缓存的实现,需控制最大空间(maxsize),以及目前占用空间(size),相关实现代码如下:


// 移除较少使用的缓存数据trimToSize(tempsize: number) {  while (true) {    if (tempsize < 0) {      this.map.clear()      this.size = 0      break    }    if (this.size <= tempsize || this.map.isEmpty()) {      break    }    var delkey = this.map.getFirstKey()    this.map.remove(delkey)    this.size--  }}
// 缓存数据最大值maxSize(): number{  return this.maxsize}
// 设置缓存数据量最大值resize(maxsize: number) {  if (maxsize < 0) {    throw new Error('maxsize <0 & maxsize invalid');  }  this.maxsize = maxsize  this.trimToSize(maxsize)}
// 清除缓存evicAll() {  this.trimToSize(-1)}

(2)磁盘缓存

默认情况下,磁盘缓存的是解码后的图片文件,需防止应用重复从网络或其他地方下载和读取数据。ImageKnife 磁盘缓存的实现,主要依靠 journal 文件对缓存数据进行保存,保证程序磁盘缓存内容的持久化问题。相关实现代码:


//读取journal文件的缓存数据readJournal(path: string) {  var fileReader = new FileReader(path)  var line: string = ''  while (!fileReader.isEnd()) {    line = fileReader.readLine()    line = line.replace('
', '').replace('
', '')    this.dealwithJournal(line)  }  this.fileUtils.deleteFile(this.journalPathTemp)  this.trimToSize()}
//根据LRU算法删除多余缓存数据private trimToSize() {  while (this.size > this.maxSize) {    var tempkey: string = this.cacheMap.getFirstKey()    var fileSize = this.fileUtils.getFileSize(this.dirPath + tempkey)    if (fileSize > 0) {      this.size = this.size - fileSize    }    this.fileUtils.deleteFile(this.dirPath + tempkey)    this.cacheMap.remove(tempkey)    this.fileUtils.writeData(this.journalPath, 'remove ' + tempkey + '
')  }}
//清除所有disk缓存数据cleanCacheData() {  var length = this.cacheMap.size()  for (var index = 0; index < length; index++) {    this.fileUtils.deleteFile(this.dirPath + this.cacheMap[index])  }  this.fileUtils.deleteFile(this.journalPath)  this.cacheMap.clear()  this.size = 0}

2.2.3 图片解码

当我们使用 ImageKnife 去加载一张图片的时候,并不是将原始图片直接显示出来,而是会进行图片解码后再显示到页面。图片解码就是将不同格式的图片(包括 JPEG、PNG、GIF、WebP、BMP)解码成统一格式的 PixelMap 图片文件。ImageKnife 的图片解码能力依赖的是 ArkUI 开发框架提供的 ImageSource 解码能力。通过 import image from '@ohos.multimedia.image'导入 ArkUI 开发框架的图片能力,并调用 createImageSource() 方法获取,实现代码如下:


import image from '@ohos.multimedia.image'
export class TransformUtils {  static centerCrop(buf: ArrayBuffer, outWidth: number, outHeihgt: number,                    callback?: AsyncTransform>) {    // 创建媒体解码imageSource    var imageSource = image.createImageSource(buf as any);    // 获取图片信息    imageSource.getImageInfo()      .then((p) => {        var sw;        var sh;        var scale;        var pw = p.size.width;        var ph = p.size.height;        // 根据centerCrop规则控制缩放比例        if (pw == outWidth && ph == outHeihgt) {          sw = outWidth;          sh = outHeihgt;        } else {          if (pw * outHeihgt > outWidth * ph) {            scale = outHeihgt / ph;          } else {            scale = outWidth / pw;          }          sw = pw * scale;          sh = ph * scale;        }        var options = {          editable: true,          rotate: 0,          desiredRegion: { size: { width: sw, height: sh },            x: pw / 2 - sw / 2,            y: ph / 2 - sh / 2,          },        }        if (callback) {          // 回调,创建相关配置pixelmap          callback('', imageSource.createPixelMap(options));        }      })      .catch((error) => {        callback(error, null);      })  }}

2.3 显示图片

获取到 PixelMap 解码文件后,接下来就是将它渲染到应用界面上。ImageKnife 的图片渲染能力依赖的是 ArkUI 开发框架提供的 image 组件的渲染能力。由于 eTS 是声明式的,我们无法直接获得 Image 组件的对象,需要依赖 ArkUI 开发框架的 @State 能力绑定输入参数,在改变属性对象之后,通知 UI 组件重新渲染,达到图片显示的效果,相关代码如下:
@Componentexport struct ImageKnifeComponent {  @Watch('watchImageKnifeOption') @Link imageKnifeOption: ImageKnifeOption;  @State imageKnifePixelMapPack: PixelMapPack = new PixelMapPack();  @State imageKnifeResource: Resource = $r('app.media.icon_loading')  @State imageKnifeString: string = ''  @State normalPixelMap: boolean = false;  @State normalResource: boolean = true;  previousData: ImageKnifeData = null;  nowData: ImageKnifeData = null;
  build() {    Stack() {      //Image组件配置      Image(this.normalPixelMap ? this.imageKnifePixelMapPack.pixelMap : (this.normalResource ? this.imageKnifeResource : this.imageKnifeString))        .objectFit(this.imageKnifeOption.imageFit ? this.imageKnifeOption.imageFit : ImageFit.Fill)        .visibility(this.imageVisible)        .width(this.imageWidth)        .height(this.imageHeight)    }  }  //必要的用户配置和回调方法  configNecessary(request: RequestOption){    request.load(this.imageKnifeOption.loadSrc)      .addListener((err, data) => {        console.log('request.load callback')        this.imageKnifeChangeSource(data)        this.animateTo('image');        return false;      })
    if (this.imageKnifeOption.size) {      request.setImageViewSize(this.imageKnifeOption.size)    }  }  // imageknife 第一次启动和数据刷新后重新发送请求  imageKnifeExecute() {    let request = new RequestOption();    this.configNecessary(request);    this.configCacheStrategy(request);    this.configDisplay(request);    ImageKnife.call(request);  }  //返回数据Image渲染展示图片  imageKnifeSpecialFixed(data:ImageKnifeData) {    if (data.isPixelMap()) {      this.displayPixelMap(data);    }    else if (data.isString()) {      this.displayString(data);    } else if (data.isResource()) {      this.displayResource(data);    } else {    }  }}
注:@State 装饰的变量是组件内部的状态数据,当这些状态数据被修改时,将会调用所在组件的 build 方法进行 UI 刷新。

三、ImageKnife实战

通过上文的介绍,相信大家对 ImageKnife 组件有了深刻的了解。下面我们将创建一个 ImageKnife_Test 项目,为大家展示 ArkUI 开发框架中 ImageKnife 组件的使用。通过将 ImageKnife 组件下载至项目中,然后根据 ImageKnifeOption 配置相关信息,即可完成 GIF 图片的加载。

3.1 创建项目

如图 8 所示,在 DevEco Studio 中新建 ImageKnife_Test 项目,项目类型选择 Application,语言选择 eTS,点击 Finish 完成创建。

51e17770-d6ac-11ec-bce3-dac502259ad0.jpg

图8 创建项目

3.2 添加依赖

成功创建项目后,接下来就是将 ImageKnife 组件下载至项目中。

首先,我们需找到 .npmrc 配置文件,并在文件中添加 @ohos 的 scope 仓库地址:@ohos:registry=https://repo.harmonyos.com/npm/,如图 9 所示:

52287cec-d6ac-11ec-bce3-dac502259ad0.jpg

图9 添加 scope仓库地址

配置好 npm 仓库地址后,如图 10 所示,在 DevEco Studio 的底部导航栏,点击“Terminal”(快捷键 Alt+F12),键入命令:npm install @ohos/imageknife 并回车,此时 ImageKnife 组件会被自动下载至项目中。下载完成后工程根目录下会生成 node_modules/@ohos/imageknife 目录。

526d892c-d6ac-11ec-bce3-dac502259ad0.jpg

图10 下载至项目

3.3 编写逻辑代码

ImageKnife 组件成功下载至项目中后,接下来就是逻辑代码编写,这里我们将为大家介绍两种使用方式:

方式一:首先初始化全局 ImageKnife 实例,然后在 app.ets 中调用 ImageKnife.with() 进行初始化,相关代码如下:


import {ImageKnife} from '@ohos/imageknife'export default {  data: {    imageKnife: {} // ImageKnife  },  onCreate() {    this.data.imageKnife = ImageKnife.with();  },  onDestroy() {  },}然后在页面index.ets中使用imageknife,相关代码如下:@Entry@Componentstruct Index {  build() {
  }
  // 页面初始化完成,生命周期回调函数中 进行调用ImageKnife  aboutToAppear() {    let requestOption = new RequestOption();  requestOptin.load($r('app.media.IceCream'))  .addListener((err,data) => {      //加载成功/失败回调监听    })    ...  ImageKnife.call(requestOption)  }}
var ImageKnife;var defaultTemp = globalThis.exports.defaultif (defaultTemp != undefined) {  ImageKnife = defaultTemp.data.imageKnife;}
方式二:在 index.ets 中,直接使用 ImageKnifeOption 作为入参,并配合自定义组件 ImageKnifeComponent 使用,相关代码如下:
import {ImageKnifeOption} from '@ohos/imageknife'
@Entry@Componentstruct Index {  @State imageKnifeOption1: ImageKnifeOption =    {      loadSrc: $r('app.media.gifSample'),      size: { width: 300, height: 300 },      placeholderSrc: $r('app.media.icon_loading'),      errorholderSrc: $r('app.media.icon_failed')    };  build() {    Scroll() {      Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {        ImageKnifeComponent({ imageKnifeOption: $imageKnifeOption1 })      }    }    .width('100%')    .height('100%')  }}
以上就是本期全部内容,恭喜大家又花几分钟时间收获了一个实用的组件。希望广大开发者能利用这个强大的开源组件开发出更多精美的应用。同时,我们会陆续更新实用组件的解析,敬请期待! 审核编辑 :李倩

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 框架
    +关注

    关注

    0

    文章

    404

    浏览量

    18497
  • 组件
    +关注

    关注

    1

    文章

    602

    浏览量

    19067

原文标题:ImageKnife组件,让小白也能轻松搞定图片开发

文章出处:【微信号:gh_e4f28cfa3159,微信公众号:OpenAtom OpenHarmony】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    中科源CPET简介及产品体系简介

          车载电源总成是电动汽车的核心 “能量枢纽”,集成车载充电机(OBC)、DC/DC 变换器、高压配电盒(PDU)三大关键部件,可根据应用需求设计为独立式或二合一/三合一/多合一集成式,作为整车“电控总成”的核心模块,其承担着外部电网与动力电池、高压系统与低压系统之间的电能转换、传输及管理核心功能,直接决定电动汽车的充电速度、用电效率与运行稳定性,产品可靠性更是整车安全与核心性能的重要保障。因此,在成品阶段对车载电源
    发表于 03-20 11:14 0次下载

    CET消防设备电源监控系统简介

    电子发烧友网站提供《CET消防设备电源监控系统简介 .pdf》资料免费下载
    发表于 03-18 15:11 0次下载

    各种显示技术简介

    各种 显示****技术简介 致力成为差异化显示领域中全链路方案的领先者 ** 各种显示器方案** 1.多种规格的芯片,根据不同功能,选择最合适的芯片 2.适应场景多,兼容性强 3.画质好,色彩
    发表于 02-02 15:51

    半导体金线键合(Gold Wire Bonding)封装工艺技术简介

    【博主简介】本人“爱在七夕时”,系一名半导体行业质量管理从业者,旨在业余时间不定期的分享半导体行业中的:产品质量、失效分析、可靠性分析和产品基础应用等相关知识。常言:真知不问出处,所分享的内容
    的头像 发表于 12-07 20:58 1239次阅读
    半导体金线键合(Gold Wire Bonding)封装工艺技术<b class='flag-5'>简介</b>;

    比较器的简介分类

    一、比较器简介据圣邦微SGMICRO比较器一级代理鑫富立介绍,比较器是一种得到广泛使用的电路元件。实际上也是增益非常高的运算放大器,可以放大输入端很小的差分信号,并驱动输出端切换到两个输出状态中的一
    的头像 发表于 11-21 20:13 646次阅读
    比较器的<b class='flag-5'>简介</b>分类

    VDMA IP核简介

    VDMA端口信号 S_AXI_LITE:PS端可以通过AXI_LITE协议对IP核进行控制; S_AXIS_S2MM:视频流(AXI STREAM)输入到IP核的FIFO中; S_AXIS_MM2S:IP核的FIFO生成视频流(AXI STREAM)输出到后端; S_AXI_S2MM:IP核的FIFO中的像素数据存入memory; S_AXI_MM2S:memory中的像素数据输出到IP核的FIFO中; s_axi_lite_aclk、s_axi_mm2s_aclk、s_axis_mm2s_aclk、s_axi_s2mm_aclk、s_axis_s2mm_aclk分别为上述端口的控制时钟,一般采用同一频率时钟。 mm2s_introut和s2mm_introut分别为MM2S和S2MM通道完成后的中断信号输出。 VDMA基础设置 Address Width:地址宽度,与memory一致; Frame Buffers:帧缓存数量,当选择1时,则输入输出皆在同一块内存中;当选择2及以上时,则输入输出操作不同内存区域,且交替进行; Memory Map Data Width:S_AXI_S2MM或S_AXI_MM2S通道的数据位宽,且必须大于视频流数据位宽; Burst Szie:AXI猝发传输大小,一般设置为16; Stream Data Width:视频流数据位宽,一般由VDMA前端输入自动确定; Line Buffer Depth:S_AXIS_S2MM或S_AXIS_MM2S通道FIFO,当输入输出视频帧率相当时,可以适当选择较小深度,当输入输出视频帧率差别较大时,需要加大FIFO深度。 对于写通道,同步选项选择s2mm tuser,即当一帧视频的第一个像素到来时,s2mm tuser被拉高,VDMA开始写入memory; 对于读通道,同步选项选择None,即只要后端准备好接受数据,ready信号为1时,VDMA即开始输出像素点; 至于GenLock Mode,写通道和读通道分别选择Dynamic-Master和Dynamic-Slave,即写通道依次写入0,1,2···,而读通道每次读取写通道上一帧数据,并且写通道和读通道都可以跳过对方正在操作的帧。 VDMA寄存器设置 主要有以下几个重要寄存器: 注意:HSIZE和STRIDE都是以Byte为单位,且VSIZE设置必须放置在所有寄存器设置的最后。
    发表于 10-28 06:14

    国密系列算法简介及SM4算法原理介绍

    一、 国密系列算法简介 国家商用密码算法(简称国密/商密算法),是由我国国家密码管理局制定并公布的密码算法标准。其分类1所示: 图1 国家商用密码算法分类 就各种商用密码的用途而言,如下
    发表于 10-24 08:25

    risc-v P扩展(一) P指令集简介

    一、P扩展简介: 数字信号处理(DSP)已成为现代电子系统的重要技术。广泛的现代应用都采用DSP算法来解决其特定领域的问题,包括传感器融合、伺服电机控制、音频解码/编码、语音合成和编码、MPEG4
    发表于 10-23 07:40

    AES加密模式简介与对比分析

    一、 常见加密模式简介 前几篇分享介绍了AES和SM4加密算法。在加密算法的基础上,还有不同的加密模式。加密模式是在计算机和通信领域中用于保护数据安全性的重要概念。它定义了加密算法在处理大量数据
    发表于 10-22 08:21

    AXI GPIO扩展e203 IO口简介

    AXI GPIO简介 AXI-GPIO是一种Xilinx公司开发的外设IP,可以连接到AXI总线上,并提供GPIO(General Purpose Input Output)功能。AXI-GPIO
    发表于 10-22 08:14

    Perforce P4产品简介:无限扩展+全球协作+安全管控+工具集成

    P4中文版产品简介,由龙智整理,欢迎下载&交流探讨。来看看为什么3A游戏、虚拟制片、半导体团队都在用P4进行版本控制。还未用过的小伙伴,也欢迎联系免费体验!
    的头像 发表于 05-30 13:32 942次阅读
    Perforce P4产品<b class='flag-5'>简介</b>:无限扩展+全球协作+安全管控+工具集成

    FPC组成简介及工程设计规范

    FPC产品简介概述: 1,FPC概念 2,FPC产品结构组成 3,FPC材料 4,FPC产品类型 5,FPC产品特征 FPC(Flexible Printed Circuit)挠性印刷电路版,简称
    发表于 05-27 15:10

    【直播预告】《实时操作系统应用技术—基于RT-Thread与ARM的编程实践》教学脉络及资源简介

    直播预告直播主题:《实时操作系统应用技术—基于RT-Thread与ARM的编程实践》教学脉络及资源简介开放时间:2025年5月29日(周四)20:00主讲老师:王宜怀课程类型:视频直播观看平台
    的头像 发表于 05-26 17:50 1409次阅读
    【直播预告】《实时操作系统应用技术—基于RT-Thread与ARM的编程实践》教学脉络及资源<b class='flag-5'>简介</b>

    蓝牙LE Audio技术简介和优势分析

    Energy)技术的优点,同时又具备卓越的音频性能。本文将从技术简介和优势分析两个方面对蓝牙LE Audio技术进行详细的介绍。 一、蓝牙LE Audio技术简介 蓝牙LE Audio技术是蓝牙技术联盟在
    的头像 发表于 05-21 16:08 5208次阅读

    NVMe协议简介2

    NVMe指令提交与完成机制 NVMe指令提交与完成机制是NVMe协议的核心,该机制制定了NVMe指令的交互流程和处理步骤。在基于PCIe的NVMe协议中,NVMe主机控制器与NVMe设备的交互通过PCIe进行,使用PCIe的存储读写TLP请求。指令的提交与完成机制如图1所示,图中展示的指令提交与完成步骤如下: 图1 NVMe指令提交与完成步骤图 (1)主机控制器向提交队列写入一个或多个提交命令; (2)主机请求配置NVMe设备的提交队列尾门铃寄存器,表示有新的命令需要进行处理; (3)NVMe设备从提交队列中读取提交指令条目; (4)NVMe继续执行获取的命令,命令可以无序完成; (5)命令完成执行后,控制器将完成队列条目写入关联的完成队列。NVMe设备在完成队列条目中提供最近的关联提交队列条目头指针; (6)NVMe设备可选地向主机生成一个中断,以表明有一个新的完成队列条目要等待主机控制器使用和处理; (7)主机控制器处理完成队列中的新完成队列条目; (8)主机控制器请求配置完成队列头门铃寄存器,指示完成队列条目已被处理。
    发表于 05-15 23:15