昨天回复了一封电子邮件,有朋友问个问题很有代表性,内核初始化时会将896M前的物理页面作一一映射,那么用户进程分配到896M前的页面建立用户映射时是否要清除内核的一一映射。
关于这个问题,我的前面的文章已经有了解释,但是不甚详细,现在通过一个例子详细解释一下。实际上并不需要清除内核的一一映射,内核的一一映射只有内核自己使用,而且带来了很多的方便,内核巧妙的通过一一映射快速的执行内核路径,其实内核的一一映射也只有内核自己知道,用户进程根本涉及不到,内核只要管理好自己的内存没有什么是不可以的。页面的页表映射是硬件MMU的机制,而OS内核中拥有的是内存管理机制,二者并不冲突,它们都是独立的机制,并且层次不同,完全可以独立存在,比如你可以在没有MMU的嵌入式设备上实现复杂的内存管理,同时你也可以在同一个硬件MMU下实现不同的内存管理,比如windows和linux的就不同,我的观点大致总结如下(缺漏的部分前面的文章中有):在linux中内核一般不会介入用户的策略,它只是提供机制,向上就到系统调用接口为止,它没有upcall接口;只要用户不会访问内核,内核不会随意访问用户内存就不会有冲突,用户是难缠的,而且行为是不确定的,内核的行为是确定的,用户显然不能访问内核内存,但是内核却可以访问用户内存,然而内核十分清楚自己拥有哪些内存,比如初始化的时候将896以下页面作了一一映射,可是内核不一定用得了那么多,当用户进程需要内存时,完全可以从还在伙伴系统的512M处拽一个页面分配之并且映射到用户空间同时保留着内核的一一映射,这时这个512M处的页面已经从伙伴系统脱离了,内核如果这时也需要内存是不会被分配到该页面的,这样就不会有冲突,如果该页面本来就由内核所使用,那么它就不会在伙伴系统也不可能分配到用户进程,这么来说也不会有冲突,linux的内存管理和硬件的 MMU是两码事,如果说有联系那就是映射,影射仅仅是一个纽带和一个适配器而已。
下面我就通过一个例子来说明,当然要写内核模块了,我的机器是512M内存,少于896M,也就是全部作了一一映射。我们首先执行以下命令得到insmod程序的一些信息,因为模块加载是在insmod进程的上下文中:
[root@zhaoya ~]#objdump -d /sbin/insmod
...
08048ab0 <.fini>:</.fini>
8048ab0: 55 push %ebp
8048ab1: 89 e5 mov %esp,%ebp
8048ab3: 53 push %ebx
...//0xcebe0000
我们看到进程地址空间0x8048ab3处是53,我们如果直接访问0x8048ab3,那么得到的就是53,这是显然的,但是我们还可以得到0x8048ab3所在页面的内核一一映射地址,然后访问那个地址看是不是还是53,如果是,那么就说明用户页面可能存在两份映射,接下来写一个模块:
#include <linux></linux>
#include <linux></linux>
#include <linux></linux>
#include <linux></linux>
#include <linux></linux>
#include <linux></linux>
static __init int test_init(void)
{
char * user_addr = (char *)0x8048ab3; //常规访问这个地址
printk("%x/n",*str);
struct page *page;
int n = get_user_pages(current, current->mm, user_addr, 1, 0, 1,&page,NULL);
printk("count:%d/n",n);
if(n>0)
{
unsigned long addr = page_address(page);
printk("address:%X/n",addr);
unsigned char * p = (unsigned char *)(address + user_addr&0xfff) ;//最后加入偏移
printk("%x/n",*p); //按照内核一一映射访问页面的内核地址
}
return 0;
}
static __exit void test_exit(void)
{
return ;
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Zhaoya");
MODULE_DESCRIPTION("kernel map");
MODULE_VERSION("Ver 0.1");
我们实在没有必要用cr3得到页目录,然后用二级或者三级乃至多级页面映射的方式去得到页面,那是非常复杂的,而且和体系结构相关,如果非要那样做的话首先你必须熟悉你的机器,其次还要熟悉C语言,幸运的是,内核提供了get_user_pages这个函数,我们可以轻而易举的根据虚拟地址得到页面。结果当然显而易见了,两次打印都是53,如果觉得不保险可以多试几个虚拟地址。
实际上一个页面保持多个映射并不是稀罕事,原因还是前面说的,内存管理和MMU管理是两码事。比如共享内存页面就可能保持多个映射。
分享到:
相关推荐
在IT领域,尤其是在系统安全和程序保护方面,"C++ x64内核保护进程源码"是一个重要的主题。这涉及到使用C++编程语言,在64位操作系统内核层面对进程进行保护的技术。下面我们将详细探讨这个主题的相关知识点。 1. *...
- **PCB(进程控制块)**:每个进程都有一个PCB,存储关于进程的重要信息,如身份信息(PID、UID、GID等)、状态信息、调度信息(优先级、实时优先级等)以及家族关系等。 - **进程的最大数量**:在较旧的内核版本...
这个压缩包包含了关于Linux内核的深入讲解,特别是关于进程管理和进程调度的内容。 首先,让我们从Linux内核的简介开始。Linux内核是由林纳斯·托瓦兹开发的开源操作系统内核,它遵循GNU General Public License,...
本资源主要介绍操作系统中进程内存初始化和页表建立的知识点,涵盖了虚拟内存映射结构、页表建立、进程内存管理等方面的内容。 一、虚拟内存映射结构 虚拟内存(Virtual Memory)是操作系统中的一种内存管理机制,...
其中,内核会在进程的虚拟空间查找一块连续的虚拟地址并把虚拟地址的起始和结束地址填充到VMA的vm_start和vm_end字段中,然后调用remap_pfn_range()在页表中建立物理地址与虚拟地址的映射关系。
首先,我们需要了解的是,每个进程都有其独立的地址空间,这是进程隔离的一个重要体现。在Linux中,地址空间分为用户空间和内核空间,它们通过系统调用进行交互。用户空间是应用程序执行代码和数据所在的区域,而...
Linux内核是操作系统的核心部分,负责管理系统...总的来说,Linux内核的结构和进程管理是其高效、灵活和可扩展性的基础,为用户提供了一个可靠的操作系统平台。理解和掌握这些概念对于系统管理员和开发者来说至关重要。
1. 内存保护:内核通过页表机制来隔离和保护进程的内存空间,防止一个进程非法访问或修改其他进程的内存。 2. 权限控制:在x64架构下,内核模式和用户模式的切换是通过特权环(Ring 0和Ring 3)实现的,确保只有...
当我们想要从内核空间修改一个进程的内存时,必须遵循一定的规则和方法。以下是一些关键知识点: 1. **进程地址空间的访问权限**:在用户空间,进程只能访问那些被标记为可读或可写的内存区域。而在内核空间,由于...
早先2.4版本的内核把所有可运行的进程连接在一个链表上,每次调度时都要循环遍历链表上的每一个进程,计算其优先级以决定选择哪一个进程运行。这种方法的扩展性不是很好,调度器选择一个可运行的进程的时间将随着...
Linux采用了一个体系结构无关的三级页表模型,以适应不同平台的需要。此外,Linux还巧妙地将中间目录(PMD)“折叠”到全局目录(PGD)中,以适应二级页表硬件。 #### TLB(Translation Lookaside Buffer) - **...
- **临时内核页表(Temporary Kernel Page Table)**:这是系统启动时使用的第一个页表。它包含了基本的内存映射,用于支持早期的系统初始化。 - **永久内核页表(Permanent Kernel Page Table)**:随着系统的...
每个进程都有自己的地址空间,内核通过页表机制管理这些空间,确保数据的隔离。进程切换由调度器控制,根据优先级和等待状态决定哪个进程获得CPU执行权。 三、内存管理 Windows内核内存管理的核心任务是分配和回收...
8. **内存保护**:恶意软件可能会利用NT内核的内存保护机制,如页表和内存权限设置,来保护其代码不被读取或修改。 尽管这些技术可以用于逃避杀毒软件的检测,但它们同时也违反了安全准则,可能导致系统不稳定或被...
内核空间包含内核代码、全局数据和设备驱动,用户空间则供用户进程使用。 7. vmalloc()内存特点:vmalloc()分配的内存地址连续,但物理地址不连续,适合需要大块连续虚拟地址但不关心物理连续性的场景。 8. malloc...
在Linux内核的早期版本中,0.11是一个重要的里程碑,它为后续版本的发展奠定了基础。通过注释这个早期版本的源代码,读者可以深入理解Linux内核的基本结构和工作流程。赵炯的注释详尽易懂,涵盖了内核的主要模块,如...
0 号进程是一个特殊的内核线程,其主要职责是初始化用户空间环境,为后续的用户进程提供必要的基础设施。创建 0 号进程的具体步骤如下: 1. **初始化内核数据结构**:包括进程控制块(PCB)、内核栈等。 2. **设置...
总之,突破Linux 2.2.x内核的进程数限制是一个涉及深入理解和调整内核层次结构的任务,包括进程调度、内存管理和硬件交互等方面。尽管存在挑战,但通过对现有内核的分析和改进,完全有可能在2.2.x内核上实现更高数量...