自己动手实现一个malloc内存分配器 | 30图

C语言与CPP编程 2021-01-12 00:00

对内存分配器透彻理解是编程高手的标志之一

如果你不能理解malloc之类内存分配器实现原理的话,那你可能写不出高性能程序,写不出高性能程序就很难参与核心项目,参与不了核心项目那么很难升职加薪,很难升级加薪就无法走向人生巅峰,没想到内存分配竟如此关键,为了走上人生巅峰你也要势必读完本文

现在我们知道了,对内存分配器透彻的理解是写出高性能程序的关键所在,那么我们该怎样透彻理解内存分配器呢?

还有什么能比你自己动手实现一个理解的更透彻吗

接下来,我们就自己实现一个malloc内存分配器。读完本文后内存分配对你将不再是一个神秘的黑盒。
在讲解实现原理之前,我们需要回答一个基本问题,那就是我们为什么要发明内存分配器这种东西。

内存申请与释放

程序员经常使用的内存申请方式被称为动态内存分配,Dynamic Memory Allocation。我们为什么需要动态的去进行内存分配与释放呢?
答案很简单,因为我们不能提前知道程序到底需要使用多少内存。那我们什么时候才能知道呢?答案是只有当程序真的运行起来后我们才知道。

这就是为什么程序员需要动态的去申请内存的原因,如果能提前知道我们的程序到底需要多少内存,那么直接知道告诉编译器就好了,这样也不必发明malloc等内存分配器了。
知道了为什么要发明内存分配器的原因后,接下来我们着手实现一个。

程序员应如何看待内存

实际上,现代程序员是很幸福的,程序员很少去关心内存分配的问题。作为程序员,可以简单的认为我们的程序独占内存,注意,是独占哦

写程序时你从来没有关心过如果我们的程序占用过多内存会不会影响到其它程序,我们可以简单的认为每个程序(进程)独占4G内存(32位操作系统),即使我们的物理内存512M。不信你可以去试试,在即使只有512M大小的内存上你依然可以申请到2G内存来使用,可这是为什么呢?关于这个问题我们会在《深入理解操作系统》系列中详细阐述。
总之,程序员可以放心的认为我们的程序运行起来后在内存中是这样的:
作为程序员我们应该知道,内存动态申请和释放都发生在堆区,heap。
我们使用的malloc或者C++中的new申请内存时,就是从堆区这个区域中申请的
接下来我们就要自己管理堆区这个内存区域。
堆区这个区域实际上非常简单,真的是非常简单,你可以将其看做一大数组,就像这样:
从内存分配器的角度看,内存分配器根本不关心你是整数、浮点数、链表、二叉树等数据结构、还是对象、结构体等这些花哨的概念,在内存分配器眼里不过就是一个内存块,这些内存块中可以装入原生的字节序,申请者拿到该内存块后可以塑造成整数、浮点数、链表、二叉树等数据结构以及对象、结构体等,这是使用者的事情,和内存分配器无关。
我们要在这片内存上解决两个问题:
  • 实现一个malloc函数,也就是如果有人向我申请一块内存,我该怎样从堆区这片区域中找到一块返回给申请者。

  • 实现一个free函数,也就是当某一块内存使用完毕后,我该怎样还给堆区这片区域。

这是内存分配器要解决的两个最核心的问题,接下来我们先去停车场看看能找到什么启示。

从停车场到内存管理
实际上你可以把内存看做一条长长的停车场,我们申请内存就是要找到一块停车位,释放内存就是把车开走让出停车位。
只不过这个停车场比较特殊,我们不止可以停小汽车、也可以停占地面积很小的自行车以及占地面积很大的卡车,重点就是申请的内存是大小不一的,在这样的条件下你该怎样实现以下两个目标呢?
  • 快速找到停车位,在内存申请中,这涉及到以最大速度找到一块满足要求的空闲内存

  • 尽最大程度利用停车场,我们的停车场应该能停尽可能多的车,在内存申请中,这涉及到在给定条件下尽可能多的满足内存申请需求

