linux内核页表

2024-05-07 10:58
文章标签 linux 内核 页表

本文主要是介绍linux内核页表,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

曾 几何时,我一直被迷惑着,我知道所有进程和所有内核线程共享内核页表,也就是在页全局目录的768项以上的目录项指向的页表,我一直以为在创建新的进程的 时候创建新进程的页全局目录的时候会连带的把内核的基础全局目录复制过去,实际上这是合理的,当我看到网上很多文章都这么说时,我似乎感到一种欣慰:我太有才了!但是当我读到2.6.17的源代码时, 梦被打碎了,在pgd_alloc里面没有上述的动作,代码如下:

pgd_t *pgd_alloc(struct mm_struct *mm) 

int i
pgd_t *pgd = quicklist_alloc(0, GFP_KERNELpgd_ctor); 
if (PTRS_PER_PMD == 1 || !pgd) 
return pgd; 
for (i = 0; i < UNSHARED_PTRS_PER_PGD; ++i) { 
pmd_t *pmd = pmd_cache_alloc(i); 
if (!pmd) 
goto out_oom; 
paravirt_alloc_pd(__pa(pmd) >> PAGE_SHIFT); 
set_pgd(&pgd[i], __pgd(1 + __pa(pmd))); 

return pgd; 
out_oom: 
for (i--; i >= 0; i--) { 
pgd_t pgdent = pgd[i]; 
void* pmd = (void *)__va(pgd_val(pgdent)-1); 
paravirt_release_pd(__pa(pmd) >> PAGE_SHIFT); 
pmd_cache_free(pmd, i); 

quicklist_free(0, pgd_dtor, pgd); 
return NULL

我们看到,仅仅初始化了768之前的页目录项,没有内核页目录的踪迹,怎么回事呢?网上的那么多文章的依据又是什么呢?迷茫中,我想到了版本问题,于是我查阅了2.4的系列内核源代码,果然是那么回事: 
172 pgd_t *pgd_alloc(struct mm_struct *mm) 

int i
pgd_t *pgd = kmem_cache_alloc(pae_pgd_cachepGFP_KERNEL); 
if (pgd) { 
unsigned long pmd; 
for (i = 0; i < USER_PTRS_PER_PGDi++) { 
pmd = __get_free_page(GFP_KERNEL); 
if (!pmd) 
goto out_oom; 
clear_page(pmd); 
set_pgd(pgd + i__pgd(1 + __pa(pmd))); 

memcpy(pgd + USER_PTRS_PER_PGD
swapper_pg_dir + USER_PTRS_PER_PGD
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); 

return pgd; 
out_oom: 
for (i--; i >= 0; i--) 
free_page((unsigned long)__va(pgd_val(pgd[i])-1)); 
kmem_cache_free(pae_pgd_cachep, pgd); 
return NULL

看起来比2.6的内核长很多,这么做合理是合理,但是有必要吗?用户进程真的会那么频繁的进入内核从而访问内核吗?想想malloc库函数,再想想库提供用户io缓冲区,如果你没有研究过前面的两个,那么mmap总该知道吧,为什么要用到前面的库函数,而且他们的库级别实现非常复杂,有自己的一套策略,有何诱惑可以值得库设计者付出这么大的代价呢?究其原因就是为了尽可能少的进行系统调用从而进入内核空间,要知道计算机的目的是为人服务,为人服务就是运行用户的程序,也就是用户进程,并不是为了让人去研究操作系统,操作系统内核只是提供服务,进行全局统筹管理,遗憾的是,他和用户进程是共享 
处理器资源的,这就要求它必须在最短的时间内完成自己的任务,全程只需分清一个主次关系,用户进程为主,内核运行为辅,用户不求助,内核别插手用户事务,只有当用户真正要内核时,内核再挺身而出,这样就把内核事务拖到了不能再拖为止,于是乎再拷掠前面的问题时我想到了缺页中断,下面看看缺页中断是怎么处理的: 
asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) 

...... 
if (unlikely(address >= TASK_SIZE)) { 
if (!(error_code & 5)) 
goto vmalloc_fault; 
...... 
vmalloc_fault: 

...... 
int index = pgd_index(address);//得到缺页地址应该所在的页全局目录的目录项索引 
pgd_t *pgd, *pgd_k; 
pmd_t *pmd, *pmd_k; 
pte_t *pte_k; 
asm("movl %%cr3,%0":"=r" (pgd));//读出当前进程的页全局目录的位置 
pgd = index + (pgd_t *)__va(pgd);//得到具体的对应于缺页地址的目录项 
pgd_k = init_mm.pgd + index;//swapper_pgd_dir中队应的目录项 
if (!pgd_present(*pgd_k))//如果swapper_pgd_dir模板中都没有,准备后事吧 
goto no_context;//善后 
......
 
pmd = pmd_offset(pgd, address);//以下的分析方法同上 
pmd_k = pmd_offset(pgd_k, address); 
if (!pmd_present(*pmd_k)) 
goto no_context;//善后 
set_pmd(pmd, *pmd_k); 
pte_k = pte_offset_kernel(pmd_k, address);//内核和用户进程共享内核页表,因此以下也就没有set_pmd(pmd, *pmd_k)之类的了 
if (!pte_present(*pte_k)) 
goto no_context; 
return;//最终引起缺页的地址的MMU元素被创建,访问重新开始 


以上的分析应该很明了了,在此再小声说一句,网上的文章只是作者的理解,仅仅可以帮你理解问题,真正解决问题,你还得自己来,比如读内核,你必须自亲自阅读才能悟道。


注:本文中只关注kmalloc部分,不关注直接映射的部分,理解时应该从该角度理解;

来源:http://blog.csdn.net/dog250/article/details/5303051

这篇关于linux内核页表的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/967157

相关文章

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

Linux samba共享慢的原因及解决方案

《Linuxsamba共享慢的原因及解决方案》:本文主要介绍Linuxsamba共享慢的原因及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux samba共享慢原因及解决问题表现原因解决办法总结Linandroidux samba共享慢原因及解决

新特性抢先看! Ubuntu 25.04 Beta 发布:Linux 6.14 内核

《新特性抢先看!Ubuntu25.04Beta发布:Linux6.14内核》Canonical公司近日发布了Ubuntu25.04Beta版,这一版本被赋予了一个活泼的代号——“Plu... Canonical 昨日(3 月 27 日)放出了 Beta 版 Ubuntu 25.04 系统镜像,代号“Pluc

Linux安装MySQL的教程

《Linux安装MySQL的教程》:本文主要介绍Linux安装MySQL的教程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux安装mysql1.Mysql官网2.我的存放路径3.解压mysql文件到当前目录4.重命名一下5.创建mysql用户组和用户并修

Linux上设置Ollama服务配置(常用环境变量)

《Linux上设置Ollama服务配置(常用环境变量)》本文主要介绍了Linux上设置Ollama服务配置(常用环境变量),Ollama提供了多种环境变量供配置,如调试模式、模型目录等,下面就来介绍一... 目录在 linux 上设置环境变量配置 OllamPOgxSRJfa手动安装安装特定版本查看日志在

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

Linux系统之dns域名解析全过程

《Linux系统之dns域名解析全过程》:本文主要介绍Linux系统之dns域名解析全过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、dns域名解析介绍1、DNS核心概念1.1 区域 zone1.2 记录 record二、DNS服务的配置1、正向解析的配置