自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(46)
  • 收藏
  • 关注

原创 NVME 类IO命令

该命令用于在一个NS上获取一个“预定”,抢占一个“预定”并持有NS,并终止持有NS的“预定”。该命令使用CDW10和Reservation Acquire structure,使用PRP1和PRP2(或者sgl)携带的信息CDW10RTYPE(除去预定可xx,其他都被禁止)另外一个信息是Reservation Acquire structure。

2024-08-20 19:46:24 999

原创 nvme-cli常见命令分析

nvme-cli命令常常用于获取或者设置SSD参数,比如常见的nvme list,nvme id-ctrl等,都是获取SSD的基本信息,也有nvme admin-passthru用于读取或者设置自定义命令。作为使用者,我们并不知道nvme-cli源码怎么实现的,为了探究溯源,阅读源码探究一下nvme-cli常见命令的细节。具体的nvme-cli master代码下载地址见。

2024-06-05 22:35:34 1299

原创 链路初始化和训练

链路初始化和训练,由物理层进行控制,是一个基于硬件的过程。初始化设备的链路和端口,使得设备能够收发报文,在链路上正常通信。在reset后由硬件自动启动完整的训练过程,并由LTSSM管理。1 位锁定训练开始,接收端时钟和发送端时钟不同步,接收端无法可靠采样输入信号的数据bit训练期间,接收端的时钟和数据恢复(CDR,clock and data recovery)逻辑,通过使用数据bit流作为时钟的参考信号,来重建发送端的时钟,一旦从数据流中恢复了时钟,表示接收端完成位锁定。2 符号锁定。

2024-05-25 15:23:20 1233

原创 代码随想录训练营32day-动态规划5

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,。给定一个代表每个房屋存放金额的非负整数数组,计算你,一夜之内能够偷窃到的最高金额。思路:当前房屋有2个状态:偷和不偷若是当前房屋被偷,那么前一个房屋必不能被偷(触发警报),前2个房屋可以被偷,若是当前房屋没被偷,那么前一个房屋可以被偷。动态规划步骤:1 dp[i]代表第i个房屋,前面i个房屋被偷的最大金额;

2024-05-13 22:32:11 397

原创 NVME协议第四章-Data Structures

本章描述NVME所需的数据结构(讨论均基于PCIE over NVME)。

2024-05-10 15:12:07 1167

原创 代码随想录训练营31day-动态规划4

给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数。3 初始化:dp[0] = 0,凑成0的个数为0,其余应该是INT_MAX;3 初始化dp[0] = 1,如果等于0,那么累加依旧等于0,其余值为0;题目求的是组合数目,和常见的完全背包问题,求最大价值不一样。1 定义dp[j],表示j数字下,能组合成j的组合数目。思路:完全平方数看作物品,n代表背包,物品可以多次放入。3 初始化时候,dp[0] = 1,其余初始化为0;1 设置dp[j],代表数字j的组合个数;

2024-05-06 21:51:18 882

原创 Nvme协议第三章 Controller Registers

控制器寄存器位于MLBAR/MUBAR寄存器(PCI BAR0和BAR1)中,该寄存器应映射到支持有序访问和可变访问宽度的内存空间。host主机通过访问虚拟内存的方式访问该部分寄存器。注:访问过程只能一次访问一个寄存器,不能多个访问。

2024-05-06 19:55:59 1521

原创 NVME协议第二章 System Bus Registers

