自定义博客皮肤VIP专享

*博客头图:

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

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

博客底图:

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

栏目图:

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

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

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

原创 dpdk中udp包的接受与发送

内存池中的mbuf并不会直接存储数据包的信息,而是存储数据包的地址,大小等信息。struct rte_ipv4_hdr ipv4头结构体, 包含版本,ttl,next_proto_id,源地址,目标地址等字段。struct rte_ether_hdr 以太网帧头结构体,包含了三个成员变量,目的地址,源地址,IP类型。struct rte_udp_hdr udp头结构体,包含源端口,目的端口,数据长度以及校验和。rte_ipv4_udptcp_cksum(ip头地址,udp头地址)计算校验和的函数。

2024-12-17 13:53:58 554

原创 网卡驱动及dpdk的使用

dpdk实现对这些rte_mbuf的动态管理。实际并不是这样的,实际情况是把真正的数据存放到内存中的某个特定区域,然后把该区域的地址存放到rte_mbuf中,因此需要用户构建一个结构体指针数组存放rte_mbuf中的地址。实际数据包是一块连续的内存,分别存放了以太网帧头,ip头,tcp/udp头,可以通过rte_mbuf里存放的实际数据地址和地址偏移量取得不同头的信息,并读取数据。可以简单的理解为,把网卡的接收队列里的数据包,拷贝到内存池中的rte_mbuf中,然后从这些rte_mbuf中提取数据。

2024-12-12 20:15:04 731

原创 协程及调度器的实现

不同的IO设备实现异步,关键在于当某个IO设备无法立刻获取数据或者返回时,立即通过协程的方式,跳转回协程调度器,因此需要通过钩子函数对原本的内核函数进行修改。钩子是一种机制,通过该机制,可以把原本的系统函数进行重写。是,把本来epoll通过同步判断事件的方式通过异步实现了。:webserver、kv存储等等 --》用组件实现一个。第一部分:IO管理的改写 与 协程的定义。ntyco--》用网络框架实现一个。可以通过结构体来创建一个协程。通过结构体创建一个调度器。第二部分:调度器的实现。

2024-12-11 10:58:50 149

原创 协程设计原理与实现

协程的核心就是,以同步的方式,实现异步的性能。以上面的例子讲解,就是用不同的函数实现不同的步骤,这样在编程看起来是同步的(就是所谓的以同步的方式),然后不同函数在实现步骤的时候,会设定一个类似于原语的操作,如果这个步骤无法立刻完成,就跳转到下一个事情中去,直到满足条件之后,再回来继续完成该事件(这个原语即是实现了异步的性能)。

2024-12-09 23:08:06 398

原创 基于事件驱动的websocket简单实现

WebSocket 是一种网络通信协议,旨在为客户端和服务器之间提供全双工、实时的通信通道。它是在 HTML5 规范中引入的,可以让浏览器与服务器进行持久化连接,以便实现低延迟的数据交换。全双工通信:客户端和服务器可以同时发送和接收消息,而不必等待对方完成操作。轻量级:相较于传统的 HTTP 协议,WebSocket 头部信息更小,这减少了网络开销。持久连接:一旦建立连接,双方可以一直保持这个连接,直到主动关闭。这样避免了频繁建立和关闭连接带来的性能损耗。实时性。

2024-12-08 21:00:07 719

原创 网络原理 网络协议栈

在之前的学习过程中,由于对这些底层原理不太熟悉,所以在敲代码的基础上还花了大量的时间了解这些偏向下层的内容,导致学习进度缓慢。不过再看今天的内容,就非常容易理解了。基本和之前自己的理解差不多,哈哈哈,说明之前自己的理解是正确的,不枉我花了这么多时间查、补相关的知识。所以以上三次握手,使得客户端和服务端都知道了对方同时具有了发送和接收的能力,可靠连接可以建立。unix有不同的衍生版本,针对不同的版本,通过Posix定义了一套标准的操作系统接口API,使得不同的开发版本可以使用相同的API调用,具有可移植性。

2024-12-06 23:16:29 400

原创 网络编程第四课 http与websocket

