段页式内存管理(Previous article damaged after 优快云 upgradte Blog system~)

本文深入解析Linux系统的内存管理机制,包括段寄存器、页表转换、虚拟地址空间的划分及管理方式等内容。介绍了进程虚拟地址空间如何映射到物理地址,以及Linux内核如何通过分页机制管理和分配内存。


1. CPU的段寄存器中存放段选择符(六个段寄存器cs,ds,ss等),通过段选择符中的偏移量在段描述符表中找到所要访问内存的段描述符,在段描述符中找到相应段的段基地址;
2. 段基地址+(相加)逻辑地址(虚拟地址,指针)的偏移量=线性地址,线性地址经过页目录,页表转换成物理地址。

Intel用寄存器CR3存放当前使用的页目录的物理地址,从而可以实现到物理地址的转化。
系统中可以只有一个页目录,所有任务共享;也可以有多个页目录,每个任务一个,任务页目录的基址地址保存在任务的TSS段中(CR3域)
GDTR保存的是全局描述符表(GDT)的基地址,表长等GDT的信息,LDTR保存的是某个进程的局部描述符表的描述符的选择子(有点绕,也就是指向GDT中的某个LDT描述符)和对应描述符的内容(此内容不可见)。

http://www.kerneltravel.net/journal/v/mem.htm
Linux系统虽然保留了段机制,但是将所有程序的段地址都定死为0-4G,所以虽然逻辑地址和线性地址是两种不同的地址空间,但在Linux中逻辑地址就等于线性地址,它们的值是一样的

虚拟空间:

第一、4G的进程地址空间被人为的分为两个部分——用户空间与内核空间。用户空间从0到3G(0xC0000000),内核空间占据3G到4G。用户进程通常情况下只能访问用户空间的虚拟地址,不能访问内核空间虚拟地址。只有用户进程进行系统调用(代表用户进程在内核态执行)等时刻可以访问到内核空间。

第二、用户空间对应进程,所以每当进程切换,用户空间就会跟着变化;而内核空间是由内核负责映射,它并不会跟着进程改变,是固定的。内核空间地址有自己对应的页表(init_mm.pgd),用户进程各自有不同的页表。

第三、每个进程的用户空间都是完全独立、互不相干的。不信的话,你可以把上面的程序同时运行10次(当然为了同时运行,让它们在返回前一同睡眠100秒吧),你会看到10个进程占用的线性地址一模一样。

Linux内核管理物理内存是通过分页机制实现的,它将整个内存划分成无数个4k(在i386体系结构中)大小的页,从而分配和回收内存的基本单位便是内存页了。利用分页管理有助于灵活分配内存地址,因为分配时不必要求必须有大块的连续内存[3],系统可以东一页、西一页的凑出所需要的内存供进程使用。虽然如此,但是实际上系统使用内存时还是倾向于分配连续的内存块,因为分配连续内存时,页表不需要更改,因此能降低TLB的刷新率(频繁刷新会在很大程度上降低访问速度)。

鉴于上述需求,内核分配物理页面时为了尽量减少不连续情况,采用了“伙伴”关系来管理空闲页面。伙伴关系分配算法大家应该不陌生——几乎所有操作系统方面的书都会提到,我们不去详细说它了,如果不明白可以参看有关资料。这里只需要大家明白Linux中空闲页面的组织和管理利用了伙伴关系,因此空闲页面分配时也需要遵循伙伴关系,最小单位只能是2的幂倍页面大小。内核中分配空闲页面的基本函数是get_free_page/get_free_pages,它们或是分配单页或是分配指定的页面(2、4、8…512页)。

 注意:get_free_page是在内核中分配内存,不同于malloc在用户空间中分配,malloc利用堆动态分配,实际上是调用brk()系统调用,该调用的作用是扩大或缩小进程堆空间(它会修改进程的brk域)。如果现有的内存区域不够容纳堆空间,则会以页面大小的倍数为单位,扩张或收缩对应的内存区域,但brk值并非以页面大小为倍数修改,而是按实际请求修改。因此Malloc在用户空间分配内存可以以字节为单位分配,但内核在内部仍然会是以页为单位分配的。

创建进程fork()、程序载入execve()、映射文件mmap()、动态内存分配malloc()/brk()等进程相关操作都需要分配内存给进程。不过这时进程申请和获得的还不是实际内存,而是虚拟内存,准确的说是“内存区域”。进程对内存区域的分配最终都会归结到do_mmap()函数上来(brk调用被单独以系统调用实现,不用do_mmap()),

内核使用do_mmap()函数创建一个新的线性地址区间。但是说该函数创建了一个新VMA并不非常准确,因为如果创建的地址区间和一个已经存在的地址区间相邻,并且它们具有相同的访问权限的话,那么两个区间将合并为一个。如果不能合并,那么就确实需要创建一个新的VMA了。但无论哪种情况, do_mmap()函数都会将一个地址区间加入到进程的地址空间中--无论是扩展已存在的内存区域还是创建一个新的区域。

同样,释放一个内存区域应使用函数do_ummap(),它会销毁对应的内存区域。

 


TLB:转换旁视缓冲 (Translation Look-Aside Buffer)

一个常见的硬件缓冲,是处理器中的页表入口缓冲。处理器不总是直接读取页表而是在需要时缓存页面的转换。这种缓冲又叫做转换旁视缓冲(TLB),它包含系统中一个或多个处理器的页表入口的缓冲拷贝。当发出对虚拟地址的引用时,处理器试图找到相匹配的 TLB 入口。如果找到则直接将虚拟地址转换成物理地址并对数据进行处理。如果没有找到则向操作系统寻求帮助。处理器将向操作系统发出 TLB 失配信号,它使用一个特定的系统机制来将此异常通知操作系统。操作系统则为此地址匹配对产生新的 TLB 入口。当操作系统清除此异常时,处理器将再次进行虚拟地址转换。
 