现在,我们已经清楚的理解任务了,那么该怎么实现呢?

任务拆分
现在我们已经明确要实现什么以及衡量其好坏的标准,接下来我们就要去设计实现细节了,让我们把任务拆分一下,怎么拆分呢?
我们可以自己想一下从内存的申请到释放需要哪些细节。
申请内存时,我们需要在内存中找到一块大小合适的空闲内存分配出去,那么我们怎么知道有哪些内存块是空闲的呢
因此,第一个实现细节出现了,我们需要把内存块用某种方式组织起来,这样我们才能追踪到每一块内存的分配状态
现在空闲内存块组织好了,那么一次内存申请可能有很多空闲内存块满足要求,那么我们该选择哪一个空闲内存块分配给用户呢?
因此,第二个实现细节出现了,我们该选择什么样的空闲内存块给到用户
接下来我们找到了一块大小合适的内存块,假设用户需要16个字节,而我们找到的这块空闲内存块大小为32字节,那么将16字节分配给用户后还剩下16字节,这剩下的内存该怎么处理呢?
因此,第三个实现细节出现了,分配出去内存后,空闲内存块剩余的空间该怎么处理
最后,分配给用户的内存使用完毕,这是第四个细节出现了,我们该怎么处理用户还给我们的内存呢
以上四个问题是任何一个内存分配器必须要回答的,接下来我们就一一解决这些问题,解决完这些问题后一个崭新的内存分配器就诞生啦。

管理空闲内存块
空闲内存块的本质是需要某种办法来来区分哪些是空闲内存哪些是已经分配出去的内存。
有的同学可能会说,这还不简单吗,用一个链表之类的结构记录下每个空闲内存块的开始和结尾不就可以了,这句话也对也不对。

说不对,是因为如果要申请内存来创建这个链表那么这就是不对的,原因很简单,因为创建链表不可避免的要申请内存,申请内存就需要通过内存分配器,可是你要实现的就是一个内存分配器,你没有办法向一个还没有实现的内存分配器申请内存
说对也对,我们确实需要一个类似链表这样的结构来维护空闲内存块,但这个链表并不是我们常见的那种。
因为我们无法将空闲内存块的信息保存在其它地方,那么没有办法,我们只能将维护内存块的分配信息保存在内存块本身中,这也是大多数内存分配器的实现方法。
那么,为了维护内存块分配状态,我们需要知道哪些信息呢?很简单:
  • 一个标记,用来标识该内存块是否空闲
  • 一个数字,用来记录该内存块的大小
为了简单起见,我们的内存分配器不对内存对齐有要求,同时一次内存申请允许的最大内存块为2G,注意,这些假设是为了方便讲解内存分配器的实现而屏蔽一些细节,我们常用的malloc等不会有这样的限制
因为我们的内存块大小上限为2G,因此我们可以使用31个比特位来记录块大小,剩下的一个比特位用来标识该内存块是空闲的还是已经被分配出去了,下图中的f/a是free/allocate,也就是标记是已经分配出去还是空闲的。这32个比特位就是header,用来存储块信息。
剩下的灰色部分才是真正可以分配给用户的内存,这一部分也被称为负载,payload,我们调用malloc返回的内存起始地址正是这块内存的起始地址
现在你应该知道了吧,不是说堆上有10G内存,这里面就可以全部用来存储数据的,这里面必然有一部分要拿出来维护内存块的一些信息,就像这里的header一样。

