zram压缩机制看swapon系统调用
1.swapon开启zram交换分区
swapon /dev/block/zram0
mkswap /dev/block/zram0
上面命令调用了linux的swapon系统调用启动zram0交换分区;mkswap命令向块设备文件/dev/block/zram0写入了swap_header信息
问题:实际安卓平台是哪里触发swapon和mkswap调用的,我们已MTK8195平台为例:
init.xxx.rc:swapon_all /vendor/etc/fstab.enableswap其中fstab.enableswap内容如下:
/dev/block/zram0 none swap defaults zramsize=xx%
那么swapon_all命令执行了哪里的代码呢?又是哪里解析fstab.enableswap文件呢,答案是:
system/core/init/builtins.cpp:
/* swapon_all [ <fstab> ] */
static Result<void> do_swapon_all(const BuiltinArguments& args) {auto swapon_all = ParseSwaponAll(args.args);if (!swapon_all.ok()) return swapon_all.error();Fstab fstab;if (swapon_all->empty()) {if (!ReadDefaultFstab(&fstab)) {return Error() << "Could not read default fstab";}} else {if (!ReadFstabFromFile(*swapon_all, &fstab)) {return Error() << "Could not read fstab '" << *swapon_all << "'";}}if (!fs_mgr_swapon_all(fstab)) { return Error() << "fs_mgr_swapon_all() failed";}return {};
}
而fs_mgr_swapon_all实现:/system/core/fs_mgr/fs_mgr.cpp:
bool fs_mgr_swapon_all(const Fstab& fstab) {...const char* mkswap_argv[2] = {MKSWAP_BIN,entry.blk_device.c_str(),};int err = logwrap_fork_execvp(ARRAY_SIZE(mkswap_argv), mkswap_argv, nullptr, false,LOG_KLOG, false, nullptr);if (err) {LERROR << "mkswap failed for " << entry.blk_device;ret = false;continue;}/* If -1, then no priority was specified in fstab, so don't set* SWAP_FLAG_PREFER or encode the priority */int flags = 0;if (entry.swap_prio >= 0) {flags = (entry.swap_prio << SWAP_FLAG_PRIO_SHIFT) & SWAP_FLAG_PRIO_MASK;flags |= SWAP_FLAG_PREFER;} else {flags = 0;}err = swapon(entry.blk_device.c_str(), flags);if (err) {LERROR << "swapon failed for " << entry.blk_device;ret = false;}...
}
2.swapon系统调用
kernel-5.15/mm/swapfile.c
swapon(...) {swap_file = file_open_name(name, O_RDWR|O_LARGEFILE, 0);p->swap_file = swap_file;mapping = swap_file->f_mapping;dentry = swap_file->f_path.dentry;inode = mapping->host;/** Read the swap header.*/if (!mapping->a_ops->readpage) {error = -EINVAL;goto bad_swap_unlock_inode;}page = read_mapping_page(mapping, 0, swap_file);if (IS_ERR(page)) {error = PTR_ERR(page);goto bad_swap_unlock_inode;}swap_header = kmap(page);maxpages = read_swap_header(p, swap_header, inode);...nr_extents = setup_swap_map_and_extents(p, swap_header, swap_map, cluster_info, maxpages, &span);...error = init_swap_address_space(p->type, maxpages);...
}
上面代码read_mapping_page是能够读取内容的关键是mapping对象,因为mapping->aops有readpage函数,但是这里mapping和mapping->aops是什么时候设置的?先公布答案:mapping的aops指向的是def_blk_aops,定义在kernel-5.15/block/fops.c:
const struct address_space_operations def_blk_aops = { .set_page_dirty = __set_page_dirty_buffers,.readpage = blkdev_readpage,.readahead = blkdev_readahead,.writepage = blkdev_writepage,.write_begin = blkdev_write_begin,.write_end = blkdev_write_end,.writepages = blkdev_writepages,.direct_IO = blkdev_direct_IO,.migratepage = buffer_migrate_page_norefs,.is_dirty_writeback = buffer_check_dirty_writeback,
};
但是这是什么代码路径设置进去的呢?我们就以zram为例:一切要从blk_alloc_disk函数说起
zram_drv.c:
static int zram_add(void)
{struct zram *zram;int ret, device_id;zram = kzalloc(sizeof(struct zram), GFP_KERNEL);if (!zram)return -ENOMEM;ret = idr_alloc(&zram_index_idr, zram, 0, 0, GFP_KERNEL);if (ret < 0)goto out_free_dev;device_id = ret;init_rwsem(&zram->init_lock);
#ifdef CONFIG_ZRAM_WRITEBACKspin_lock_init(&zram->wb_limit_lock);
#endif/* gendisk structure */zram->disk = blk_alloc_disk(NUMA_NO_NODE);...
}__blk_alloc_disk(kernel-5.15/block/genhd.c)-->__alloc_disk_node(kernel-5.15/block/genhd.c)--->bdev_alloc(kernel-5.15/block/bdev.c)struct block_device *bdev_alloc(struct gendisk *disk, u8 partno)
{struct block_device *bdev;struct inode *inode;inode = new_inode(blockdev_superblock);if (!inode)return NULL;inode->i_mode = S_IFBLK;inode->i_rdev = 0;inode->i_data.a_ops = &def_blk_aops;mapping_set_gfp_mask(&inode->i_data, GFP_USER);bdev = I_BDEV(inode);mutex_init(&bdev->bd_fsfreeze_mutex);spin_lock_init(&bdev->bd_size_lock);bdev->bd_partno = partno;bdev->bd_inode = inode;bdev->bd_stats = alloc_percpu(struct disk_stats);if (!bdev->bd_stats) {iput(inode);return NULL;}bdev->bd_disk = disk;return bdev;
}
看到bdev_alloc可以看到inode->i_data.a_ops = &def_blk_aops就是设置的地方了。同时这里还生成了block_device,我们再看下block_device是怎么生成的!!!这里的关键是上面的new_inode调用到了哪里?答案:kernel-5.15/fs/inode.c:new_inode函数:
kernel-5.15/fs/inode.c:struct inode *new_inode(struct super_block *sb)
{struct inode *inode;spin_lock_prefetch(&sb->s_inode_list_lock);inode = new_inode_pseudo(sb);if (inode)inode_sb_list_add(inode);return inode;
}kernel-5.15/fs/inode.c:struct inode *new_inode_pseudo(struct super_block *sb)
{struct inode *inode = alloc_inode(sb);if (inode) {spin_lock(&inode->i_lock);inode->i_state = 0;spin_unlock(&inode->i_lock);INIT_LIST_HEAD(&inode->i_sb_list);}return inode;
}kernel-5.15/fs/inode.c:static struct inode *alloc_inode(struct super_block *sb)
{const struct super_operations *ops = sb->s_op;struct inode *inode;if (ops->alloc_inode)//调用对应的alloc_inode,我们分析的场景调用到了kernel-5.15/block/bdev.c:bdev_alloc_inodeinode = ops->alloc_inode(sb);elseinode = kmem_cache_alloc(inode_cachep, GFP_KERNEL);if (!inode)return NULL;//很重要的初始化函数:inode_init_alwaysif (unlikely(inode_init_always(sb, inode))) {if (ops->destroy_inode) {ops->destroy_inode(inode);if (!ops->free_inode)return NULL;}inode->free_inode = ops->free_inode;i_callback(&inode->i_rcu);return NULL;}return inode;
}
最终new_inode调用到了kernel-5.15/fs/inode.c:z的alloc_inode函数如下:
static struct inode *bdev_alloc_inode(struct super_block *sb)
{struct bdev_inode *ei = kmem_cache_alloc(bdev_cachep, GFP_KERNEL);if (!ei)return NULL;memset(&ei->bdev, 0, sizeof(ei->bdev));return &ei->vfs_inode;
}int inode_init_always(struct super_block *sb, struct inode *inode)
{static const struct inode_operations empty_iops;static const struct file_operations no_open_fops = {.open = no_open};struct address_space *const mapping = &inode->i_data;inode->i_sb = sb;inode->i_blkbits = sb->s_blocksize_bits;inode->i_flags = 0;atomic64_set(&inode->i_sequence, 0);atomic_set(&inode->i_count, 1);inode->i_op = &empty_iops;inode->i_fop = &no_open_fops;inode->i_ino = 0;inode->__i_nlink = 1;inode->i_opflags = 0;if (sb->s_xattr)inode->i_opflags |= IOP_XATTR;i_uid_write(inode, 0);i_gid_write(inode, 0);atomic_set(&inode->i_writecount, 0);inode->i_size = 0;inode->i_write_hint = WRITE_LIFE_NOT_SET;inode->i_blocks = 0;inode->i_bytes = 0;inode->i_generation = 0;inode->i_pipe = NULL;inode->i_cdev = NULL;inode->i_link = NULL;inode->i_dir_seq = 0;inode->i_rdev = 0;inode->dirtied_when = 0;...mapping->a_ops = &empty_aops;mapping->host = inode;
}
相关文章:
zram压缩机制看swapon系统调用
1.swapon开启zram交换分区 swapon /dev/block/zram0 mkswap /dev/block/zram0 上面命令调用了linux的swapon系统调用启动zram0交换分区;mkswap命令向块设备文件/dev/block/zram0写入了swap_header信息 问题:实际安卓平台是哪里触发swapon和mkswap调用的ÿ…...
SpringBoot2+Vue3开发博客管理系统
项目介绍 博客管理系统,可以帮助使用者管理自己的经验文章、学习心得、知识文章、技术文章,以及对文章进行分类,打标签等功能。便于日后的复习和回忆。 架构介绍 博客管理系统采用前后端分离模式进行开发。前端主要使用技术:Vu…...
JS【详解】Symbol (含Symbol 作为属性名,静态方法for 和 keyFor,11 个内置的 Symbol 值)
ES6 语法,表示唯一且不可变的值,常用作属性键值或者唯一标识符。 let a Symbol() let a Symbol(atomic symbol)console.log(Symbol() Symbol()) // false console.log(Symbol(atom) Symbol(atom)) // falseSymbol 作为属性名 let key Symbol(); le…...
Vue 项目运行时,报错Error: Cannot find module ‘node:path‘
Vue 项目运行时,报错Error: Cannot find module ‘node:path’ internal/modules/cjs/loader.js:883throw err;^Error: Cannot find module node:path Require stack: - D:\nodejs\node_modules\npm\node_modules\node_modules\npm\lib\cli.js - D:\nodejs\node_mo…...
综合评价 | 基于组合博弈赋权的物流系统综合评价(Matlab)
目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 综合评价 | 基于组合博弈赋权的物流系统综合评价(Matlab) 组合博弈赋权(Weighted Sum)是一种常见的多目标决策方法,用于将多个目标指标进行综合评估和权衡…...
国标GB28181视频汇聚平台EasyCVR安防监控系统常见播放问题分析及解决方法
国标GB28181安防综合管理系统EasyCVR视频汇聚平台能在复杂的网络环境中,将前端设备统一集中接入与汇聚管理。平台支持多协议接入,包括:国标GB/T 28181协议、GA/T 1400协议、RTMP、RTSP/Onvif协议、海康Ehome、海康SDK、大华SDK、华为SDK、宇视…...
30 哈希的应用
位图 概念 题目 给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何判断一个数是否在这40亿个整数中 1.遍历,时间复杂度O(N) 2.二分查找,需要先排序,排序(N*logN),二分查找,logN。…...
(笔记)Error: qemu-virgl: Failed to download resource “qemu-virgl--test-image“解决方法
错误: > Downloading https://www.ibiblio.org/pub/micro/pc-stuff/freedos/files/distributions/1.2/FD12FLOPPY.zip curl: (22) The requested URL returned error: 404Error: qemu-virgl: Failed to download resource "qemu-virgl--test-image" D…...
IntelliJ IDEA介绍
IntelliJ IDEA 是由 JetBrains 开发的一个集成开发环境 (IDE),专门为 Java 开发设计,同时也支持多种其他编程语言和框架。IntelliJ IDEA 以其智能代码分析、强大的重构功能以及丰富的插件生态系统而闻名,是许多开发者的首选 IDE。 IntelliJ IDEA介绍 IntelliJ IDEA 的主要…...
【office技巧】如何合并pdf并且添加目录页
所用工具:wps,acrobat reader 1.制作目录页 在wps里设置一级标题,二级标题,然后自动生成目录页,保存为pdf。 在acrobat reader里删除除了目录页之外的其他页面。 2.pdf合并 在acrobat reader里合并pdf。 注意有可能…...
Spring Boot中的安全性配置详解
Spring Boot中的安全性配置详解 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将深入探讨如何在Spring Boot应用中实现全面的安全性配置,保…...
数据权限和字段权限设计指南
数据权限和字段权限的设计是信息系统安全的基础。随着数据量的增加和用户需求的多样化,合理的权限设计变得愈加重要。本文将介绍数据权限和字段权限的基本概念、设计思路和实际应用,帮助读者建立全面的权限管理体系。 2. 数据权限设计 2.1 数据权限的定…...
Linux 常用命令之 RZ和SZ 简介
一、引言 在Linux系统管理中,尤其是在远程操作时,文件的上传与下载是常见的需求。对于CentOS用户而言,rz和sz这两个命令提供了简单而高效的文件传输方式,尤其在SSH终端环境中更为便利。本文将详细介绍rz和sz命令的基本概念、如何…...
Docker Compose:简化多容器管理的利器
在现代的应用开发和部署过程中,Docker已经成为不可或缺的工具。它通过容器化技术,使得应用的部署变得更加轻松和高效。然而,当我们需要管理和运行多个容器时,单纯依赖Docker命令行工具可能会显得繁琐且复杂。这时,Dock…...
深度解析:机器学习如何助力GPT-5实现语言理解的飞跃
文章目录 文章前言机器学习在GPT-5中的具体应用模型训练与优化机器翻译与跨语言交流:情感分析与问答系统:集成机器学习功能:文本生成语言理解任务适应 机器学习对GPT-5性能的影响存在的挑战及解决方案技术细节与示例 文章前言 GPT-5是OpenAI公…...
Springcloud-消息总线-Bus
1.消息总线在微服务中的应用 BUS- 消息总线-将消息变更发送给所有的服务节点。 在微服务架构的系统中,通常我们会使用消息代理来构建一个Topic,让所有 服务节点监听这个主题,当生产者向topic中发送变更时,这个主题产生的消息会被…...
js 接收回调函数 转换为promise
下面是一个示例代码,展示如何编写一个接收回调函数并将其转换为 Promise 的 JavaScript 函数: // 定义一个接收回调函数并转换为 Promise 的函数 function convertCallbackToPromise(callbackFunction) {// 返回一个新的 Promise 对象return new Promis…...
Python 面试【★★★】
欢迎莅临我的博客 💝💝💝,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…...
计算机网络(物理层)
物理层 物理层最核心的工作内容就是解决比特流在线路上传输的问题 基本概念 何为物理层?笼统的讲,就是传输比特流的。 可以着重看一下物理层主要任务的特性 传输媒体 传输媒体举例: 引导型传输媒体 引导型传输媒体指的是信号通过某种…...
OpenGL-ES 学习(6)---- 立方体绘制
目录 立方体绘制基本原理立方体的顶点坐标和绘制顺序立方体颜色和着色器实现效果和参考代码 立方体绘制基本原理 一个立方体是由8个顶点组成,共6个面,所以绘制立方体本质上就是绘制这6个面共12个三角形 顶点的坐标体系如下图所示,三维坐标…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...
【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)
服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...
深入理解JavaScript设计模式之单例模式
目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式(Singleton Pattern&#…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
C++ 求圆面积的程序(Program to find area of a circle)
给定半径r,求圆的面积。圆的面积应精确到小数点后5位。 例子: 输入:r 5 输出:78.53982 解释:由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982,因为我们只保留小数点后 5 位数字。 输…...
在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
AI病理诊断七剑下天山,医疗未来触手可及
一、病理诊断困局:刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断",医生需通过显微镜观察组织切片,在细胞迷宫中捕捉癌变信号。某省病理质控报告显示,基层医院误诊率达12%-15%,专家会诊…...
Netty从入门到进阶(二)
二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架,用于…...
【堆垛策略】设计方法
堆垛策略的设计是积木堆叠系统的核心,直接影响堆叠的稳定性、效率和容错能力。以下是分层次的堆垛策略设计方法,涵盖基础规则、优化算法和容错机制: 1. 基础堆垛规则 (1) 物理稳定性优先 重心原则: 大尺寸/重量积木在下…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
