用mychar驱动吃掉所有内存

-- TOC --

mychar驱动通过ioctl可以无限申请内容,根据LDD3的精神,写一个尽可能吃掉内存的小程序。

先用C写一个按指定设备和大小吃内存的小程序,每次吃固定大小内存:

$ cat eat_mem.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <sys/ioctl.h>
#include "mychar.h"


#define ERRBUF_SIZE 32
#define _PERROR \
    do { \
        char errbuf[ERRBUF_SIZE] = {0}; \
        sprintf(errbuf, "%s:%d", __FILE__, __LINE__); \
        perror(errbuf); \
    } while(0) \


int main(int argc, char **argv) {
    int fd, cnt;
    unsigned long length = 0;
    assert(argc == 3);

    if ((fd=open(argv[1],O_RDONLY)) == -1) {
        _PERROR;
        return errno;
    }

    length = atoi(argv[2]);
    if ((cnt=ioctl(fd,MYCHAR_IOC_AM,&length)) == -1) {
        _PERROR;
        return errno;
    }

    fprintf(stdout, "%d", cnt);
    return 0;
}
$ gcc -Wall -Wextra -I/home/xinlin/sources/linux-5.14.14/include eat_mem.c -o eat_mem

这段C代码的一个限制是ioctl的返回值只能是int,但是驱动mychar_ioctl的返回确实long型。

下面是python主程序,在命令行指定一个要吃掉的内存总大小,然后python脚本会在错误发生时,不断缩小每次申请的内存大小来尝试,直到每次申请的数量小于4K,或者满足要求,如果第2个参数是freeall,释放所有申请内存:

$ cat eat_mem.py
import sys
import subprocess
from fcntl import ioctl


MYCHAR_IOC_FALL = 0x5A09


if sys.argv[2] == 'freeall':
    with open(sys.argv[1]) as f:
        ioctl(f, MYCHAR_IOC_FALL)
    sys.exit(0)


left = int(sys.argv[2])
eat = 0
piece = 1024*1024*100
while left > eat:
    cmd = f'./eat_mem {sys.argv[1]} {piece}'
    proc = subprocess.run(cmd.split(),
                          stdout=subprocess.PIPE,
                          stderr=subprocess.STDOUT)
    if proc.returncode != 0 and piece < 4096:
        print('eat: %dM' % (eat/1024/1024))
        print('last eat_mem return code: ', proc.returncode)
        sys.exit(proc.returncode)
    elif proc.returncode != 0:
        piece //= 2
        print('try piece: %dB, %fM' % (piece,piece/1024/1024))
    else:
        eat += piece


print('eat: %dM' % (eat/1024/1024))

加载mychar驱动后,用watch free -h持续观察内存,测试的命令行如下:

$ sudo python3 eat_mem.py mychar-5 $((1024*1024*1024))  # eat 1G
try piece: 52428800B, 50.000000M
try piece: 26214400B, 25.000000M
try piece: 13107200B, 12.500000M
try piece: 6553600B, 6.250000M
try piece: 3276800B, 3.125000M
try piece: 1638400B, 1.562500M
try piece: 819200B, 0.781250M
try piece: 409600B, 0.390625M
try piece: 204800B, 0.195312M
try piece: 102400B, 0.097656M
try piece: 51200B, 0.048828M
try piece: 25600B, 0.024414M
eat: 1024M
$ free -h
              total        used        free      shared  buff/cache   available
Mem:          1.8Gi       1.7Gi        69Mi       0.0Ki        81Mi        36Mi
Swap:         1.8Gi       456Mi       1.4Gi
$ sudo python3 eat_mem.py mychar-5 freeall
$ free -h
              total        used        free      shared  buff/cache   available
Mem:          1.8Gi       458Mi       1.3Gi       0.0Ki        88Mi       1.3Gi
Swap:         1.8Gi       461Mi       1.4Gi

用来创造一个低内存环境,但我还不知道用来测什么~~!

本文链接:https://cs.pynote.net/sf/linux/dd/202201072/

-- EOF --

-- MORE --