本章节主要详细地介绍如何为Nvme控制器构造PCI Header,PCI Capability,PCI Express Extended Capabilities。(PCI相关可参考。

2024-05-06 12:01:35 329

原创 代码随想录训练营30-动态规划3

一开始阅读题目,根本联系不到01背包,但是仔细分析,题目可以转化为求2堆相近的石头,这样大堆减小堆石头,得到的值应该就是最小值。但是怎么求其中某一堆石头呢?结合分割等和子集,找到一个target,利用01背包,就可以找到最大的dp,即找到最大的石头堆。怎么获取target,一个整体分成两部分,那么和对半分,就是需要石头堆的最大值。(a) : (b)//把问题拆分成:划分成两块相近的石头堆,就可以使用0、1背包//根据题目限制。

2024-05-04 12:14:25 336

原创 使用qemu调试NVME driver

编译完成后,将image拷贝到buildboot的output目录下(根据自己保存的目录 最终的目录名称应该都一样)。于是想了一个办法,新拉了一个Linux内核版本,目前我使用的是linux-6.8.8版本,于是编译Linux。但是这里遇到参考博客评论区遇到的问题,使用ls-l /dev/n*命令找nvme设备,没有找到任何设备。然后执行上面的qemu命令运行qemu,可以正常看到nvme设备,此时就可以调试nvme驱动代码。另外,builidroot可以下载最新的版本,进入网站下载,进行解压。

2024-05-01 10:40:34 842 1

原创 代码随想录训练营29-动态规划2

具体可以参考。

2024-04-29 16:35:18 197

原创 代码随想录训练营28day-动态规划

1 dp[i]代表走到i阶梯上的方案数量,初始化时候,0阶梯讨论无意义,dp[1] =1 dp[2] =2。1 dp[i]代表F[i],初始值F[0] = 0 F[1] = 1;题目规定可以走1步或者2步,需要 n 阶你才能到达楼顶,有多少方案?注意:动态规划题目,一定要理解dp的含义,以及状态转移公式的推导。2 状态转移方程:F(n) = F(n-1) + F(n -2)2 转移方程dp[i] = dp[i -1] + dp[i-2]3 最后返回F(n)

2024-04-29 08:57:18 273

原创 代码随想录训练营27day-贪心算法5

以下全部都是关于重叠问题的题目。

2024-04-28 16:53:46 656

原创 代码随想录训练营26day-贪心算法4

首先需要消耗10元,因为5元可以兑换零钱方式更多,先把兑换方式少的减掉。2 排序k(人数)因为身高已经排序成功,所以需要考虑的是k值,把k插入对应的位置,这样people身高是排序的,只需要考虑k的位置,就满足了两个条件。2 如果是10元,那么需要five--,ten++,但是如果five本身就小于0,那么不可能找零成功,返回false;题目解析:注意一开始是没有零钱,也只会取5 10 20三类数字,因此从这3类数字出发,去判断。1 先考虑身高,从高到低,如果身高相同,那么k(人数)少的排前面。

2024-04-23 12:01:32 596

原创 代码随想录训练营25day-贪心算法3

主要是用贪心的思维解决问题,达到训练的目的。题目中说明了必须要用k次,数组也有负数或者正数,怎么让数组最大化呢?1 k次范围内,把所有的负数全部翻转,这样能够最大化;2 如果还剩下次数k-n(n是负数的个数),那么怎么最大化呢?一开始思考时候,把最小的数字依次翻转,代价最小,但是这个思路是错误的,找到现在数组最小的元素,来回翻转(题目说同一个元素可以来回翻转),损失最多就是减少该值,这样代价才最小。3 综合上面两个情况,这样能全局最优,获取最大的值。

2024-04-22 11:09:38 421

原创 代码随想录训练营24day-贪心算法2

题目介绍限制条件,必须卖了再买,而且当前交易一只股票。一开始想法是去遍历,找到每个区间段间的差值,然后再相加。看了解答,其实每一天的利润,都是可以用差值表示出来,每一天的利润最大,那么累加起来,总利润也是最大的。再思考怎么能最大化,只要每天的是正利润,那么就是递增的。

2024-04-21 10:58:01 436

原创 代码随想录训练营23day-贪心算法

贪心算法核心思想是局部最优,以确定全局最优。当然需要使用数学归纳去总结,但是实际应用过程,可以举反例来验证是不是可以使用贪心算法。参考代码随想录(

2024-04-19 13:59:11 725

原创 代码随想录训练营21day-回溯4

主要在于怎么选择子序列:首先同层的处理,需要判断,当前层前面出现过的数字,后面不能再使用(很重要!另外,如果path头部数字和当前数字不是递增的,那么需要跳过。全排列是找所有可能的组合,因此,不需要用startindx来拆分了,数字都会重复使用,但是在纵向迭代时候,需要记录这个值是否使用过,如果使用过,那么跳出;本题不能按照前面的方法来判断重复数字,因为数组本来就带顺序属性,不能移动。主要是理解used在树枝和树层的含义!一、491 非递减子序列。

2024-04-17 22:24:18 213

原创 代码随想录训练营20day-回溯3

解决问题过程中,遇到问题:2 *returnsize赋初值,如果不满足条件 直接会回NULL;

2024-04-16 13:20:11 331

原创 代码随想录训练营-20day 回溯2

回溯的模板思路:当sum大于等于目标值 可以返回,其中等于目标值时候,把结果返回到result上;回溯时候,记录path和sum。特别重要一点,回溯时候,start还是从当前位置出发,这里数字可以重复,只要找到对应的目标值。

2024-04-15 13:53:42 314

原创 代码随想录训练营18day-二叉树7

利用二叉搜索树的有序性,每一层遍历时候,最小差一定是在相邻的两个节点间产生的,因此做递归的时候,记录一个pre和cur节点,用来比较差值,迭代更新时候,记录最小值。二叉搜索树中序遍历,能有效利用有序性。迭代法:根据之前的中序遍历,进行修改:这里也需要记录pre和cur节点,方便进行比较最小差值。

2024-04-13 22:19:12 952

原创 代码随想录训练营19day-回溯1

1 回溯搜索法,通常用于解决穷举问题,列举所以可能性结果,找到想要的结果。类似于枚举多少组合,多少个可能性结果的情况,都需要用回溯法。2 回溯一般和递归成对出现,处理当前结果,进入递归,再回溯,一一对应。3 回溯的一般模板(参考代码随想录)

2024-04-13 20:44:33 450

原创 代码随想录训练营17day-二叉树6

这里遇到一个初始化问题:在leetcode上面,如果全局初始化,会导致数据异常!如下图,我把pre指针放在全局初始化,导致某一次预期pre应该为空,但是实际却没有。2)创建节点,初始化(这里需要结构体所有的entry都初始化),然后递归到子树;1)函数返回条件:如果root1为空,不管root2怎么样,直接返回root2;3)因为不是全局搜索,找到指定条件需要返回,因此需要返回值。1)返回条件:如果root为空,或者找到指定value;2)单层递归:因为搜索树是有序的,所以应该判断;4)返回root节点。