跟踪内存分配状态
有了上图,我们就可以将堆这块内存区域组织起来并进行内存分配与释放了,如图所示:
在这里我们的堆区还很小,每一方框代表4字节,其中红色区域表示已经分配出去的,灰色区域表示空闲内存,每一块内存都有一个header,用带斜线的方框表示,比如16/1,就表示该内存块大小是16字节,1表示已经分配出去了;而32/0表示该内存块大小是32字节,0表示该内存块当前空闲。
细心的同学可能会问,那最后一个方框0/1表示什么呢?原来,我们需要某种特殊标记来告诉我们的内存分配器是不是已经到末尾了,这就是最后4字节的作用。
通过引入header我们就能知道每一个内存块的大小,从而可以很方便的遍历整个堆区。遍历方法很简单,因为我们知道每一块的大小,那么从当前的位置加上当前块的大小就是下一个内存块的起始位置,如图所示:
通过每一个header的最后一个bit位就能知道每一块内存是空闲的还是已经分配出去了,这样我们就能追踪到每一个内存块的分配信息,因此上文提到的第一个问题解决了。
接下来我们看第二个问题。

怎样选择空闲内存块
当应用程序调用我们实现的malloc时,内存分配器需要遍历整个空闲内存块找到一块能满足应用程序要求的内存块返回,就像下图这样:
假设应用程序需要申请4字节内存,从图中我们可以看到有两个空闲内存块满足要求,第一个大小为8字节的内存块和第三个大小为32字节的内存块,那么我们到底该选择哪一个返回呢?这就涉及到了分配策略的问题,实际上这里有很多的策略可供选择。

First Fit
最简单的就是每次从头开始找起,找到第一个满足要求的就返回,这就是所谓的First fit方法,教科书中一般称为首次适应方法,当然我们不需要记住这样拗口的名字,只需要记住这是什么意思就可以了。
这种方法的优势在于简单,但该策略总是从前面的空闲块找起,因此很容易在堆区前半部分因分配出内存留下很多小的内存块,因此下一次内存申请搜索的空闲块数量将会越来越多。

Next Fit
该方法是大名鼎鼎的Donald Knuth首次提出来的,如果你不知道谁是Donald Knuth,那么数据结构课上折磨的你痛不欲生的字符串匹配KMP算法你一定不会错过,KMP其中的K就是指Donald Knuth,该算法全称Knuth–Morris–Pratt string-searching algorithm,如果你也没听过KMP算法那么你一定听过下面这本书:
这就是更加大名鼎鼎的《计算机程序设计艺术》,这本书就是Donald Knuth写的,如果你没有听过这本书请面壁思过一分钟,比尔盖茨曾经说过,如果你看懂了这本书就去给微软投简历吧,这本书也是很多程序员买回来后从来不会翻一眼只是拿来当做镇宅之宝用的。
不止比尔盖茨,有一次乔布斯见到Knuth老爷子后。。算了,扯远了,有机会再和大家讲这个故事,拉回来。
Next Fit说的是什么呢?这个策略和First Fit很相似,是说我们别总是从头开始找了,而是从上一次找到合适的空闲内存块的位置找起,老爷子观察到上一次找到某个合适的内存块的地方很有可能剩下的内存块能满足接下来的内存分配请求,由于不需要从头开始搜索,因此Next Fit将远快于First Fit
然而也有研究表明Next Fit方法内存使用率不及First Fit,也就是同样的停车场面积,First Fit方法能停更多的车。

Best Fit
First Fit和Next Fit都是找到第一个满足要求的内存块就返回,但Best Fit不是这样。
Best Fit算法会找到所有的空闲内存块,然后将所有满足要求的并且大小为最小的那个空闲内存块返回,这样的空闲内存块才是最Best的,因此被称为Best Fit。就像下图虽然有三个空闲内存块满足要求,但是Best Fit会选择大小为8字节的空闲内存块。
显然,从直觉上我们就能得出Best Fit会比前两种方法能更合理利用内存的结论,各项研究也证实了这一点。
然而Best Fit最大的缺点就是分配内存时需要遍历堆上所有的空闲内存块,在速度上显然不及前面两种方法。
以上介绍的这三种策略在各种内存分配器中非常常见,当然分配策略远不止这几种,但这些算法不是该主题下关注的重点,因此就不在这里详细阐述了,假设在这里我们选择First Fit算法。