Translation lookaside buffer
From Wikipedia, the free encyclopedia
Jump to: navigation, search
A Translation lookaside buffer (TLB) is a CPU cache that memory management hardware uses to improve virtual address translation speed. It was the first cache introduced in processors. All current desktop and server processors (such as x86) use a TLB. A TLB has a fixed number of slots that contain page table entries, which map virtual addresses to physical addresses. It is typically a content-addressable memory (CAM), in which the search key is the virtual address and the search result is a physical address. If the requested address is present in the TLB, the CAM search yields a match quickly, after which the physical address can be used to access memory. This is called a TLB hit. If the requested address is not in the TLB, the translation proceeds by looking up the page table in a process called a page walk. The page walk is a high latency process, as it involves reading the contents of multiple memory locations and using them to compute the physical address. Furthermore, the page walk takes significantly longer if the translation tables are swapped out into secondary storage, which a few systems allow. After the physical address is determined, the virtual address to physical address mapping and the protection bits are entered in the TLB.

<think>好的,用户现在遇到了两个问题:MySQL系统表损坏导致事件调度器无法启动,以及FUNC_NAME列的字符串编码错误。我需要结合之前的对话和用户提供的引用信息来给出解决方案。 首先,系统表损坏的问题。根据用户之前的回答,涉及到字符集设置和表修复。用户现在提到系统表损坏,可能需要修复mysql库中的系统表,比如event表。记得之前提到过使用REPAIR TABLE命令,但系统表可能需要特殊处理,比如在安全模式下启动或者使用mysql_upgrade工具。另外,用户提供的引用[1]提到临时表的问题,但这里可能不相关,不过需要注意在修复过程中是否有临时表影响操作。 然后是FUNC_NAME列的字符串编码错误。之前用户已经指导过修改字符集为utf8mb4,但现在问题依然存在,可能需要更彻底的检查,比如确认连接设置、客户端字符集是否一致,或者数据本身是否包含不正确的字符。用户提供的引用[2]中的错误如1060重复列名,可能与字符集转换时的冲突有关,但当前问题更可能是编码不一致导致的存储错误。 需要确保所有层面的字符集设置一致,包括数据库、表、列、连接参数和配置文件。同时,修复系统表可能需要停止服务器、使用特定命令或工具。此外,事件调度器无法启动可能与系统表损坏直接相关,修复表后可能需要重新启用事件调度器。 还需要考虑用户可能没有正确应用之前的解决方案,比如是否所有相关表都转换了字符集,或者是否有遗留的my.cnf配置未更新。可能还需要检查错误日志,获取更详细的错误信息,以确定具体的损坏原因。 最后,生成相关问题时要围绕系统表修复、事件调度器恢复、字符集深度处理等方面,帮助用户扩展解决可能的相关问题。</think>### 综合解决方案:系统表修复与字符编码修复 --- #### **一、系统表损坏导致事件调度器故障** 1. **定位损坏的系统表** - 检查`mysql.event`表状态(事件调度器依赖此表): ```sql CHECK TABLE mysql.event; ``` 若输出`Msg_text: Table is marked as crashed`或`Corrupt`,需立即修复[^1]。 2. **安全修复系统表** - **方法1**:通过`mysqlcheck`工具修复(需停止MySQL服务): ```bash mysqlcheck --repair --databases mysql --use-frm ``` - **方法2**:手动修复(紧急情况): ```sql REPAIR TABLE mysql.event USE_FRM; -- 仅当表结构未损坏时有效 ``` 3. **重启后验证事件调度器** ```sql SHOW VARIABLES LIKE 'event_scheduler'; -- 确保状态为ON SELECT * FROM mysql.event; -- 检查事件定义完整性 ``` --- #### **二、`FUNC_NAME`列字符编码错误** 1. **深度修复编码配置** - 修改列定义时**强制转换字符集**: ```sql ALTER TABLE your_table MODIFY FUNC_NAME VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci CONVERT TO CHARACTER SET utf8mb4; ``` 此操作会重写数据,修复截断的字符[^2]。 2. **修复已损坏的字符数据** - 使用`REPLACE`或`CONVERT`清理非法字符: ```sql UPDATE your_table SET FUNC_NAME = CONVERT(BINARY(CONVERT(FUNC_NAME USING latin1)) USING utf8mb4) WHERE FUNC_NAME LIKE '%\xE5%'; -- 匹配错误字符的十六进制值 ``` --- #### **三、联合修复操作流程** 1. **停止MySQL服务** ```bash systemctl stop mysql ``` 2. **配置文件更新** ```ini # /etc/my.cnf [mysqld] event_scheduler=ON # 确保事件调度器自动启用 character-set-server=utf8mb4 collation-server=utf8mb4_unicode_ci ``` 3. **启动服务并验证** ```bash systemctl start mysql mysql -e "SHOW ERRORS;" # 检查启动错误日志 ``` --- ### 关键原理 1. **系统表修复**:`mysql.event`存储事件定义,其损坏会导致调度器无法读取配置。`USE_FRM`模式通过表结构文件重建索引[^1]。 2. **编码修复**:`CONVERT TO CHARACTER SET`会重写数据页,修复因编码不一致导致的截断错误,尤其适用于多字节字符(如中文、Emoji)[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值