但是在实际开发过程中,往往需要将这两个写入的事件分开,即服务器需要连着进行两次写操作,第一次写完成后,在下一轮监听之前,还是监听其epollout状态,所以上一版代码需要改进。如果是边缘触发状态,即使进入了下一轮,内核不会因为缓冲区有数据而作为事件驱动,所以不会调用回调函数读取缓冲区的数据,只有当再一次客户端发送数据时,此时操作系统内核才会把该事件作为驱动,去调用回调函数,此时虽然客户端发送了两次数据,但是服务器才仅仅把第一次的第11个字符到第20个字符读取出来。第二组更倾向于高层的读写,较为方便。

2024-12-05 22:25:03 1285

原创 网络编程第三课-事件驱动

对于io多路复用而言,操作系统内核只是提供了管理不同io设备(即文件描述符)的方法,其实我们最终要做的并不是管理这些io设备,而是根据io设备不同的状态,提供不同的方案。对于一个tcp连接,是通过五元组(源地址,目标地址,源端口,目标端口,协议)固定的,其中源地址和目标地址是无法改变的,源端口是1024-65535是系统固定的,只能修改目标端口。使用event_register来模拟创建对象的功能,即调用了该函数,就在上述数组中加入一个新的数据表示新对象,并且根据对象的不同实现不同的回调函数。

2024-12-03 13:15:20 571

原创 网络编程第二课

io多路复用是面试中常被问到的,之前没有接触也只是笼统的被八股,至于具体内容是什么,原理怎么样并不了解,所以深入问的话是容易露馅的。这次的学习,对io复用有了较深的理解,起码不会像之前那样纯背八股那样停留表面了,起码在操作系统、网络这两个层面有了更进一步的认知。同时不得不感叹,终于有一种把之前学习到的知识串联起来的感觉。之前os是os,计网是计网,考试就是学习对应的知识点应付。这一节通过具体的代码,相当于把这两个进行了连接,有了更立体的认识。

2024-12-02 22:53:39 635

原创 网络编程第一课

今天的课程涉及到了计算机网络里tcp相关的内容,操作系统中阻塞相关的内容。这些知识本身并不陌生,之前在课堂也都学习过,知识点都理解,只是上手代码,由于不是特别熟悉,还是有点吃力的,需要每一个函数都要去查,包括参数、返回值之类的,计划2小时学完,其实花了很久来上手,大概四小时左右,代码的实现看了两遍,结合gpt搞懂了。创建了socket后,需要将该socket和对应的地址进行绑定,通信的本质在于不同的地址之间信息的传送,socket提供了一个接口,现在还需要该接口和某个具体的网络地址进行绑定才可以实现通信。

2024-11-26 22:28:17 430

原创 leetcode刷题

终于到了n皇后问题,久仰大名,终于第一次解决了,其实也没有那么难。

2024-06-06 22:57:53 117 1

原创 leetcode刷题

其中计算雨水面积要横向计算,不能只看某一个竖列(我就卡在了这一步,因此没有做出来)。和上一题相反,上一题是求凹槽面积,这一题是求凸出来的面积。只是使用了单调栈的方法来做。

2024-06-04 14:33:32 361

原创 leetcode刷题

我的思路是停留在了最大值,不知道怎么处理了,其实不用管是不是最后一个,无脑遍历两遍就行了。其中计算雨水面积要横向计算,不能只看某一个竖列(我就卡在了这一步,因此没有做出来)。当然遍历有两种方式,一种是扩充数组;相当于把上一个题的数组又遍历了一遍。只是使用了单调栈的方法来做。

2024-06-03 23:29:16 166

原创 leetcode刷题

单调栈用来记录连续变化的数据,按照某一个顺序来记录。

2024-06-03 21:13:19 289

原创 leetcode刷题

思想太妙了,用二维数组来表示。dp[i][j]表示i到j是否是回文串,这样就可以做递推公式了。

2024-05-31 18:28:43 224

原创 leetcode刷题

carl通过vector<bool> used 的方式做哈希表,一样的。去重的方法不能使用之前的方法了,因为不能改变原始顺序。所以引用undered_set来做去重操作。通过unordered_set的方式来去重。剪枝还是不够熟练,得再多想下。

2024-05-31 12:44:43 337

原创 leetcode刷题

