临时内核映射

临时内核映射与永久内核映射的区别是,临时内核映射可以在中断处理程序和可延迟函数内部使用,它不堵塞当前进程。

一 原理介绍

临时内核映射的线性地址在永久内核映射的后面,范围是[FIXADDR_START, FIXADDR_TOP),其基本逻辑是获取一个计数值n,用FIXADDR_TOP - n*4k 得到映射的线性地址。n不同,得到的线性地址也就不相同,内核是如何确保不同线程得到的n值不同的呢。

有两个措施:

1. 每cpu变量__kmap_atomic_idx (见kmap_atomic_idx_push函数)

对于每cpu变量__kmap_atomic_idx,每个cpu都维护着一个计数,比如cpu1保存的计数是3,而cpu2保存的计数是5。映射高端内存时,将计数加1,取消映射时,将计数减1。

假如一个线程运行在cpu1上,映射内存时计数加1,__kmap_atomic_idx的值变为4;另一个线程运行在cpu2上,映射内存后计数加1,__kmap_atomic_idx的值为6。

2. 每个cpu有KM_TYPE_NR个固定映射的线性地址

KM_TYPE_NR的值为20,即[0, 20),为第一个cpu的取值范围,[20, 40)为第二个cpu的取值范围,以此类推。

idx = type + KM_TYPE_NR*smp_processor_id();

 上面的逻辑可以参考下图

图1

二 临时内核映射代码 

有了上面的介绍后,下面看下临时内核映射的代码,kmap_atomic

static inline int kmap_atomic_idx_push(void)
{
	int idx = __this_cpu_inc_return(__kmap_atomic_idx) - 1;

	return idx;
}

void *kmap_atomic_prot(struct page *page, pgprot_t prot)
{
	unsigned long vaddr;
	int idx, type;

	preempt_disable();
	pagefault_disable();

	// 非高端内存,直接返回其线性地址
	if (!PageHighMem(page))
		return page_address(page);

	// 获取每cpu变量__kmap_atomic_idx的值,并将值加1
	type = kmap_atomic_idx_push();
	idx = type + KM_TYPE_NR*smp_processor_id();
	vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
	BUG_ON(!pte_none(*(kmap_pte-idx)));
    // 将页框添加到页表中
	set_pte(kmap_pte-idx, mk_pte(page, prot));
	arch_flush_lazy_mmu_mode();

	return (void *)vaddr;
}

void *kmap_atomic(struct page *page)
{
	return kmap_atomic_prot(page, kmap_prot);
}

kmap_atomic_prot中的idx即经过前面提到的两个措施后,得到的值。

获取线性地址vaddr时,FIX_KMAP_BEGIN是个枚举值,可参考enum fixed_addresses。

vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);

三 __fix_to_virt

__fix_to_virt的作用是将固定映射的一个值转成线性地址,其定义如下:

#define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))

32位系统地址空间如下图所示:

图2 

对于32位系统,FIXADDR_TOP为0xFFFFF000,即地址空间最后一个4K的起始地址

对于64位系统,FIXADDR_TOP为0xFFFFFFFF FF600000,也在线性地址空间最后的位置

x为0时, __fix_to_virt得到临时内核映射线性区最后一页的线性地址;x为1时,得到倒数第二页的线性地址,以此类推。

四 kmap_pte

kmap_pte的作用,与永久内核映射中的pkmap_page_table作用的一样的,也是指向一个页表。与pkmap_page_table不同的是,kmap_pte指向的是临时映射所用页表的结束位置。

set_pte(kmap_pte-idx, mk_pte(page, prot));

kmap_pte在kmap_init中初始化

static void __init kmap_init(void)
{
	unsigned long kmap_vstart;

	/*
	 * Cache the first kmap pte:
	 */
	kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
	kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
}

图3

kmap_vstart距离FIXADDR_TOP有 FIX_KMAP_BEGIN * 4K的,如上图所示,kmap_pte为kmap_vstart所在的页表。

五 kmap_get_fixmap_pte

调用kmap_get_fixmap_pte将kmap_vstart转换成kmap_pte。

static inline pte_t *kmap_get_fixmap_pte(unsigned long vaddr)
{
	pgd_t *pgd = pgd_offset_k(vaddr); // 页全局目录
	p4d_t *p4d = p4d_offset(pgd, vaddr);
	pud_t *pud = pud_offset(p4d, vaddr); // 页上级目录
	pmd_t *pmd = pmd_offset(pud, vaddr); // 页中间目录
	return pte_offset_kernel(pmd, vaddr); // 页表
}

六 kmap_atomic在内核中的应用

在一个函数中只调用一次kmap_atomic,如下所示:

