Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Miykael_xxm
RCore Tutorial Book V3
提交
f7dfb8bc
R
RCore Tutorial Book V3
项目概览
Miykael_xxm
/
RCore Tutorial Book V3
与 Fork 源项目一致
Fork自
rcore-os / RCore Tutorial Book V3
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
R
RCore Tutorial Book V3
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
f7dfb8bc
编写于
2月 28, 2021
作者:
chyyuu1972
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
update ch4:sec0/1
上级
b12623d8
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
10 addition
and
11 deletion
+10
-11
source/chapter4/0intro.rst
source/chapter4/0intro.rst
+1
-1
source/chapter4/1rust-dynamic-allocation.rst
source/chapter4/1rust-dynamic-allocation.rst
+9
-10
未找到文件。
source/chapter4/0intro.rst
浏览文件 @
f7dfb8bc
...
...
@@ -39,7 +39,7 @@
-----------------------
本章的应用和上一章相同,只不过由于内核提供给应用的访存接口被替换,应用的构建方式发生了变化,这方面在下面会深入介绍。
因此应用运行起来的
话效果是和上一章保持
一致的。
因此应用运行起来的
效果与上一章是
一致的。
获取本章代码:
...
...
source/chapter4/1rust-dynamic-allocation.rst
浏览文件 @
f7dfb8bc
...
...
@@ -46,8 +46,8 @@ Rust 中的动态内存分配
我们课上所介绍到的那些算法都可以随意使用。取决于应用的实际运行状况,每次分配的空间大小可能会有不同,因此也会产生外碎片。
如果在某次分配的时候发现堆空间不足,我们并不会像上一小节介绍的那样移动变量的存放位置让它们紧凑起来从而释放间隙用来分配
(事实上它很难做到这一点),
一般情况下应用会直接通过系统调用(如类 Unix 内核提供的 ``sbrk`` 调用)来向内核请求增加它地址空间内堆的大小,之后
就可以正常分配了。
注意
这一类系统调用也能缩减堆的大小。
一般情况下应用会直接通过系统调用(如类 Unix 内核提供的 ``sbrk``
系统
调用)来向内核请求增加它地址空间内堆的大小,之后
就可以正常分配了。
当然,
这一类系统调用也能缩减堆的大小。
鉴于动态分配是一项非常基础的功能,很多高级语言的标准库中都实现了它。以 C 语言为例,C 标准库中提供了如下两个动态分配
的接口函数:
...
...
@@ -60,7 +60,7 @@ Rust 中的动态内存分配
其中,``malloc`` 的作用是从堆中分配一块大小为 ``size`` 字节的空间,并返回一个指向它的指针。而后续不用的时候,将这个
指针传给 ``free`` 即可在堆中回收这块空间。我们通过返回的指针变量来间接访问堆上的空间,而无法直接进行
访问。事实上,我们在程序中能够 *直接* 看到的变量都是被静态分配在栈或者全局数据段上的,它们大小在编译期已知,比如这里
一个指针类型的大小就
等于平台
的位宽。这样的它们却可以作为背后一块大小在编译期无法确定的空间的代表,这是一件非常有趣的
一个指针类型的大小就
可以等于计算机可寻址空间
的位宽。这样的它们却可以作为背后一块大小在编译期无法确定的空间的代表,这是一件非常有趣的
事情。
除了可以灵活利用内存之外,动态分配还允许我们以尽可能小的代价灵活调整变量的生命周期。一个局部变量被静态分配在它所在函数
...
...
@@ -69,8 +69,7 @@ Rust 中的动态内存分配
一个变量的指针到 ``free`` 将它回收之前的这段时间,这个变量在堆上存在。由于需要跨越函数调用,我们需要作为堆上数据代表
的变量在函数间以参数或返回值的形式进行传递,而这些变量一般都很小(如一个指针),其拷贝开销可以忽略。
而动态内存分配的缺点在于:它背后运行着连续内存分配算法,它相比静态分配会带来一些额外的开销。如果动态分配非常频繁,
它甚至可能会成为应用的性能瓶颈。
而动态内存分配的缺点在于:它背后运行着连续内存分配算法,相比静态分配会带来一些额外的开销。如果动态分配非常频繁,可能会产生很多无法使用的空闲空间碎片,甚至可能会成为应用的性能瓶颈。
.. _rust-heap-data-structures:
...
...
@@ -169,10 +168,10 @@ RAII 的含义是说,将一个使用前必须获取的资源的生命周期绑
上边介绍的那些与堆相关的智能指针或容器都可以在 Rust 自带的 ``alloc`` crate 中找到。当我们使用 Rust 标准库
``std`` 的时候可以不用关心这个 crate ,因为标准库内已经已经实现了一套堆管理算法,并将 ``alloc`` 的内容包含在
``std`` 名字空间之下让开发者可以直接使用。然而我们的内核是在禁用了标准库(即 ``no_std`` )的裸机平台,核心库
``core`` 也并没有动态内存分配的功能,这个时候就要考虑利用 ``alloc`` 了。
``core`` 也并没有动态内存分配的功能,这个时候就要考虑利用 ``alloc``
库
了。
``alloc`` 需要我们提供给它一个全局的动态内存分配器,它会利用该分配器来管理堆空间,从而它提供的数据结构可以正常
工作。我们的动态内存分配器需要实现它提供的 ``GlobalAlloc`` Trait,这个 Trait 有两个必须实现的抽象接口:
``alloc``
库
需要我们提供给它一个全局的动态内存分配器,它会利用该分配器来管理堆空间,从而它提供的数据结构可以正常
工作。
具体而言,
我们的动态内存分配器需要实现它提供的 ``GlobalAlloc`` Trait,这个 Trait 有两个必须实现的抽象接口:
.. code-block:: rust
...
...
@@ -190,7 +189,7 @@ RAII 的含义是说,将一个使用前必须获取的资源的生命周期绑
**为何 C 语言 malloc 的时候不需要提供对齐需求?**
在 C 语言中,所有对齐要求的最大值是一个平台有关的很小的常数,消耗少量内存即可使得每一次分配都符合这个最大
在 C 语言中,所有对齐要求的最大值是一个平台有关的很小的常数
(比如8 bytes)
,消耗少量内存即可使得每一次分配都符合这个最大
的对齐要求。因此也就不需要区分不同分配的对齐要求了。而在 Rust 中,某些分配的对齐要求可能很大,就只能采用更
加复杂的方法。
...
...
@@ -203,7 +202,7 @@ RAII 的含义是说,将一个使用前必须获取的资源的生命周期绑
buddy_system_allocator = "0.6"
接着,需要引入 ``alloc`` 的依赖,由于它算是 Rust 内置的 crate ,我们并不是在 ``Cargo.toml`` 中进行引入,而是在
接着,需要引入 ``alloc``
库
的依赖,由于它算是 Rust 内置的 crate ,我们并不是在 ``Cargo.toml`` 中进行引入,而是在
``main.rs`` 中声明即可:
.. code-block:: rust
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录