mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-18 20:36:31 +00:00
BIN
docs/Multiboot2 Specification version 2.0.pdf
Normal file
BIN
docs/Multiboot2 Specification version 2.0.pdf
Normal file
Binary file not shown.
@ -3,50 +3,12 @@
|
||||
与社区建立联系
|
||||
====================================
|
||||
|
||||
联系方式
|
||||
-------------------------
|
||||
|
||||
社区公共邮箱:contact@DragonOS.org
|
||||
|
||||
DragonOS社区负责人: longjin
|
||||
DragonOS负责人: longjin
|
||||
|
||||
工作邮箱: longjin@DragonOS.org
|
||||
|
||||
开发交流QQ群: 115763565
|
||||
|
||||
DragonOS官网: https://DragonOS.org
|
||||
|
||||
了解开发动态、开发任务,请访问DragonOS的zulip社群: https://DragonOS.zulipchat.com
|
||||
|
||||
|
||||
赞助及捐赠
|
||||
-------------------------
|
||||
|
||||
DragonOS是一个开源项目,我们欢迎任何形式的赞助和捐赠,您的捐赠将用于DragonOS的开发和维护,以及社区的运营。
|
||||
|
||||
您可以通过以下方式赞助和捐赠:
|
||||
|
||||
- 访问DragonOS官网 https://DragonOS.org ,点击页面右上角的“赞助”按钮,进行捐赠
|
||||
- 联系社区负责人,沟通具体的赞助方式等。
|
||||
|
||||
财务及捐赠信息公开
|
||||
-------------------------
|
||||
|
||||
DragonOS社区的捐赠信息将按年进行公开。赞助商、赞助者信息将在收到赞助后,15天内进行公开。
|
||||
|
||||
社区管理、财务及法务主体
|
||||
-------------------------
|
||||
|
||||
DragonOS社区的管理、财务及法务主体为:灵高计算机系统(广州)有限公司。
|
||||
|
||||
我们是一家开源公司,我们坚信,开源能为我国将来的IT,打下更好的基础。我们也通过其他业务创收,投入到DragonOS的研发之中。
|
||||
|
||||
公司负责DragonOS社区的运营、财务、法务事项处理工作。
|
||||
|
||||
地址:广东省广州市番禺区小谷围街广州大学城华南理工大学大学城校区
|
||||
|
||||
邮件:contact@DragonOS.org
|
||||
|
||||
官网:https://ringotek.com.cn
|
||||
|
||||
|
||||
|
@ -233,10 +233,7 @@ make run-docker
|
||||
- Docker编译,并写入磁盘镜像,: `make docker`
|
||||
- Docker编译,写入磁盘镜像,并在QEMU中运行: `make run-docker`
|
||||
- 不编译,直接从已有的磁盘镜像启动: `make qemu`
|
||||
- 清理编译产生的文件: `make clean`
|
||||
- 编译文档: `make docs` (需要手动安装sphinx以及docs下的`requirements.txt`中的依赖)
|
||||
- 清理文档: `make clean-docs`
|
||||
|
||||
:::{note}
|
||||
如果您需要在vnc中运行DragonOS,请在上述命令后加上`-vnc`后缀。如:`make run-vnc`
|
||||
:::
|
||||
:::
|
@ -12,14 +12,10 @@
|
||||
|
||||
### 内存管理
|
||||
|
||||
- [x] 页帧分配器
|
||||
- [x] 小对象分配器
|
||||
- [x] 页分配器
|
||||
- [x] slab分配器
|
||||
- [x] VMA
|
||||
- [x] MMIO地址空间自动分配
|
||||
- [x] 页面映射器
|
||||
- [x] 硬件抽象层
|
||||
- [x] 独立的用户地址空间管理机制
|
||||
- [x] C接口兼容层
|
||||
|
||||
### 多核
|
||||
|
||||
@ -35,7 +31,6 @@
|
||||
- [x] exec
|
||||
- [x] 进程睡眠(支持高精度睡眠)
|
||||
- [x] kthread机制
|
||||
- [x] 可扩展二进制加载器
|
||||
|
||||
#### 同步原语
|
||||
|
||||
@ -48,10 +43,7 @@
|
||||
### 调度
|
||||
|
||||
- [x] CFS调度器
|
||||
- [x] 实时调度器(FIFO、RR)
|
||||
- [x] 单核调度
|
||||
- [x] 多核调度
|
||||
- [x] 负载均衡
|
||||
|
||||
### IPC
|
||||
|
||||
@ -64,8 +56,7 @@
|
||||
- [x] fat12/16/32
|
||||
- [x] Devfs
|
||||
- [x] RamFS
|
||||
- [x] Procfs
|
||||
- [x] Sysfs
|
||||
- [x] procfs
|
||||
|
||||
### 异常及中断处理
|
||||
|
||||
@ -104,7 +95,7 @@
|
||||
- [x] ACPI 高级电源配置模块
|
||||
- [x] IDE硬盘
|
||||
- [x] AHCI硬盘
|
||||
- [x] PCI、PCIe总线
|
||||
- [x] PCI
|
||||
- [x] XHCI(usb3.0)
|
||||
- [x] ps/2 键盘
|
||||
- [x] ps/2 鼠标
|
||||
@ -116,8 +107,6 @@
|
||||
- [x] VirtIO网卡
|
||||
- [x] x87FPU
|
||||
- [x] TTY终端
|
||||
- [x] 浮点处理器
|
||||
|
||||
|
||||
## 用户层
|
||||
|
||||
@ -132,9 +121,9 @@
|
||||
- [x] 基于字符串匹配的解析
|
||||
- [x] 基本的几个命令
|
||||
|
||||
### Http Server
|
||||
### 驱动程序
|
||||
|
||||
- 使用C编写的简单的Http Server,能够运行静态网站。
|
||||
- [x] ps/2键盘用户态驱动
|
||||
|
||||
## 软件移植
|
||||
|
||||
@ -143,4 +132,3 @@
|
||||
- [x] gmp 6.2.1 [https://github.com/DragonOS-Community/gmp-6.2.1](https://github.com/DragonOS-Community/gmp-6.2.1)
|
||||
- [x] mpfr 4.1.1 [https://github.com/DragonOS-Community/mpfr](https://github.com/DragonOS-Community/mpfr)
|
||||
- [x] mpc 1.2.1 [https://github.com/DragonOS-Community/mpc](https://github.com/DragonOS-Community/mpc)
|
||||
- [x] relibc [https://github.com/DragonOS-Community/relibc](https://github.com/DragonOS-Community/relibc)
|
||||
|
@ -3,11 +3,9 @@ DragonOS简介
|
||||
|
||||
DragonOS龙操作系统(以下简称“DragonOS”)是一个面向服务器领域的,从0开发内核及用户态环境,并提供Linux兼容性的64位操作系统。它使用Rust与C语言进行编写,并正在逐步淘汰原有的C代码,以在将来提供更好的安全性与可靠性。
|
||||
|
||||
**我们致力于打造完全自主可控的数字化未来!**
|
||||
|
||||
DragonOS的目标是,构建一个完全独立自主的、开源的、高性能及高可靠性的服务器操作系统,为国家数字基础设施建设提供完全独立自主的底层核心动力。
|
||||
|
||||
作为一个社区驱动的开源操作系统,为了促进开源社区建设,并避免让其遭受一些不遵守开源协议的商业公司的侵权,我们决定使用GPLv2协议开放源代码,以严格的开源协议来保护DragonOS。
|
||||
作为一个社区驱动的开源操作系统,为了促进其发展,避免让其遭受一些不遵守开源协议的商业公司的侵权,我们决定使用GPLv2协议开放源代码,以严格的开源协议来保护DragonOS。
|
||||
|
||||
你可能对DragonOS中已经实现了哪些功能感兴趣,您可以转到这里::ref:`功能特性 <_genreal_features>`
|
||||
|
||||
|
15
docs/kernel/core_api/allocate-memory.md
Normal file
15
docs/kernel/core_api/allocate-memory.md
Normal file
@ -0,0 +1,15 @@
|
||||
# 内存分配指南
|
||||
|
||||
DragonOS提供了一些用于内存分配的api。您可以使用*kmalloc*来分配小的内存块,也可以使用*alloc_pages*分配连续的2MB大小的内存页面。
|
||||
|
||||
## 选择合适的内存分配器
|
||||
|
||||
在内核中,最直接、最简单的分配内存的方式就是,使用`kmalloc()`函数进行分配。并且,出于安全起见,除非内存在分配后一定会被覆盖,且您能确保内存中的脏数据一定不会对程序造成影响,在其余情况下,我们建议使用`kzalloc()`进行内存分配,它将会在`kmalloc()`的基础上,把申请到的内存进行清零。
|
||||
|
||||
您可以通过`kmalloc()`函数分配得到32bytes到1MBytes之间的内存对象。并且,这些内存对象具有以下的性质:
|
||||
|
||||
- 内存起始地址及大小按照2次幂对齐。(比如,申请的是80bytes的内存空间,那么获得的内存对象大小为128bytes且内存地址按照128bytes对齐)
|
||||
|
||||
对于需要大量连续内存的分配,可以使用`alloc_pages()`向页面分配器申请连续的内存页。
|
||||
|
||||
当内存空间不再被使用时,那么必须释放他们。若您使用的是`kmalloc()`分配的内存,那么您需要使用`kfree()`释放它。若是使用`alloc_pages()`分配的内存,则需要使用`free_pages()`来释放它们。
|
@ -13,3 +13,16 @@
|
||||
data_structures
|
||||
casting
|
||||
softirq
|
||||
|
||||
内存管理
|
||||
===================
|
||||
|
||||
这里快速讲解了如何在DragonOS中分配、使用内存。以便您能快速的了解这个模块。
|
||||
|
||||
详细的内存管理模块的文档请参见::ref:`memory_management_module`
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
allocate-memory
|
||||
mm-api
|
267
docs/kernel/core_api/mm-api.md
Normal file
267
docs/kernel/core_api/mm-api.md
Normal file
@ -0,0 +1,267 @@
|
||||
(_core_mm_api)=
|
||||
|
||||
# 内存管理API
|
||||
|
||||
## SLAB内存池
|
||||
|
||||
SLAB内存池提供小内存对象的分配功能。
|
||||
|
||||
### `void *kmalloc(unsigned long size, gfp_t gfp)`
|
||||
|
||||
  获取小块的内存。
|
||||
|
||||
#### 描述
|
||||
|
||||
  kmalloc用于获取那些小于2M内存页大小的内存对象。可分配的内存对象大小为32bytes~1MBytes. 且分配的内存块大小、起始地址按照2的n次幂进行对齐。(比如,申请的是80bytes的内存空间,那么获得的内存对象大小为128bytes且内存地址按照128bytes对齐)
|
||||
|
||||
##### 参数
|
||||
|
||||
**size**
|
||||
|
||||
  内存对象的大小
|
||||
|
||||
**gfp**
|
||||
|
||||
  标志位
|
||||
|
||||
### `void *kzalloc(unsigned long size, gfp_t gfp)`
|
||||
|
||||
#### 描述
|
||||
|
||||
  获取小块的内存,并将其清零。其余功能与kmalloc相同。
|
||||
|
||||
|
||||
##### 参数
|
||||
|
||||
**size**
|
||||
|
||||
  内存对象的大小
|
||||
|
||||
**gfp**
|
||||
|
||||
  标志位
|
||||
|
||||
### `unsigned long kfree(void *address)`
|
||||
|
||||
  释放从slab分配的内存。
|
||||
|
||||
#### 描述
|
||||
|
||||
  该函数用于释放通过kmalloc申请的内存。如果`address`为NULL,则函数被调用后,无事发生。
|
||||
|
||||
  请不要通过这个函数释放那些不是从`kmalloc()`或`kzalloc()`申请的内存,否则将会导致系统崩溃。
|
||||
|
||||
##### 参数
|
||||
|
||||
**address**
|
||||
|
||||
  指向内存对象的起始地址的指针
|
||||
|
||||
## 物理页管理
|
||||
|
||||
DragonOS支持对物理页的直接操作
|
||||
|
||||
### `struct Page *alloc_pages(unsigned int zone_select, int num, ul flags)`
|
||||
|
||||
#### 描述
|
||||
|
||||
  从物理页管理单元中申请一段连续的物理页
|
||||
|
||||
#### 参数
|
||||
|
||||
**zone_select**
|
||||
|
||||
  要申请的物理页所位于的内存区域
|
||||
|
||||
可选值:
|
||||
|
||||
- `ZONE_DMA` DMA映射专用区域
|
||||
- `ZONE_NORMAL` 正常的物理内存区域,已在页表高地址处映射
|
||||
- `ZONE_UNMAPPED_IN_PGT` 尚未在页表中映射的区域
|
||||
|
||||
**num**
|
||||
|
||||
  要申请的连续物理页的数目,该值应当小于64
|
||||
|
||||
**flags**
|
||||
|
||||
  分配的页面要被设置成的属性
|
||||
|
||||
可选值:
|
||||
|
||||
- `PAGE_PGT_MAPPED` 页面在页表中已被映射
|
||||
- `PAGE_KERNEL_INIT` 内核初始化所占用的页
|
||||
- `PAGE_DEVICE` 设备MMIO映射的内存
|
||||
- `PAGE_KERNEL` 内核层页
|
||||
- `PAGE_SHARED` 共享页
|
||||
|
||||
#### 返回值
|
||||
|
||||
##### 成功
|
||||
|
||||
  成功申请则返回指向起始页面的Page结构体的指针
|
||||
|
||||
##### 失败
|
||||
|
||||
  当ZONE错误或内存不足时,返回`NULL`
|
||||
|
||||
### `void free_pages(struct Page *page, int number)`
|
||||
|
||||
#### 描述
|
||||
|
||||
  从物理页管理单元中释放一段连续的物理页。
|
||||
|
||||
#### 参数
|
||||
|
||||
**page**
|
||||
|
||||
  要释放的第一个物理页的Page结构体
|
||||
|
||||
**number**
|
||||
|
||||
  要释放的连续内存页的数量。该值应小于64
|
||||
|
||||
## 页表管理
|
||||
|
||||
### `int mm_map_phys_addr(ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool use4k)`
|
||||
|
||||
#### 描述
|
||||
|
||||
  将一段物理地址映射到当前页表的指定虚拟地址处
|
||||
|
||||
#### 参数
|
||||
|
||||
**virt_addr_start**
|
||||
|
||||
  虚拟地址的起始地址
|
||||
|
||||
**phys_addr_start**
|
||||
|
||||
  物理地址的起始地址
|
||||
|
||||
**length**
|
||||
|
||||
  要映射的地址空间的长度
|
||||
|
||||
**flags**
|
||||
|
||||
  页表项的属性
|
||||
|
||||
**use4k**
|
||||
|
||||
  使用4级页表,将地址区域映射为若干4K页
|
||||
|
||||
### `int mm_map_proc_page_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul phys_addr_start, ul length, ul flags, bool user, bool flush, bool use4k)`
|
||||
|
||||
#### 描述
|
||||
|
||||
  将一段物理地址映射到指定页表的指定虚拟地址处
|
||||
|
||||
#### 参数
|
||||
|
||||
**proc_page_table_addr**
|
||||
|
||||
  指定的顶层页表的起始地址
|
||||
|
||||
**is_phys**
|
||||
|
||||
  该顶层页表地址是否为物理地址
|
||||
|
||||
**virt_addr_start**
|
||||
|
||||
  虚拟地址的起始地址
|
||||
|
||||
**phys_addr_start**
|
||||
|
||||
  物理地址的起始地址
|
||||
|
||||
**length**
|
||||
|
||||
  要映射的地址空间的长度
|
||||
|
||||
**flags**
|
||||
|
||||
  页表项的属性
|
||||
|
||||
**user**
|
||||
|
||||
  页面是否为用户态可访问
|
||||
|
||||
**flush**
|
||||
|
||||
  完成映射后,是否刷新TLB
|
||||
|
||||
**use4k**
|
||||
|
||||
  使用4级页表,将地址区域映射为若干4K页
|
||||
|
||||
#### 返回值
|
||||
|
||||
- 映射成功:0
|
||||
- 映射失败:-EFAULT
|
||||
|
||||
### `void mm_unmap_proc_table(ul proc_page_table_addr, bool is_phys, ul virt_addr_start, ul length)`
|
||||
|
||||
#### 描述
|
||||
|
||||
  取消给定页表中的指定地址空间的页表项映射。
|
||||
|
||||
#### 参数
|
||||
|
||||
**proc_page_table_addr**
|
||||
|
||||
  指定的顶层页表的基地址
|
||||
|
||||
**is_phys**
|
||||
|
||||
  该顶层页表地址是否为物理地址
|
||||
|
||||
**virt_addr_start**
|
||||
|
||||
  虚拟地址的起始地址
|
||||
|
||||
**length**
|
||||
|
||||
  要取消映射的地址空间的长度
|
||||
|
||||
### `mm_unmap_addr(virt_addr, length)`
|
||||
|
||||
#### 描述
|
||||
|
||||
  该宏定义用于取消当前进程的页表中的指定地址空间的页表项映射。
|
||||
|
||||
#### 参数
|
||||
|
||||
**virt_addr**
|
||||
|
||||
  虚拟地址的起始地址
|
||||
|
||||
**length**
|
||||
|
||||
  要取消映射的地址空间的长度
|
||||
|
||||
## 内存信息获取
|
||||
|
||||
### `struct mm_stat_t mm_stat()`
|
||||
|
||||
#### 描述
|
||||
|
||||
  获取计算机目前的内存空间使用情况
|
||||
|
||||
#### 参数
|
||||
|
||||
无
|
||||
|
||||
#### 返回值
|
||||
|
||||
  返回值是一个`mm_mstat_t`结构体,该结构体定义于`mm/mm.h`中。其中包含了以下信息(单位均为字节):
|
||||
|
||||
| 参数名 | 解释 |
|
||||
| ---------- | ----------------------- |
|
||||
| total | 计算机的总内存数量大小 |
|
||||
| used | 已使用的内存大小 |
|
||||
| free | 空闲物理页所占的内存大小 |
|
||||
| shared | 共享的内存大小 |
|
||||
| cache_used | 位于slab缓冲区中的已使用的内存大小 |
|
||||
| cache_free | 位于slab缓冲区中的空闲的内存大小 |
|
||||
| available | 系统总空闲内存大小(包括kmalloc缓冲区) |
|
@ -1,29 +0,0 @@
|
||||
# 内存分配指南
|
||||
|
||||
  本文将讲述如何在内核中进行内存分配。在开始之前,请您先了解一个基本点:DragonOS的内核使用4KB的页来管理内存,并且具有伙伴分配器和slab分配器。并且对用户空间、内核空间均具有特定的管理机制。
|
||||
|
||||
## 1. 安全的分配内存
|
||||
|
||||
  在默认情况下,KernelAllocator被绑定为全局内存分配器,它会根据请求分配的内存大小,自动选择使用slab还是伙伴分配器。因此,在内核中,使用Rust原生的
|
||||
内存分配函数,或者是创建一个`Box`对象等等,都是安全的。
|
||||
|
||||
|
||||
## 2. 手动管理页帧
|
||||
|
||||
:::{warning}
|
||||
**请格外小心!** 手动管理页帧脱离了Rust的内存安全机制,因此可能会造成内存泄漏或者是内存错误。
|
||||
:::
|
||||
|
||||
  在某些情况下,我们需要手动分配页帧。例如,我们需要在内核中创建一个新的页表,或者是在内核中创建一个新的地址空间。这时候,我们需要手动分配页帧。使用`LockedFrameAllocator`的`allocate()`函数,能够分配在物理地址上连续的页帧。请注意,由于底层使用的是buddy分配器,因此页帧数目必须是2的n次幂,且最大大小不超过1GB。
|
||||
|
||||
  当需要释放页帧的时候,使用`LockedFrameAllocator`的`deallocate()`函数,或者是`deallocate_page_frames()`函数,能够释放在物理地址上连续的页帧。
|
||||
|
||||
  当您需要映射页帧的时候,可使用`KernelMapper::lock()`函数,获得一个内核映射器对象,然后进行映射。由于KernelMapper是对PageMapper的封装,因此您在获取KernelMapper之后,可以使用PageMapper相关接口对内核空间的映射进行管理。
|
||||
|
||||
:::{warning}
|
||||
**千万不要** 使用KernelMapper去映射用户地址空间的内存,这会使得这部分内存脱离用户地址空间的管理,从而导致内存错误。
|
||||
:::
|
||||
|
||||
## 3. 为用户程序分配内存
|
||||
|
||||
  在内核中,您可以使用用户地址空间结构体(`AddressSpace`)的`mmap()`,`map_anonymous()`等函数,为用户程序分配内存。这些函数会自动将用户程序的内存映射到用户地址空间中,并且会自动创建VMA结构体。您可以使用`AddressSpace`的`munmap()`函数,将用户程序的内存从用户地址空间中解除映射,并且销毁VMA结构体。调整权限等操作可以使用`AddressSpace`的`mprotect()`函数。
|
@ -1,14 +1,14 @@
|
||||
.. _memory_management_module:
|
||||
|
||||
====================================
|
||||
内存管理
|
||||
内存管理文档
|
||||
====================================
|
||||
|
||||
这里讲解了内存管理模块的一些设计及实现原理,以及相应的接口。
|
||||
这里讲解了内存管理模块的一些设计及实现原理。
|
||||
|
||||
如果你正在寻找使用内存管理模块的方法,请转到::ref:`内存管理API文档 <_core_mm_api>`
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
intro
|
||||
allocate-memory
|
||||
mmio
|
@ -1,20 +0,0 @@
|
||||
# 内存管理模块简介
|
||||
|
||||
## 1. 概述
|
||||
|
||||
  DragonOS实现了具有优秀架构设计的内存管理模块,对内核空间和用户空间的内存映射、分配、释放、管理等操作进行了封装,使得内核开发者可以更加方便地进行内存管理。
|
||||
|
||||
  DragonOS的内存管理模块主要由以下类型的组件组成:
|
||||
|
||||
- **硬件抽象层(MemoryManagementArch)** - 提供对具体处理器架构的抽象,使得内存管理模块可以在不同的处理器架构上运行
|
||||
- **页面映射器(PageMapper)**- 提供对虚拟地址和物理地址的映射,以及页表的创建、填写、销毁、权限管理等操作。分为两种类型:内核页表映射器(KernelMapper)和用户页表映射器(位于具体的用户地址空间结构中)
|
||||
- **页面刷新器(PageFlusher)** - 提供对页表的刷新操作(整表刷新、单页刷新、跨核心刷新)
|
||||
- **页帧分配器(FrameAllocator)** - 提供对页帧的分配、释放、管理等操作。具体来说,包括BumpAllocator、BuddyAllocator
|
||||
- **小对象分配器** - 提供对小内存对象的分配、释放、管理等操作。指的是内核里面的SlabAllocator (SlabAllocator的实现目前还没有完成)
|
||||
- **MMIO空间管理器** - 提供对MMIO地址空间的分配、管理操作。(目前这个模块待进一步重构)
|
||||
- **用户地址空间管理机制** - 提供对用户地址空间的管理。
|
||||
- VMA机制 - 提供对用户地址空间的管理,包括VMA的创建、销毁、权限管理等操作
|
||||
- 用户映射管理 - 与VMA机制共同作用,管理用户地址空间的映射
|
||||
- **系统调用层** - 提供对用户空间的内存管理系统调用,包括mmap、munmap、mprotect、mremap等
|
||||
- **C接口兼容层** - 提供对原有的C代码的接口,使得C代码能够正常运行。
|
||||
|
@ -5,5 +5,4 @@
|
||||
:maxdepth: 1
|
||||
|
||||
kthread
|
||||
pcb
|
||||
load_binary
|
||||
pcb
|
@ -1,15 +0,0 @@
|
||||
# 加载程序
|
||||
|
||||
## 1. 二进制程序装载
|
||||
|
||||
  在小节,你将了解DragonOS的二进制程序加载器的原理。
|
||||
|
||||
  DragonOS在装载二进制程序时,执行了“探测-装载”的过程。
|
||||
|
||||
  在探测阶段,DragonOS会读取文件首部,然后依次调用各个二进制加载器的探测函数,判断该二进制程序是否适用于该加载器。如果适用,则使用这个加载器进行装载。
|
||||
|
||||
  在装载阶段,DragonOS会使用上述加载器进行装载。装载器会将二进制程序的各个段映射到内存中,并且得到二进制程序的入口地址。
|
||||
|
||||
:::{note}
|
||||
目前DragonOS不支持动态链接,因此所有的二进制程序都是静态链接的。并且暂时支持的只有ELF加载器。
|
||||
:::
|
Reference in New Issue
Block a user