void read_inline_data(struct page *page, struct page *ipage)
{
	struct inode *inode = page->mapping->host;
	void *src_addr, *dst_addr;

	if (PageUptodate(page))
		return;

	f2fs_bug_on(F2FS_P_SB(page), page->index);

	zero_user_segment(page, MAX_INLINE_DATA(inode), PAGE_SIZE);

	/* Copy the whole inline data block */
	src_addr = inline_data_addr(inode, ipage);
    // 映射
	dst_addr = kmap_atomic(page);
	memcpy(dst_addr, src_addr, MAX_INLINE_DATA(inode));
	flush_dcache_page(page);
    // 取消映射
	kunmap_atomic(dst_addr);
	if (!PageUptodate(page))
		SetPageUptodate(page);
}

映射后得到线性地址dst_addr,对线性地址进行操作,最后取消映射。

在一个函数中调用多次 kmap_atomic,看下面代码:

void copy_user_highpage(struct page *to, struct page *from,
	unsigned long u_vaddr, struct vm_area_struct *vma)
{
	void *kfrom = kmap_atomic(from);
	void *kto = kmap_atomic(to);
	int clean_src_k_mappings = 0;

	... ...

	kunmap_atomic(kto);
	kunmap_atomic(kfrom);
}

先映射from页框得到线性地址kfrom,再映射页框to得到线性地址kto。每调用一次kmap_atomic,运行此段代码的cpu保存的__kmap_atomic_idx就加1,因此最后得到的线性地址kfrom和ktto就不相同。

线性地址使用完毕后,调用kunmap_atomic取消映射,对应cpu保存的__kmap_atomic_idx的值也减1。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/406781.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Zookeeper分布式一致性协议ZAB源码剖析

Zookeeper分布式一致性协议ZAB源码剖析 ZAB协议 ZK的强一致性 ZK严格来讲并不是实时强一致性&#xff0c;而是写时强一致性&#xff0c;读时顺序一致性 ZAB协议(原子广播协议)&#xff0c;Paxos算法的一种简化实现&#xff0c;包括两种基本模式 消息广播 消息广播过程中使用类…

“IT行业职业发展的黄金之路:哪些证书能为你增光添彩?“

文章目录 每日一句正能量前言1、浙大计算机程序设计能力考试证书&#xff08;PAT&#xff09;2、全国计算机等级考试证书(NCRE)3、计算机技术与软件专业资格考试证书&#xff08;软考&#xff09;4、通信专业技术人员职业水平证书5、全国计算机应用水平考试证书&#xff08;NIT…

优秀实践| 运营商核心系统国产数据库迁移实践

作者介绍 陕西移动信息技术部 张云川 陕西移动信息技术部 王永强 新炬网络中北三部 张建 随着国家对自主可控战略的深入推进&#xff0c;笔者所在省份聚焦数据库国产化替换&#xff0c;全面加速数据库国产化替换进程。以核心系统带动周边系统&#xff0c;成功在能力运营中…

详解 CSS 的背景属性

详解 CSS 的背景属性 背景颜色 语法&#xff1a; background-color: [指定颜色]; 注&#xff1a;默认是 transparent (透明) 的&#xff0c;可以通过设置颜色的方式修改 示例代码: 运行效果: 背景图片 语法&#xff1a;background-image: url(...); url 可以是绝对路径 也可…

【Java程序设计】【C00284】基于Springboot的校园疫情防控管理系统(有论文)

基于Springboot的校园疫情防控管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的校园疫情防控系统 本系统分为系统功能模块、管理员功能模块以及学生功能模块。 系统功能模块&#xff1a;在系统首页可以查…

后端经典面试题合集

目录 1. Java基础1-1. JDK 和 JRE 和 JVM 分别是什么&#xff0c;有什么区别&#xff1f;1-2. 什么是字节码&#xff1f;采用字节码的最大好处是什么&#xff1f; 1. Java基础 1-1. JDK 和 JRE 和 JVM 分别是什么&#xff0c;有什么区别&#xff1f; JDK 是Java开发工具包&am…

使用 kind 集群安装运行极狐GitLab Runner【下】

GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 上一篇内容中&#xff0c;我们已经利用 kind 创建好了一个本地…

瑞_23种设计模式_装饰者模式

文章目录 1 装饰者模式&#xff08;Decorator Pattern&#xff09;1.1 介绍1.2 概述1.3 装饰者模式的结构 2 案例一2.1 需求2.2 代码实现 3 案例二3.1 需求3.2 代码实现 4 JDK源码解析5 总结5.1 装饰者模式的优缺点5.2 装饰者模式的使用场景5.3 装饰者模式 VS 代理模式 &#x…

Java日志技术

概况 把程序运行的信息&#xff0c;记录到文件中&#xff0c;方便程序员定位bug&#xff0c;并了解程序的执行情况等 什么是日志 好比生活中的日记&#xff0c;可以记录你生活中的点点滴滴程序中的日志&#xff0c;通常就是一个文件&#xff0c;里面记录的是程序运行过程中的…

