内存管理-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)    收藏  举报

导航