我是如何精通软件工程的
软件工程是一个庞大且不断演化的领域,涉及许多创新。虽然如此,大多数技术 —— 如果不是全部 —— 在软件工程中往往最终汇聚为几个基本原则。工程师更好地掌握软件工程的方法是熟悉软件工程的基础知识,而不是那些不断变化的框架、语言或平台。
即使熟悉基础知识也需要时间和努力。人们经常问我如何掌握软件工程,起初我无法客观地回答这个问题。但最近我开始观察自己的熟悉过程,我对这个过程有了更清晰的理解。
事实上,我从不强迫自己掌握任何东西。如果你一直关注我的工作,你会注意到我很少谈论新的潮流技术,相反,我经常谈论那些已经过时、没有人再讨论的软件工程主题。这不是因为新的东西不好,而是因为我觉得还有更多我不了解的东西,我宁愿追求那些东西。
在这篇文章中,我将带你走过我最近的开发经历,因为这些经历还新鲜在我的脑海中。
Q&Q — 问题和问题
对我来说,熟悉始于问题。我提出真正的问题,让自己进入探索的道路,在这个过程中,我会遇到一个又一个的障碍,逐个克服。每个问题都会引发另一个问题,直到我达到一个能够统一一切的基础知识。就像一个递归函数达到了其基本条件。
引发问题的原因各不相同,可能是一个学生,或者是工作中的一个随机 bug。不想陷入哲学讨论,但我发现承认自己不知道某个东西对我在熟悉过程中帮助很大。当一个学生问一个老师不知道的问题时,往往会让老师感到不安。我一直在努力克服这一点,真诚地探索问题,而不是向学生展示我有多么了解。
我还有很多不知道的东西。
接下来的文章将涉及一些技术细节。让我们深入了解。
我所不了解的内容
当后端应用程序监听一个地址和端口时,它可以开始接收来自客户端的请求。请求(无论是 HTTP 还是其他协议)以数据包的形式传输。这就是应用程序如何接收网络数据包的方式。
为简单起见,我在这里省略了用于连接创建 / 接受的其他队列。这假设连接已经创建好。
以下是流程:
- 内核在内核内存中为应用程序创建接收缓冲区。
- 内核将传入的网络数据包放入接收队列。
- 应用程序从接收缓冲区读取数据包,并将其复制到自己的进程内存中。
- 应用程序处理数据(解密、解析协议、触发事件)。
然而,我发现自己对以下两个问题还不太了解:
- 网络接口控制器(NIC)是如何将数据传输到内核内存的?
- 为什么数据必须先经过内核而不是直接进入进程内存?
接下来的段落中,我将尝试回答这两个问题。
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 是什么吗?事实上,我确实听说过这些概念,但从来没有在能够真正理解或引起我的兴趣的上下文中接触过它们。
我不知道该如何形容,但是自己发现事物与别人把事物放在盘子里递给你是不同的感觉。
如果你喜欢我的文章,点赞,关注,转发!
相关文章:
我是如何精通软件工程的
软件工程是一个庞大且不断演化的领域,涉及许多创新。虽然如此,大多数技术 —— 如果不是全部 —— 在软件工程中往往最终汇聚为几个基本原则。工程师更好地掌握软件工程的方法是熟悉软件工程的基础知识,而不是那些不断变化的框架、语言或平台…...
如何使用 Python Nornir 实现基于 CLI 的网络自动化?
在现代网络环境中,网络自动化已成为管理和配置网络设备的重要工具。Python Nornir 是一个强大的自动化框架,它提供了一个简单而灵活的方式来执行网络自动化任务。本文将详细介绍如何使用 Python Nornir 实现基于 CLI 的网络自动化。 1. Python Nornir 概…...
并发编程的三大特性之有序性
有序性的概念 Java文件在被cpu执行前会进行编译成cpu可以执行的指令,为了提高cpu的执行效率会对其中的一些语句进行重排序。Java指令最终是乱序执行的目的是为了提高cpu的执行效率,发挥cpu的性能 单例模式由于指令重排可能会出现上述的问题࿰…...
LeetCode:相交链表(java)
相交链表 题目描述指针法解题 #LeetCode 160题:相交链表,原题链接 原题链接。相交链表–可以打开测试 题目描述 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返…...
利用PHP导出MySQL数据表结构和SQL文件
目录 一、获取数据库所有的数据表 方法一:TP5 方法二:原生PHP 二、导出指定数据表的数据结构 三、 导出SQL文件 四、生成SQL语句 五、完整代码 前端 后端 语言:PHP 数据库:MySQL 功能:分为四部分,① 查出数…...
接口测试框架分析
框架大体上已经写完了,不过说实话好多代码让我自己写我也写不出来,那该怎么办呢?很简单,把现在已经写好的代码保存起来,等用的时候拿出来复制粘贴就好了,如果你是大神,自己会写,那就…...
spring boot日志
日志介绍日志的使用日志级别日志持久化更简单的输入日志lombok的运行原理 日志介绍 日志的作用: 1:发现问题; 2:定位问题; 3:记录用户的行为:看哪些是方法用户;还能拿到用户的ip&am…...
【Vue2.0源码学习】虚拟DOM篇-Vue中的DOM-更新子节点
文章目录 1. 前言2. 更新子节点3. 创建子节点4. 删除子节点5. 更新子节点6. 移动子节点7. 回到源码8. 总结 1. 前言 在上一篇文章中,我们了解了Vue中的patch过程,即DOM-Diff算法。并且知道了在patch过程中基本会干三件事,分别是:…...
rsync
配置rsync源服务器: #建立/etc/rsyncd.conf 配置文件 vim /etc/rsyncd.conf #添加以下配置项 uid root gid root use chroot yes #禁锢在源目录 address 192.168.80.10 …...
javascript:void(0)
javascript:void(0) 是一个 JavaScript 中常见的使用方式,它通常用于在 HTML 中作为链接的 href 属性值。 在 HTML 中,链接(<a> 元素)的 href 属性指定了链接目标的 URL。当用户点击该链接时,浏览器会加载该 UR…...
ThingsBoard教程(五三):规则节点解析 Kafka Node, MQTT Node
Kafka Node Since TB Version 2.0 Kafka节点将消息发送到Kafka代理。它可以接收任何类型的消息。该节点会通过Kafka生产者将记录发送到Kafka服务器。 配置 主题模式 - 可以是静态字符串,也可以是使用消息元数据属性解析的模式。例如${deviceType}引导服务器 - 用逗号分隔的…...
基于PHP实现的网上留言管理系统的设计
摘 要 随着互联网技术的迅猛发展,网络已经充斥到我们生活的方方面面,网上留言系统已经成为各种网站不可或缺的一个组成部分。一个设计美观、功能完善的网上留言系统是网站吸引网民的一个重要因素。同时,它还为网络用户提供了一个多人参与的信息交流平台。基于PHP实现的网上…...
【9 Vue全家桶 – Vuex状态管理】
1 什么是状态管理 其实是数据管理但是为了更好的指出是由于状态的变化导致数据的变化(响应式数据),我们称之为状态管理. 2 Vuex的状态管理 组件只能直接读取state,而不能直接修改state,必须通过mutation才能修改.(pinia可以直接读取和修改state) 3 Vuex的安装 npm install …...
Oracle游标学习
declare-- 1 声明一个游标cursor emp_cursor isselect ID,XM,KSNO from ZGXX where rownum < 10; v_stu_info emp_cursor%rowtype; -- %rowtype: 声明 emp表的所有字段 begin-- 2 开启游标open emp_cursor;-- 3 获取数据(一次获取一行)循环获取 去掉…...
几种常用的正则表达式
1、身份证号正则表达式 身份证号是一串18位数字和字母的组合,其中最后一位可能为数字或者字母 X。以下是可以用于匹配身份证号的正则表达式: /^[1-9]\d{5}(19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[Xx\d]$/上述正则表达式中包含…...
华为OD机试真题 Java 实现【快速开租建站】【2023Q1 200分】,附详细解题思路
一、题目描述 当前IT部门支撑了子公司颗粒化业务,该部门需要实现为子公司快速开租建站的能力,建站是指在一个全新的环境部署一套IT服务。 每个站点开站会由一系列部署任务项构成,每个任务项部署完成时间都是固定和相等的,设为1。…...
照片中对象识别模型YOLOv3在iOS项目中的浅析与使用
本文所指的YOLOv3模型为苹果开发者官网提供的图形识别对象的CoreML模型,可识别80种对象,并给出识别的对象在图形中的位置和大小信息。 我们可以直接在官网下载该模型: 机器学习 - 模型 - Apple Developer 然后直接将模型拖入工程中&#x…...
Caffeine 本地高速缓存工具类
目录 Caffeine工具类方式 SpringBoot 整合 Caffeine 缓存 (SpringCache模式) 驱逐策略 开发使用 Caffeine是一种高性能的缓存库,是基于Java 8的最佳(最优)缓存框架,性能各方面优于guava。 Caffeine工具…...
加密解密软件VMProtect教程(八)许可制度之序列号生成器
VMProtect是新一代软件保护实用程序。VMProtect支持德尔菲、Borland C Builder、Visual C/C、Visual Basic(本机)、Virtual Pascal和XCode编译器。 同时,VMProtect有一个内置的反汇编程序,可以与Windows和Mac OS X可执行文件一起…...
单源最短路的建图
1.热浪 信息学奥赛一本通(C版)在线评测系统 (ssoier.cn)http://ybt.ssoier.cn:8088/problem_show.php?pid1379 很裸的单源最短路问题,n2500,可以用dijksta或者spfa都能过,下面展示spfa的做法 #include<bits/stdc.h> usi…...
Java 语言特性(面试系列2)
一、SQL 基础 1. 复杂查询 (1)连接查询(JOIN) 内连接(INNER JOIN):返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...
TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?
在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...