没有银弹
重要的是,从上面的介绍中我们能够看到,没有一种完美的策略,每一种策略都有其优点和缺点,我们能做到的只有取舍和权衡。因此,要实现一个内存分配器,设计空间其实是非常大的,要想设计出一个通用的内存分配器,就像我们常用的malloc是很不容易的。
其实不止内存分配器,在设计其它软件系统时我们也没有银弹。

分配内存
现在我们找到合适的空闲内存块了,接下来我们又将面临一个新的问题。
如果用户需要12字节,而我们的空闲内存块也恰好是12字节,那么很好,直接返回就可以了。
但是,如果用户申请12字节内存,而我们找到的空闲内存块大小为32字节,那么我们是要将这32字节的整个空闲内存块标记为已分配吗?就像这样:
这样虽然速度最快,但显然会浪费内存,形成内部碎片,也就是说该内存块剩下的空间将无法被利用到。
一种显而易见的方法就是将空闲内存块进行划分,前一部分设置为已分配,返回给内存申请者使用,后一部分变为一个新的空闲内存块,只不过大小会更小而已,就像这样:
我们需要将空闲内存块大小从32修改为16,其中消息头header占据4字节,剩下的12字节分配出去,并将标记为置为1,表示该内存块已分配。
分配出16字节后,还剩下16字节,我们需要拿出4字节作为新的header并将其标记为空闲内存块。

释放内存
到目前为止,我们的malloc已经能够处理内存分配请求了,还差最后的内存释放。
内存释放和我们想象的不太一样,该过程并不比前几个环节简单。我们要考虑到的关键一点就在于,与被释放的内存块相邻的内存块可能也是空闲的。如果释放一块内存后我们仅仅简单的将其标志位置为空闲,那么可能会出现下面的场景:
从图中我们可以看到,被释放内存的下一个内存块也是空闲的,如果我们仅仅将这16个字节的内存块标记为空闲的话,那么当下一次申请20字节时图中的这两个内存块都不能满足要求,尽管这两个空闲内存块的总数要超过20字节。
因此一种更好的方法是当应用程序向我们的malloc释放内存时,我们查看一下相邻的内存块是否是空闲的,如果是空闲的话我们需要合并空闲内存块,就像这样:
在这里我们又面临一个新的决策,那就是释放内存时我们要立即去检查能否够合并相邻空闲内存块吗?还是说我们可以推迟一段时间,推迟到下一次分配内存找不到满足要的空闲内存块时再合并相邻空闲内存块。
释放内存时立即合并空闲内存块相对简单,但每次释放内存时将引入合并内存块的开销,如果应用程序总是释放12字节然后申请12字节,然后在释放12字节等等这样重复的模式:
    
free(ptr); obj* ptr = malloc(12); free(ptr); obj* ptr = malloc(12); ...
那么这种内存使用模式对立即合并空闲内存块这种策略非常不友好,我们的内存分配器会有很多的 无用功 但这种策略最为简单,在这里我们依然选择使用这种简单的策略。
实际上我们需要意识到,实际使用的内存分配器都会有某种推迟合并空闲内存块的策略。

高效合并空闲内存块
合并空闲内存块的故事到这里就完了吗?问题没有那么简单。
让我们来看这样一个场景:
使用的内存块其前和其后都是空闲的,在当前的设计中我们可以很容易的知道后一个内存块是空闲的,因为我们只需要从当前位置向下移动16字节就是下一个内存块,但我们怎么能知道上一个内存块是不是空闲的呢?
我们之所以能向后跳是因为当前内存块的大小是知道的,那么我们该怎么向前跳找到上一个内存块呢?
还是我们上文提到的Donald Knuth,老爷子提出了一个很聪明的设计,我们之所以不能往前跳是因为不知道前一个内存块的信息,那么我们该怎么快速知道前一个内存块的信息呢?
Knuth老爷子的设计是这样的,我们不是有一个信息头header吗,那么我们就在该内存块的末尾再加一个信息尾,footer,footer一词用的很形象,header和footer的内容是一样的
因为上一内存块的footer和下一个内存块的header是相邻的,因此我们只需要在当前内存块的位置向上移动4直接就可以等到上一个内存块的信息,这样当我们释放内存时就可以快速的进行相邻空闲内存块的合并了。