第四十回 宋江智取无为军 张顺活捉黄文炳-使用python集合计算人员变动

白龙庙聚会&#xff0c;梁上好汉人多势众&#xff0c;听说江州城里军队追赶过来了&#xff0c;大家一起出去迎敌。李逵一马当先杀入人群&#xff0c;花荣一箭射倒领头的马军&#xff0c;其它马军掉头就走&#xff0c;把自己的步兵冲倒了一半。大家一直杀到江州城边&#xff0c;…

Android | ArcGIS入门

一、概述 ArcGIS是由Esri开发的地理信息系统&#xff08;GIS&#xff09;软件。它用于制图、空间分析和数据可视化。ArcGIS允许用户以各种格式创建、管理、分析和共享地理信息。它通常用于城市规划、环境管理和应急响应等领域。该软件包括一系列工具&#xff0c;用于创建地图、…

KTV点歌系统vue+springboot音乐歌曲播放器系统

目前现有的KTV点歌系统对于用户而言其在线点歌流程仍然过于繁琐&#xff0c;对于歌曲而言其系统安全性并不能保障。同时整套系统所使用的技术相对较为落后&#xff0c;界面不能动态化展示。相比较于其它同类型网站而言不能体现技术先进性。 1.2 项目目标 KTV点歌系统的后台开发…

C语言调试

目录 一.Debug和Release介绍 二.Windows环境调试介绍 三.窗口介绍 &#xff08;1&#xff09;自动窗口和局部变量窗口 &#xff08;2&#xff09;监视窗口 &#xff08;3&#xff09;调用堆栈 &#xff08;4&#xff09;查看汇编信息 &#xff08;5&#xff09;查看寄存…

Linux笔记之LD_LIBRARY_PATH详解

Linux笔记之LD_LIBRARY_PATH详解 文章目录 Linux笔记之LD_LIBRARY_PATH详解1.常见使用命令来设置动态链接库路径2.LD_LIBRARY_PATH详解设置 LD_LIBRARY_PATH举例注意事项 3.替代方案使用标准路径编译时指定链接路径优先使用 rpath 还是 runpath&#xff1f;注意事项 1.常见使用…

四信AI智能识别及计量监测设备,助力入河入海排污口规范化建设

随着城市化和工业化的快速发展&#xff0c;污水排放已成为主要的环境问题之一。2022年&#xff0c;国务院办公厅发布《关于加强入河入海排污口监督管理工作的实施意见》&#xff0c;提出“加强科技研发&#xff0c;开展各类遥感监测、水面航测、水下探测、管线排查等实用技术和…

Curator基本使用

文章目录 1. 基本操作1.1 建立连接1.2 创建结点1.3 查询结点查询数据查询子结点查看结点信息 1.4 修改结点普通修改带乐观锁的修改 1.5 删除删除单个结点删除带子结点的结点必须成功的删除带回调函数的删除 2. 监听器事件2.1 NodeCache单一结点连续监听2.2 PathChildrenCache监…

GEE入门篇|遥感专业术语(实践操作2):空间分辨率(Spatial Resolution)

目录 空间分辨率&#xff08;Spatial Resolution&#xff09; 1.MODIS&#xff08;搭载在Aqua 和 Terra 卫星上&#xff09; 2. TM&#xff08;搭载在早期LandSat卫星上&#xff09; 3.MSI&#xff08;搭载在在Sentinel-2 卫星上&#xff09; 4.NAIP 空间分辨率&#xff0…

基于qt的图书管理系统----03核心界面设计

参考b站&#xff1a;视频连接 源码github&#xff1a;github 目录 1 添加软件图标2 打包程序3 三个管理界面设计4 代码编写4.1 加载界面4.2 点击按钮切换界面4.3 组团添加样式4.4 搭建表头4.5 表格相关操作 从别人那里下载的项目会有这个文件&#xff0c;里边是别人配置的路径…

ETL:数据转换与集成的关键过程

ETL&#xff1a;数据转换与集成的关键过程 在现代数据驱动的世界中&#xff0c;有效地管理和处理数据对于企业的成功至关重要。ETL&#xff08;提取、转换、加载&#xff09;是一种关键的数据处理过程&#xff0c;有助于将数据从源系统提取、清洗、转换并加载到目标系统中&…

大蟒蛇(Python)笔记(总结,摘要,概括)——第9章 类

目录 9.1 创建和使用类 9.1.1 创建Dog类 9.1.2 根据类创建实例 9.2 使用类和实例 9.2.1 Car类 9.2.2 给属性指定默认值 9.2.3 修改属性的值 9.3 继承 9.3.1 子类的_init_()方法 9.3.2 给子类定义属性和方法 9.3.3 重写父类中的方法 9.3.4 将实例用作属性 9.3.5 模拟实物 9.…