2024-04-12 15:33:54 300

原创 代码随想录训练营16day:二叉树5

1)第一就是malloc时候,把returnsize和returncolSize放到递归函数里面,这样导致了参数过多,借鉴其他人的写法,可以使用全局变量,减少函数参数;用迭代法时候,填value值时候出现错误,是想去找top的上一个值,然后相加,结果就是在遍历过程,top可能会减到-1,然后再加回来,导致数组越界。本题需要理解到递归过程,什么时候需要返回值,另外,这种遍历所有或者在所有节点中搜索的题目,应该都需要回溯。2 拆分前序遍历的左右区间时候,记得排除首位置元素,另外,起始位置也是改变了的。

2024-04-11 22:24:17 538

原创 代码随想录训练营-15day:二叉树4

2 就是c语言写法,需要传入top在里面,因此按照代码随想录的思路,先把value入栈,top在递归过程,会变化,导致元素缺失,因此需要把入栈操作放到判断左右子树的条件里面。主要是理解递归+回溯的思路,每一次递归之后,需要回退,把路径搜索完成,遍历一个完整的路径。之前使用的数字转字符函数和strcat,没使用成功;使用递归方式:首先需要知道高度是什么意思,怎么获取高度。如果高度差大于1了,那么回复高度就没有意义了。平衡二叉树的定义:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。

2024-04-11 09:52:01 345

原创 代码随想录-14day:二叉树3

递归法:这里需要理清楚最小深度的定义,特别这样的情况,如果左子树或者右子树为空时候,最小的深度不是止步在为空的节点处,还是得看右边或者左边还有子树没有,继续找。如果左子树为空,右子树不为空,说明最小深度是 1 + 右子树的深度。迭代法:可以使用层次遍历的思路解答:按照每一层遍历记录一个size ,每一层遍历结束后,把每一层遍历结果相加。可以使用迭代法和递归法,以递归法为例:还是以递归三要素为基准,进行解决。最大深度:根节点到最远叶子节点的最长路径上的节点数。使用层序遍历的方式依旧可以解决,参考上一篇博客。

2024-04-05 19:33:52 295

原创 代码随想录-13day:二叉树2

思路:每一层的节点指向下一个节点,因此需要找到当前节点和下一个节点,在处理过程,没有考虑queue size的情况,导致计算当前层的时候,可能访问到其他位置了,如果不限制size大于0情况下去找next node,可能找到的next node就是其他层的节点,也可能没有值。1 C语言写的函数,returnSIze和 returnColumnSize分别代表的意思,第一个returnSize代表的是有多少个数组,即有多少层,另一个是指一个层里面,有多少个size,即每一个元素的数量;