收工
至此,我们的内存分配器就已经设计完毕了。
我们的简单内存分配器采用了First Fit分配算法;找到一个满足要求的内存块后会进行切分,剩下的作为新的内存块;同时当释放内存时会立即合并相邻的空闲内存块,同时为加快合并速度,我们引入了Donald Knuth的设计方法,为每个内存块增加footer信息。
这样,我们自己实现的内存分配就可以运行起来了,可以真正的申请和释放内存

总结
本文从0到1实现了一个简单的内存分配器,但不希望这里的阐述给大家留下内存分配器实现很简单的印象,实际上本文实现的内存分配器还有大量的优化空间,同时我们也没有考虑线程安全问题,但这些都不是本文的目的。
本文的目的在于把内存分配器的本质告诉大家,对于想理解内存分配器实现原理的同学来说这些已经足够了,而对于要编写高性能程序的同学来说实现自己的内存池是必不可少的,内存池实现也离不开这里的讨论。
希望本文对大家理解内存分配器有帮助。

最后的最后,如果觉得文章对你有帮助的话,请多多分享转发在看

C语言与CPP编程 C语言/C++开发,C语言/C++基础知识,C语言/C++学习路线,C语言/C++进阶,数据结构;算法;python;计算机基础等
评论
  • 「他明明跟我同梯进来,为什么就是升得比我快?」许多人都有这样的疑问:明明就战绩也不比隔壁同事差,升迁之路却比别人苦。其实,之间的差异就在于「领导力」。並非必须当管理者才需要「领导力」,而是散发领导力特质的人,才更容易被晓明。许多领导力和特质,都可以通过努力和学习获得,因此就算不是天生的领导者,也能成为一个具备领导魅力的人,进而被老板看见,向你伸出升迁的橘子枝。领导力是什么?领导力是一种能力或特质,甚至可以说是一种「影响力」。好的领导者通常具备影响和鼓励他人的能力,并导引他们朝着共同的目标和愿景前
    优思学院 2025-01-08 14:54 93浏览
  • 村田是目前全球量产硅电容的领先企业,其在2016年收购了法国IPDiA头部硅电容器公司,并于2023年6月宣布投资约100亿日元将硅电容产能提升两倍。以下内容主要来自村田官网信息整理,村田高密度硅电容器采用半导体MOS工艺开发,并使用3D结构来大幅增加电极表面,因此在给定的占位面积内增加了静电容量。村田的硅技术以嵌入非结晶基板的单片结构为基础(单层MIM和多层MIM—MIM是指金属 / 绝缘体/ 金属) 村田硅电容采用先进3D拓扑结构在100um内,使开发的有效静电容量面积相当于80个
    知白 2025-01-07 15:02 155浏览
  • 光伏逆变器是一种高效的能量转换设备,它能够将光伏太阳能板(PV)产生的不稳定的直流电压转换成与市电频率同步的交流电。这种转换后的电能不仅可以回馈至商用输电网络,还能供独立电网系统使用。光伏逆变器在商业光伏储能电站和家庭独立储能系统等应用领域中得到了广泛的应用。光耦合器,以其高速信号传输、出色的共模抑制比以及单向信号传输和光电隔离的特性,在光伏逆变器中扮演着至关重要的角色。它确保了系统的安全隔离、干扰的有效隔离以及通信信号的精准传输。光耦合器的使用不仅提高了系统的稳定性和安全性,而且由于其低功耗的
    晶台光耦 2025-01-09 09:58 43浏览
  • 根据环洋市场咨询(Global Info Research)项目团队最新调研,预计2030年全球中空长航时无人机产值达到9009百万美元,2024-2030年期间年复合增长率CAGR为8.0%。 环洋市场咨询机构出版了的【全球中空长航时无人机行业总体规模、主要厂商及IPO上市调研报告,2025-2031】研究全球中空长航时无人机总体规模,包括产量、产值、消费量、主要生产地区、主要生产商及市场份额,同时分析中空长航时无人机市场主要驱动因素、阻碍因素、市场机遇、挑战、新产品发布等。报告从中空长航时
    GIRtina 2025-01-09 10:35 60浏览
  • 在当前人工智能(AI)与物联网(IoT)的快速发展趋势下,各行各业的数字转型与自动化进程正以惊人的速度持续进行。如今企业在设计与营运技术系统时所面临的挑战不仅是技术本身,更包含硬件设施、第三方软件及配件等复杂的外部因素。然而这些系统往往讲究更精密的设计与高稳定性,哪怕是任何一个小小的问题,都可能对整体业务运作造成严重影响。 POS应用环境与客户需求以本次分享的客户个案为例,该客户是一家全球领先的信息技术服务与数字解决方案提供商,遭遇到一个由他们所开发的POS机(Point of Sal
    百佳泰测试实验室 2025-01-09 17:35 59浏览
  • 在智能网联汽车中,各种通信技术如2G/3G/4G/5G、GNSS(全球导航卫星系统)、V2X(车联网通信)等在行业内被广泛使用。这些技术让汽车能够实现紧急呼叫、在线娱乐、导航等多种功能。EMC测试就是为了确保在复杂电磁环境下,汽车的通信系统仍然可以正常工作,保护驾乘者的安全。参考《QCT-基于LTE-V2X直连通信的车载信息交互系统技术要求及试验方法-1》标准10.5电磁兼容试验方法,下面将会从整车功能层面为大家解读V2X整车电磁兼容试验的过程。测试过程揭秘1. 设备准备为了进行电磁兼容试验,技
    北汇信息 2025-01-09 11:24 69浏览
  • 故障现象一辆2017款东风风神AX7车,搭载DFMA14T发动机,累计行驶里程约为13.7万km。该车冷起动后怠速运转正常,热机后怠速运转不稳,组合仪表上的发动机转速表指针上下轻微抖动。 故障诊断 用故障检测仪检测,发动机控制单元中无故障代码存储;读取发动机数据流,发现进气歧管绝对压力波动明显,有时能达到69 kPa,明显偏高,推断可能的原因有:进气系统漏气;进气歧管绝对压力传感器信号失真;发动机机械故障。首先从节气门处打烟雾,没有发现进气管周围有漏气的地方;接着拔下进气管上的两个真空
    虹科Pico汽车示波器 2025-01-08 16:51 107浏览
  • 本文介绍编译Android13 ROOT权限固件的方法,触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。关闭selinux修改此文件("+"号为修改内容)device/rockchip/common/BoardConfig.mkBOARD_BOOT_HEADER_VERSION ?= 2BOARD_MKBOOTIMG_ARGS :=BOARD_PREBUILT_DTB
    Industio_触觉智能 2025-01-08 00:06 111浏览
  • 职场是人生的重要战场,既是谋生之地,也是实现个人价值的平台。然而,有些思维方式却会悄无声息地拖住你的后腿,让你原地踏步甚至退步。今天,我们就来聊聊职场中最忌讳的五种思维方式,看看自己有没有中招。1. 固步自封的思维在职场中,最可怕的事情莫过于自满于现状,拒绝学习和改变。世界在不断变化,行业的趋势、技术的革新都在要求我们与时俱进。如果你总觉得自己的方法最优,或者害怕尝试新事物,那就很容易被淘汰。与其等待机会找上门,不如主动出击,保持学习和探索的心态。加入优思学院,可以帮助你快速提升自己,与行业前沿
    优思学院 2025-01-09 15:48 53浏览
  • 1月7日-10日,2025年国际消费电子产品展览会(CES 2025)盛大举行,广和通发布Fibocom AI Stack,赋智千行百业端侧应用。Fibocom AI Stack提供集高性能模组、AI工具链、高性能推理引擎、海量模型、支持与服务一体化的端侧AI解决方案,帮助智能设备快速实现AI能力商用。为适应不同端侧场景的应用,AI Stack具备海量端侧AI模型及行业端侧模型,基于不同等级算力的芯片平台或模组,Fibocom AI Stack可将TensorFlow、PyTorch、ONNX、
    物吾悟小通 2025-01-08 18:17 53浏览
  • 一个真正的质量工程师(QE)必须将一件产品设计的“意图”与系统的可制造性、可服务性以及资源在现实中实现设计和产品的能力结合起来。所以,可以说,这确实是一种工程学科。我们常开玩笑说,质量工程师是工程领域里的「侦探」、「警察」或「律师」,守护神是"墨菲”,信奉的哲学就是「墨菲定律」。(注:墨菲定律是一种启发性原则,常被表述为:任何可能出错的事情最终都会出错。)做质量工程师的,有时会不受欢迎,也会被忽视,甚至可能遭遇主动或被动的阻碍,而一旦出了问题,责任往往就落在质量工程师的头上。虽然质量工程师并不负
    优思学院 2025-01-09 11:48 82浏览
  • HDMI 2.2 规格将至,开启视听新境界2025年1月6日,HDMI Forum, Inc. 宣布即将发布HDMI规范2.2版本。新HDMI规范为规模庞大的 HDMI 生态系统带来更多选择,为创建、分发和体验理想的终端用户效果提供更先进的解决方案。新技术为电视、电影和游戏工作室等内容制作商在当前和未来提供更高质量的选择,同时实现多种分发平台。96Gbps的更高带宽和新一代 HDMI 固定比率速率传输(Fixed Rate Link)技术为各种设备应用提供更优质的音频和视频。终端用户显示器能以最
    百佳泰测试实验室 2025-01-09 17:33 60浏览
  • 在过去十年中,自动驾驶和高级驾驶辅助系统(AD/ADAS)软件与硬件的快速发展对多传感器数据采集的设计需求提出了更高的要求。然而,目前仍缺乏能够高质量集成多传感器数据采集的解决方案。康谋ADTF正是应运而生,它提供了一个广受认可和广泛引用的软件框架,包含模块化的标准化应用程序和工具,旨在为ADAS功能的开发提供一站式体验。一、ADTF的关键之处!无论是奥迪、大众、宝马还是梅赛德斯-奔驰:他们都依赖我们不断发展的ADTF来开发智能驾驶辅助解决方案,直至实现自动驾驶的目标。从新功能的最初构思到批量生
    康谋 2025-01-09 10:04 58浏览
  •  在全球能源结构加速向清洁、可再生方向转型的今天,风力发电作为一种绿色能源,已成为各国新能源发展的重要组成部分。然而,风力发电系统在复杂的环境中长时间运行,对系统的安全性、稳定性和抗干扰能力提出了极高要求。光耦(光电耦合器)作为一种电气隔离与信号传输器件,凭借其优秀的隔离保护性能和信号传输能力,已成为风力发电系统中不可或缺的关键组件。 风力发电系统对隔离与控制的需求风力发电系统中,包括发电机、变流器、变压器和控制系统等多个部分,通常工作在高压、大功率的环境中。光耦在这里扮演了
    晶台光耦 2025-01-08 16:03 84浏览
我要评论
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