首页 > 其他分享 >我是如何学习软件工程的

我是如何学习软件工程的

时间:2023-05-24 23:32:33浏览次数:35  
标签:DMA NIC 学习 如何 软件工程 内核 数据包 CPU 内存

image.png

软件工程是一个庞大且不断演化的领域,涉及许多创新。虽然如此,大多数技术——如果不是全部——在软件工程中往往最终汇聚为几个基本原则。工程师更好地学习软件工程的方法是学习软件工程的基础知识,而不是那些不断变化的框架、语言或平台

即使学习基础知识也需要时间和努力。人们经常问我如何学习软件工程,起初我无法客观地回答这个问题。但最近我开始观察自己的学习过程,我对这个过程有了更清晰的理解。

事实上,我从不强迫自己学习任何东西。如果你一直关注我的工作,你会注意到我很少谈论新的潮流技术,相反,我经常谈论那些已经过时、没有人再讨论的软件工程主题。这不是因为新的东西不好,而是因为我觉得还有更多我不了解的东西,我宁愿追求那些东西。

在这篇文章中,我将带你走过我最近的学习经历,因为这些经历还新鲜在我的脑海中。

Q&Q — 问题和问题

对我来说,学习始于问题。我提出真正的问题,让自己进入探索的道路,在这个过程中,我会遇到一个又一个的障碍,逐个克服。每个问题都会引发另一个问题,直到我达到一个能够统一一切的基础知识。就像一个递归函数达到了其基本条件。

引发问题的原因各不相同,可能是一个学生,或者是工作中的一个随机 bug。不想陷入哲学讨论,但我发现承认自己不知道某个东西对我在学习过程中帮助很大。当一个学生问一个老师不知道的问题时,往往会让老师感到不安。我一直在努力克服这一点,真诚地探索问题,而不是向学生展示我有多么了解。

我还有很多不知道的东西。

接下来的文章将涉及一些技术细节。让我们深入了解。

我所不了解的内容

当后端应用程序监听一个地址和端口时,它可以开始接收来自客户端的请求。请求(无论是 HTTP 还是其他协议)以数据包的形式传输。这就是应用程序如何接收网络数据包的方式。

为简单起见,我在这里省略了用于连接创建/接受的其他队列。这假设连接已经创建好。

以下是流程:

  1. 内核在内核内存中为应用程序创建接收缓冲区。
  2. 内核将传入的网络数据包放入接收队列。
  3. 应用程序从接收缓冲区读取数据包,并将其复制到自己的进程内存中。
  4. 应用程序处理数据(解密、解析协议、触发事件)。

然而,我发现自己对以下两个问题还不太了解:

  1. 网络接口控制器(NIC)是如何将数据传输到内核内存的?
  2. 为什么数据必须先经过内核而不是直接进入进程内存?

接下来的段落中,我将尝试回答这两个问题。

Q1 — NIC 如何将数据包传输到内核

为了回答第一个问题,我必须了解 CPU 的工作原理,在这个过程中我发现了很多东西,这里与我们相关的是中断(interrupt)的概念。为了从任何外部设备(鼠标、键盘、硬盘或 NIC)读取数据,CPU 必须被中断并告知在哪里读取或写入数据。

因此,我将这个知识应用到我的问题上,得出了以下结论:

当 NIC 接收到电信号、光信号或无线电信号(无论是以太网、光纤还是 WIFI/5G),并将其转换为二进制数据存储在其本地缓冲区中时,它会向 CPU 发送中断请求,要求 CPU 停止当前工作并将数据传输到主存中。

CPU 从 NIC 中读取数据,并将其放入缓存行中,然后将缓存行刷新到内存中。但是数据确切地放在内存的哪个位置呢?这就是 NIC 驱动程序(在内核空间运行的软件)告诉 CPU 地址位置的地方。CPU 最终将数据刷新到提供的内存地址中。这个循环一直重复,直到 NIC 中没有数据。然后内核接管处理。

这里花费了很多时间来试图回答更具体的问题,比如 CPU 如何将缓存行刷新到内存?如果其他核心也在读取相同的内存位置会发生什么?但是我暂时跳过这些问题。

这一切对我来说都是有道理的,只有一件事让我感到困惑,这听起来非常冗长。如果我在软件工程中了解了什么,那就是我们尽量避免过度冗长。

虽然中断在小型 I/O(如鼠标移动或键盘按键)中有效,但对于大数据传输,如网络传输、磁盘读取或写入,对 CPU 来说非常耗时。因此,我认为不能仅仅这样处理,肯定还有其他方式。将大量数据放入微小的 CPU 寄存器和缓存中并进行刷新将需要很长时间。于是我进行了更多的搜索,发现了 DMA。

原来这正是为什么发明了 DMA(直接内存访问)的原因。DMA 允许 NIC 直接访问主内存,以便设备可以自行读取和写入数据,从而使 CPU 解放出来。CPU 通过在 DMA 上设置目标内存地址以及应从哪个设备(即 NIC)读取数据来启动传输,所有这些都是根据设备驱动程序的指令。 在 NIC 开始将数据直接传输到内存之后,内核/驱动程序就可以在内存中正常处理一次数据。

问题2 — 为什么数据首先进入内核?