2024-04-05 11:23:32 905

原创 nvme协议学习总结

至于CQ的tail指针怎么处理呢,CQ命令里面DW3有个P字符,初始化时候设置成0,当CQ填入时候,把该值设置成1,这样当SSD发送CQ到host时候,host可以读取CQ任何信息,保留了上次P状态位置,即旧的tail位置,依次往下检查,得到现在的新的tail位置。首先是SQ head指针,SSD取指令对于host是不可见的,所以当SSD取完指令后,把head信息更新到了CQ head里面,host拿到CQ信息就知道了SQ的head;step4:SSD执行取回的CMD;未完待续...(后序继续补充)

2024-04-02 14:11:39 538

原创 代码随想录训练营-12day-二叉树1

此外,代码随想录提供思路,把迭代法统一风格,就是在入栈时候,加入节点同时,也加入一个空节点进行标记。前序和后序遍历可以统一成为一个code风格,前序调整顺序再翻转数组就是后序。注意点:a. 用数组来保存节点(指针);b. cur指针的位置变化。3 二叉树遍历方式:1)前序遍历;1 理解满二叉树,完全二叉树,平衡二叉树和二叉搜索树的概念;2 二叉树存储方式:其一是数组线性存储;其二是链表链式存储;5 二叉树的遍历方法:1) 递归方法;a.递归函数的参数和返回值;c.确定单层递归逻辑。

2024-04-02 14:04:30 281

原创 PCIE学习总结

上图所示,Host发送TLP到Switch,首先匹配switch的配置空间的所有bar地址,如果匹配上了,那么switch解析该TLP,如果不是发给switch的TLP包,查看mem base + mem limt,即查看下游的设备的地址范围,如果在范围内,那么是发给下游设备的,switch此时发挥路由功能,转发该TLP包;还有一种路由方式是隐式路由,即RC发送TLP后,如果是广播TLP(TLP类型在header上标记),那么就转发,如果是终结message,那么收到此TLP,就接收于此,不再转发。

2024-04-01 18:13:41 1236

原创 代码随想录-11day:栈和队列03

c语言没有代码随想录解答方法里面的队列,需要自己实现,显得比较麻烦,因此看到一个使用hashmap保存key times的方式,然后根据times排序,获取前k个频次最高的数字。方法2:学习了解答区里面的方法,用数组保存数字的index,借鉴队列的思路用于排序,找到队列头的值,来存储最大值,每次遍历后,能保证队列头值是最大值。方法1:暴力解法,整个数组遍历,然后每一次找k个元素窗口的最大值保存下来,但是会超时;

2024-04-01 11:40:57 128

原创 代码随想录训练营-10day:栈和队列2

利用栈的思想,把首个字符写入字符数组str,然后遍历字符s,从i = 1开始,如果遇到了相等的字符,那么str index减1,这里有一个点,就是index会减到-1,需要另外判断,重新开始赋值,从下一个字符开始,s的i也对应加1(注意不要越界),完成所有的字符遍历,然后字符串str最后加\0。3)如果长度为0 ,即没字符串,那么返回-1;3 判断是否是数字串,这里需要注意负数和减法的符号是一样的,因此,需要做判断,如果字符串len有且仅有1个,那么就是减法,否则是负数,那么就是数字,需要保存到数组。

2024-03-30 15:31:44 355

原创 代码随想录训练营-9day:栈和队列01

2 pop元素,栈的pop操作,是把最后的元素取出来,因此队列最后一个元素,需要遍历队列,把元素遍历完,最后一个就是pop元素。主要是队列结构体定义,以及栈和队列初始化,可以使用数组作为队列的元素(代表一个栈),使用2个栈来操作“入”和“出”的队列元素。队列使用c语言比较麻烦,所以主要是学习代码随想录上面的思路,栈的特点是先入后出,队列是先入先出;1 push元素,把元素先写入队列中,保存到队列最开头;

2024-03-29 20:08:00 191

原创 代码随想录训练营-8day:字符串2

