内存管理-43-Swap-1-命令行工具实现
一、mkswap
基于 A13 + msm-5.4
1. 简介
源码位置: /android/external/toybox/toys/other/mkswap.c
该命令对要成为swap后端的设备的首页写一些格式化的内容(也就意味着用于swap的少一页),没有调用swap相关系统调用。
使用:
/ # mkswap --help Toybox 0.8.4-android multicall binary: https://landley.net/toybox (see toybox --help) usage: mkswap [-L LABEL] DEVICE Set up a Linux swap area on a device or file.
2. 用户空间实现
void mkswap_main(void) { /* (1) 以可读写方式打开目标设备/文件(参数 DEVICE), *toys.optargs 应该是参数如“/dev/block/zram0” */ int fd = xopen(*toys.optargs, O_RDWR), pagesize = sysconf(_SC_PAGE_SIZE); /* (2) 获取目标总长度(普通文件走 st_size,块设备优先走 ioctl(fd, BLKGETSIZE64, &size)), 可对块设备的fd进行ioctl#### */ off_t len = fdlength(fd); /* (3) 计算可用于 swap 的页数: pages = 总页数 - 1(预留首页用于 swap header 等元数据) */ unsigned int pages = (len / pagesize) - 1; /* (4)) toybuf 作为临时 header 缓冲区,按 unsigned int 为单位写入 */ unsigned int*swap = (unsigned int *)toybuf; /* (5) header 内部偏移: uuid 起始在 swap+3,label 起始在 swap+7 */ char *label = (char *)(swap+7), *uuid = (char *)(swap+3); /* * 写入头部。请注意,旧版本的内核在交换过程中会检查磁盘上的签名(而不是缓存中的签名), * 因此写入后需要进行同步。 * * (6) 填写 header 关键字段 * swap[0] = version(1) * swap[1] = 总页数 - 1 */ swap[0] = 1; swap[1] = pages; /* (7) 跳到 1024 偏移写 header(兼容传统 swap header 布局) */ xlseek(fd, 1024, SEEK_SET); /* (8) 生成 UUID(RFC4122 v4 风格随机 UUID) */ create_uuid(uuid); /* (9) 若指定 -L,还可以在mkswap时写入最多 15 个字符的标签 */ if (TT.L) strncpy(label, TT.L, 15); /* (10) 在偏移1024位置写 header(129 个 unsigned int) */ xwrite(fd, swap, 129 * sizeof(unsigned int)); /* (11) 跳到第一页末尾写签名字符串 “SWAPSPACE2”, 这是内核 swapon 校验 swap 区是否合法的关键 #### */ xlseek(fd, pagesize - 10, SEEK_SET); xwrite(fd, "SWAPSPACE2", 10); /* (12) 强制落盘(旧内核在 swapon 时会直接检查磁盘内容) */ fsync(fd); /* 此宏为0,不执行#### */ if (CFG_TOYBOX_FREE) close(fd); /* (13) 组织输出信息(大小、label、UUID) */ if (TT.L) sprintf(toybuf, ", LABEL=%s", label); else *toybuf = 0; printf("Swapspace size: %luk%s, UUID=%s\n", pages * (unsigned long)(pagesize/1024), toybuf, show_uuid(uuid)); }
3. 内核空间实现
不涉及。
4. 实验
4.1 file-swap
/ # dd if=/dev/zero of=/data/vendor/swap/swapfile bs=1m count=200 200+0 records in 200+0 records out 209715200 bytes (200 M) copied, 0.276512 s, 723 M/s / # / # mkswap /data/vendor/swap/swapfile Swapspace size: 204796k, UUID=54b045bd-2b52-430b-8dda-04a7946ae4b2 / # / # swapon /data/vendor/swap/swapfile -p 32759 / # cat /proc/swaps Filename Type Size Used Priority /dev/block/zram0 partition 6291452 723888 32758 /data/vendor/swap/swapfile file 204796 0 32759 / # / # swapoff /data/vendor/swap/swapfile //这样可以关闭 / # cat /proc/swaps Filename Type Size Used Priority /dev/block/zram0 partition 6291452 811068 32758
4.2 zram-swap
/ # swapoff /dev/block/zram0 / # cat /proc/swaps Filename Type Size Used Priority / # / # mkswap /dev/block/zram0 Swapspace size: 6291452k, UUID=c90e5ef6-2bde-40eb-9f7b-86dd027628a7 / # / # swapon /dev/block/zram0 -p 32758 / # cat /proc/swaps Filename Type Size Used Priority /dev/block/zram0 partition 6291452 0 32758
5. 小结
(1) swap可用空间大小是指定大小减去1个page=4k的大小。
二、swapon
1. 简介
启用swap后端设备。
源码位置: /android/external/toybox/toys/other/swapon.c
用法:
/ # swapon --help Toybox 0.8.4-android multicall binary: https://landley.net/toybox (see toybox --help) usage: swapon [-d] [-p priority] filename Enable swapping on a given device/file. -d Discard freed SSD pages -p Priority (highest priority areas allocated first)
-p指定优先级,高优先级设备被优先使用。
2. 用户空间实现
void swapon_main(void) { /* 0x70000 = SWAP_FLAG_DISCARD|SWAP_FLAG_DISCARD_ONCE|SWAP_FLAG_DISCARD_PAGES */ int flags = (toys.optflags&FLAG_d)*0x70000; /* 若指定了-p优先级参数(0..32767),flags参数或上 0x8000 | <prio> << 0 */ if (toys.optflags) flags |= SWAP_FLAG_PREFER | (TT.p << SWAP_FLAG_PRIO_SHIFT); /* 调用swapon系统调用 */ if (swapon(*toys.optargs, flags)) perror_exit("Couldn't swapon '%s'", *toys.optargs); }
3. 内核空间实现
对应系统调用:
SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags) //mm/swapfile.c
TODO
4. 实验
见上面 mkswap 命令的实验。
三、swapoff
1. 简介
关闭swap后端设备。
源码位置: android/external/toybox/toys/other/swapoff.c
/ # swapoff --help Toybox 0.8.4-android multicall binary: https://landley.net/toybox (see toybox --help) usage: swapoff swapregion Disable swapping on a given swapregion.
2. 用户空间实现
void swapoff_main(void) { if (swapoff(toys.optargs[0])) perror_exit("failed to remove swaparea"); }
3. 内核空间实现
系统调用:
SYSCALL_DEFINE1(swapoff, const char __user *, specialfile) //mm/swapfile.c
TODO
4. 实验
见上面 mkswap 命令的实验。
posted on 2026-03-31 11:29 Hello-World3 阅读(0) 评论(0) 收藏 举报
浙公网安备 33010602011771号