但实际上,为什么不直接将数据从 NIC 移动到进程内存呢?从 NIC 直接复制数据到内核,然后再从内核复制到应用程序,这样做的成本肯定是累积的。我发现设备驱动程序在内核中运行,而内核是与 NIC 进行通信的实体,所以数据包的存在于内核中。此外,内核(目前)还不知道将数据放在进程内存的哪个位置,而且它也不知道进程是否准备好读取数据。老实说,我不明白为什么不能通过重新设计 API 来实现这一点。我认为使用 io_uring 可能可以做到这一点,但我还没有探索过。

即使使用 DMA,每个数据包的传输对 DMA 控制器来说也是一种负担。因此,我发现 Intel 提出了一种称为 DMA 合并的想法,其中 NIC 在本地缓冲数据包,然后延迟接收数据包的 DMA 传输。这样可以最小化传输次数,以节省能源,但代价是增加延迟。

在这个探索过程中,我还学到了虚拟内存、转换后备缓冲区、NUMA 架构、上下文切换等等知识。

总结

我刚才所做的被称为“附带知识”。在学习的过程中,除了目标知识,还发现了其他事物。

也许你会说,真的吗?你不知道中断是什么,甚至不知道 DMA 是什么吗?事实上,我确实听说过这些概念,但从来没有在能够真正理解或引起我的兴趣的上下文中接触过它们。

我不知道该如何形容,但是自己发现事物与别人把事物放在盘子里递给你是不同的感觉。

如果你喜欢我的文章,点赞,关注,转发!

标签:DMA,NIC,学习,如何,软件工程,内核,数据包,CPU,内存
From: https://blog.51cto.com/slagga/6343448

相关文章

  • 如何保证用户重试操作的幂等性
    服务不稳定是一类常态,面对此类场景恰当的应对策略应该是什么?退一步说,即使我们能够确保第一方服务的稳定性,我们又应该如何面对网络延迟以及掌控以外的不确定性?这都是本篇文章会谈到的内容本文是团队内部分享的文字版,敏感信息已经抹去或者重写。我们通过三个实际的线上问题来看看在......
  • 「学习笔记」略谈点分治
    点分治适合处理大规模的树上路径信息问题。引入给定一棵\(n\)个点树和一个整数\(k\),求树上两点间的距离小于等于\(k\)的点对有多少。对于这个题,如果我们进行\(O_{n^3}\)搜索,那只要\(n\)一大,铁定超时。所以,我们要用一个更优秀的解法,这就是我们的点分治。淀粉质可......
  • *【学习笔记】(9) 分块
    分块思想引用一下oi-wiki的话:分块的基本思想是:通过对原数据的适当划分,并在划分后的每一个块上预处理部分信息,从而较一般的暴力算法取得更优的时间复杂度。数列/序列分块引入#6280.数列分块入门4给定一长度为$n$的数列,有\(n\)次操作。操作分为两种:区间加,查询区间......
  • 【学习笔记】(15) Kruskal 重构树
    前置知识:kruskal求最小生成树,倍增。1.算法简介以下所有讨论基于最小生成树。在Kruskal求最小生成树的过程:将所有边按照边权排序,若当前边\((u,v)\)两端不连通,则往生成树边集\(E\)中加入\((u,v)\)并连接\(u,v\)。使用并查集维护连通性。如果能用某种结构描述每条边......
  • GitlabCI学习笔记之三:GitLabRunner pipeline语法之tags allow_faillure when retry ti
    1.tags用于从允许运行该项目的所有Runner列表中选择特定的Runner,在Runner注册期间,您可以指定Runner的标签。tags可让您使用指定了标签的runner来运行作业,此runner具有ruby和postgres标签。示例给定带有osx标签的OSXRunner和带有windows标签的WindowsRunner,以下作业将在......
  • java基于springboot+vue的书籍学习平台管理系统,学期学习论坛管理系统,附源码+数据库+lw
    1、项目介绍困扰管理层的许多问题当中,书籍学习将会是不敢忽视的一块。但是管理好书籍学习又面临很多麻烦需要解决,在工作琐碎,记录繁多的情况下将书籍学习的当前情况反应给相关部门决策,等等。在此情况下开发一款书籍学习平台,于是乎变得非常合乎时宜。经过网上调查和搜集数据,......
  • 如何使用Map处理Dom节点
    本文浅析一下为什么Map(和WeakMap)在处理大量DOM节点时特别有用。我们在JavaScript中使用了很多普通的、古老的对象来存储键/值数据,它们处理的非常出色:constperson={firstName:'Alex',lastName:'MacArthur',isACommunist:false};但是,当你开始处理较大的......
  • redis学习4集群--黑马
    主从复制将master中的数据有效的复制到slave中master写数据执行写操作时,将出现变化的数据自动同步到slave读数据(可忽略)slave读数据写数据(禁止)主从连接(slave连接master)方式一:客户端发送命令slaveof方式二:启动服务器参数redis-server-slaveof方式三:服务器配......
  • C语言学习记录04
    逻辑操作符:条件操作符||三目操作符:例://i>j成立,为真,所以i为真,j为假,所以结果为i。逗号表达式:下表引用操作符:函数调用操作符:常见关键字:命名规则:......
  • 2023.5.24——软件工程站立会议(阶段二)
    站立会议内容:1.整个项目预期的任务量:目前已经花的时间:剩余的时间:2.任务看板照片: 3.团队照片: 4.产品状态:最新做好的功能:正在完成中5.燃尽图:......