首先需要获取next数组,根据代码随想录的讲解,len - next[size -1]就是重复子串的长度,因此,如果len %(len - next[size -1]),那么肯定能全部重复。本题主要是理解KMP算法,主要是最长公共前缀如何计算的,在循环遍历过程中,应该怎么遍历数据。具体讲解可以看代码随想录的讲解。1 next数组的获取。

2024-03-29 00:45:15 219

原创 代码随想录训练营-7day:字符串1

本题目需要解决字符串里面的空字符,利用双指针法,将字符串内部不符合的空字符处理。具体思路如下:slow =0,初始化index,当字符不为空,填入s[slow], slow++,这里需要注意,单词之间是有空格的,所以每遍历一个单词,需要加入空格。所以本题目主要判断翻转区间: if(len > k + i) ,区间落在了[k 2k],否则落在了[0 k].2 如果后面字符[0, k]区间,那么全部翻转,如果[k, 2k],那么重复上面1的操作。1 每隔2k个字符,前面k个字符翻转,后面k个字符不翻转;

2024-03-28 00:55:31 242

原创 代码随想录训练营-6day:哈希表2

一开始记录magazine内部字符出现的次数,利用hash set(c语言可用数组,26个字母),在ansomNote字符串中遍历,把遇到的字符次数剪掉,如果hash set内部元素有小于0的,说明magazine内部没有此字符,那么就组成不了ansomNote。这道题处理时候,自己编写的hash map函数遇到初始化的问题,没有插入数据,也能找到,导致随机值,后面就想的是,初始化value为0,遍历时候,把nums1 + nums2的值出现次数保存下来;在三数字之和的基础上,主要是对去重的理解。

2024-03-27 10:55:05 392

原创 代码随想录训练营-5day:哈希表

一‘、 哈希表理论基础根据代码随想录()的基础理论,需要清楚hash冲突,以及如何解决;另外C++里面的hash函数的数据结构以及特点;),需要注意的key value的数据类型。二、 242.有效的字母异位词其实这个题目就是找A数组内部元素是否和B数组内部元素重叠,这里就印证一个思想:一个元素是否出现在集合内,那么需要考虑hash法。

2024-03-25 17:44:28 858

原创 代码随想录-4day:24. 两两交换链表中的节点 、19.删除链表的倒数第N个节点 、链表相交 、142.环形链表II

删除倒数第N个节点,用双指针的办法,首先fast向前进N+1个节点,slow=0位置处,当fast==NULL时候,fast移动了LEN-N个,slow同步移动了LEN-N个,位置来到了倒数N位置的前一个,这样就能释放掉N个节点。链表相交的题目,一开始并没有理解到相交是什么意思,后面看了代码随想录和code,明白是指针相等,一旦存储节点的地址相等,说明相交,记住这一点,这个题目就清晰了。),主要是需要理解到环形链表相遇时候的公式推导,分为两个部分:1 两个节点相遇时候的节点位置;2 推导环形入口点的公式;

2024-03-24 18:37:30 405

原创 代码训练营-3day:移除链表元素、创建链表、翻转链表

还有就是使用递归,递归不太好理解,这样去思考的:找到递归的最后一层,往前推(迭代是正向推),递归的最后一层的处理,调用完成后,后面回复函数现场时候,所有的函数处理都是这样的操作。所以考虑时候,不使用虚拟头结点的话,就需要从头开始遍历,链表需要注意的是,头结点的value等于target,那么直接指向下一个节点,free掉当前的节点;然后,获取index位置节点value,需要考虑的是,index是否会超界,如果超了,return -1;然后,尾部插入,找到最末端节点,申请新节点,插入末端,并指向NULL;

2024-03-22 18:21:05 325

原创 代码训练营-2day:有序数组的平方、长度最小的子数组、螺旋矩阵

这道题目需要考虑细节特别多,最主要还是区间封闭选择,是左闭右开,还是左开右闭,当每一次遍历矩阵时候,需要遵循此原则,才能不重复和不遗漏。),使用滑动窗口方法,学习过程中,针对该方法,最核心的点是怎么处理头窗口的移动,例如本题目,每一次累加和大于目标值,就需要更新头窗口,并把每一次最小的长度记录下来。setp1:首先找到两端数,先平方,再比较,最大那个数,填入新的数组最后位置,如果是最右边指针指向的平方数大于左边的平方数,那么右指针减1,否则左指针加1;2 偏移量,每一次循环后,边界都有偏移;

2024-03-21 17:41:49 294

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除