本质就是求最长公共子序列,然后用两个字串的大小分别减去最长的子序列大小再相加,就是最终结果。以下代码初始化有一些问题。两个字符串的删除操作。

2024-05-30 23:04:39 216

原创 leetcode刷题

dp[i][j]的含义是不同子串到i与主串到j有多少种相同的方案。和之前的序列问题类似,代码基本不变。

2024-05-30 11:18:46 400

原创 leetcode刷题

还是要搞清楚,dp[]的含义,要不然想了很久,一开始方向就搞错,一开始以为dp[i]代表的就是从0到i的最大和,而carl的思路是以i为结尾的最大子序列和。上一题由于需要连续,所以只能从左上角的位置+1,来更新。本题不连续,只要包含就行,所以可以根据左上角,上方,左方联合推出来。把题目搞清楚了,发现和上一个题一模一样,其实就是在求最长公共子序列。本地与上一题类似,不同点在于dp[i][j]表示的内容不一样。首先要搞清楚什么是子序列,不一定是连续的。之前通过贪心的方法做,本次使用dp。

2024-05-28 20:36:32 283

原创 leetcode刷题

只是在递推的时候,需要使用两层for循环。因为每次求dp[i],都需要和前面每一个dp的状态进行对比。dp[i] 代表从第0个数据到第i个数据,最大的子序列。比上一个题目要简单些,因为是连续,所以只需要一层循环。

2024-05-27 22:58:05 284

原创 leetcode刷题

在不持有股票的情况下,又细化分了两种情况,一个是前一天就已经不持有了,一个是当天才卖出。这样做的目的是可以区分出冷冻期。因为卖出之后,才会有冷冻期。只需要在卖出的时候,多减去手续费就可以了。最后还多了一种状况就是冷冻期。

2024-05-27 15:04:16 164

原创 leetcode刷题

(本来我自己的想法是设置数组的长度是3,代表不持有,第一次持有,第二次持有,还有尝试不知道对不对)其实类似,只是dp数组的状态又多了几种情况而已。和上一题差不多,进一步扩充了数组的维度而已。买卖股票的最佳时机III。买卖股票的最佳时机IV。

2024-05-26 22:02:12 567

原创 leecode刷题

持有股票有两种可能,一是前一天已经持有了dp[i-1][0],二是前一天没有持有,今天购入股票(即当天买的,由于可以买多次,并非第一次买,所以手里的钱不一定是0,而是dp[i -1][1], 所以最大价值就是dp[i -1][1] - prices[i]), 选最大值就可以。不持有股票也有两种可能,一是前一天就没有持股票dp[i - 1][1], 二是前一天持股票了,今天卖了(即dp[i-1][0]+prices[i])dp[i][1]代表第i天不持有股票的情况下,最大的收益。买卖股票的最佳时机I。

2024-05-26 15:16:59 324

原创 leetcode刷题

如果要偷第i家,那么最大价值是d[i - 2] + nums[i]第二种情况是不考虑第一家,取最大值。最后比较两个最大值,选最大的。把线性数组连成了一个环,所以只需要分情况讨论就可以。dp[i] 代表偷到第i家,能偷到的最大价值。第i家的最大价值和前一家、前两家有关系。第一种情况是不考虑最后一家,取最大值。如果不偷,那么就是d[i - 1]

2024-05-25 19:00:16 456

原创 leetcode刷题

多重背包和01背包的区别在于:对于每个不同的物品,有一个数量限制,既不是只能用一次,又不是可以无限使用。注意是需要词语的顺序,因此这是一个排列问题,所以外层循环是背包,内层循环是物品。解法比较简单,就是把每个物品拆分成单个物品,然后就转换为了01背包问题。(这个递推还是挺抽象的,不太好理解)

2024-05-25 16:10:54 366

原创 leetcode刷题

不只是只能爬1、2阶楼梯了,而是一次可以爬最大m阶楼梯。需要注意初始化,以及返回条件。完全背包,思路还是一样的。

2024-05-24 15:11:03 250

原创 leetcode刷题

完全背包的状态是由上一个状态和左边的状态推出来的,因此先遍历背包,还是先遍历物品都可以。

2024-05-24 10:13:49 366

原创 leetcode刷题

递推公式就是dp[j] += dp[j - nums[i]];更新数组时,dp[j] 指的是如果不放这个新的数,原本有多少种方案,再加上dp[j - nums[i]]代表如果把这个数放进去,有多少种新的方案,总和就是更新后的数组。也是把数组分成两堆,一堆是负数,一堆是正数。本质上是把石头分成两堆,使得两堆石头的总重量最相近。和之前的题类似,只是背包换成了二维的。dp[j] 代表容量为j的背包,有多少种存放方案。初始化,dp[0] 初始化为1,代表只有一种情况。接下来就简单了,一样的套路。

2024-05-23 15:23:13 139

原创 leetcode刷题

如果背包大于第i个物品的重量,能放下,则可以选择替换之前的物品或者不替换(替换的标准在于最后的价值是否最大,这样就保证了每次更新,当前容量的背包都是最大的。d[i][j] 表示 从0--i个物品中进行选择,在容量为j的背包中能取到的最大值。如果背包容量小于第i个物品的重量,放不下,不用更新。01背包基础原理搞懂了,但是应用太难套了。只需将第一行和第一列进行初始化就可以。可以先遍历背包,也可以先遍历物品。一维-----动态数组。

2024-05-16 15:40:54 408

原创 leetcode刷题

递推: j * (i - j) j * dp[i - j] he。dp[i] 表示 个数为 i 的树中,有多少不同的二叉搜索树。dp[i]的含义:把i拆分后,可以得到的最大乘积。递推:分别取第i个作为根节点,i左右两边的数量乘积。

2024-05-15 21:41:25 172

原创 leetcode刷题

不同路径更新每一个格子,格子的数值就是到达该格子的方法数,迭代策略就是上面的数值+左面的数值。int uniquePaths(int m, int n) { vector<vector<int>> result (m, vector<int>(n)); result[0][0] = 1; for(int row = 0; row < m; row++){ for(int col = 0

2024-05-15 11:42:22 272

原创 leetcode刷题

使用模板,之前的模板是只收集叶子节点,该题目就是收集这个路程中所有的节点。是之前组合II去重,和子集的结合体。

2024-05-15 11:39:58 415

原创 leetcode刷题

模板不变,只是把返回条件进一步改变了。本来是按照path大小返回,由于这个可以重复并且不限大小,因此需要按照总和这个标准来返回。如果总和大于target,则返回,如果相等,添加到result里再返回。(复杂,需要区分同一树枝使用过和同一树层使用过的区别)used 数组是巧妙的点,用来记录访问过的数据。按顺序从大到小排列。

2024-05-13 22:15:08 224

原创 leetcode刷题

在返回的结构上加上一个判断就可以。一样的套路,只是写的太繁琐了。

2024-05-13 19:18:09 220

原创 leetcode刷题

虽然是暴力解法,但还是可以通过剪枝操作降低时间复杂度。比如该问题,如果后续剩余可以加入的元素比现有的少了,就不需要再遍历了。回溯其实和递归是相辅相成的,有递归就一定有回溯。只是有些题目用到的到,有些题目用不到。回溯其实也是暴力解法,只是有些题目只能暴力解决。回溯问题其实就是类似于n叉树的遍历。

2024-05-13 19:16:27 161 1

原创 leetcode刷题

确定i 和 dp[i] 的含义。debug时把结果打出来。

2024-05-13 15:16:46 119

原创 leetcode刷题

将有序数组转换为平衡二叉树。把二叉树转换为累加树。

2024-05-11 17:17:28 313

原创 leetcode刷题

单调递增的数字暴力方法bool mode(int n){ int pre = 9; while(n){ if (n % 10 <= pre){ pre = n % 10; n = n / 10; } else{ return false; } }

2024-05-11 16:41:43 108

原创 leetcode刷题

二叉搜索树的最近公共祖先。我真垃圾啊,写这么多if。二叉搜索树中的插入操作。

2024-05-10 21:55:08 274

原创 leetcode刷题

二叉搜索树的最小绝对值。二叉树的最近公共祖先。

2024-05-10 20:33:55 225

空空如也

空空如也

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

TA关注的人

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