如何使用内核模块直接访问保留内存?

smb*_*let 5 c linux memory-management linux-kernel

我试图将操作系统(Ubuntu Server 15.04)限制为特定的内存使用量并保留其余部分,但编写内核模块以读取/写入保留的内存。我想出了如何使用内核参数“mem=4G memmap=4G@0 memmap=4G$4G”(操作系统为 4GB,保留 4GB,在 4GB 点拆分)来限制使用/保留内存,但我不知道如何保留内存的 DMA 与内核模块一起使用。我想只创建一个 proc 文件,但我不确定您是否可以在操作系统分配的内存之外创建一个。

有什么建议?谢谢!

编辑:这是为了研究,所以它不需要“很好”

更新: 也许我不需要编写内核模块。我刚刚找到了这个,我打算试一试:http : //elinux.org/Memory_Management#Reserving_.28and_accessing.29_the_top_of_memory_on_startup

更新: 我尝试了上面的链接,但是每当我尝试编写时都会出现段错误。这是我的代码:

    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/mann.h>

    #define RESERVED_MEMORY_SIZE 0x100000000

    int main() {
            int fd;
            char *reserved_memory;

            fd = open("/dev/mem", O_RDWR | O_SYNC);
            reserved_memory = (char *) mmap(0, RESERVED_MEMORY_SIZE, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, 4096);
            reserved_memory[0] = 'a';
            return 0;
    }
Run Code Online (Sandbox Code Playgroud)

dmesg 显示:

    a.out[1167]: segfault at ffffffffffffffff ip 00000000004005d7 sp 00007ffeffccbd80 error 7 in a.out[400000+1000]
Run Code Online (Sandbox Code Playgroud)

对于踢球,我尝试了 reserved_memory[1]:

    a.out[1180]: segfault at 0 ip 00000000004005db sp 00007ffc388d77b0 error 6 in a.out[400000+1000]
Run Code Online (Sandbox Code Playgroud)

我将研究这些消息的格式,以便弄清楚它在告诉我什么。

更新:

我发现这个问题是由与我有相同问题的人提出的,但唯一的解决方案似乎是内核重建。我将尽量避免这种情况,所以也许我最好的选择是再次自定义内核模块。 访问 mmaped /dev/mem?

smb*_*let 4

好吧,所以我想我解决了。事实证明,我只是不明白 mmap 是如何工作的,而且我猜想如果 /dev/mem 位于保留内存中,内核对写入/读取 /dev/mem 没有限制。下面是两个程序,它们将写入我在内存中的保留位置并从中读取。

写“你好世界!”:

    #include <errno.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/mman.h>

    #define RESERVED_MEMORY_OFFSET  0x100000000     /* Offset is 4GB */

    int main() {
            int fd;
            char *reserved_memory;
            char *buffer = "Hello World!";

            fd = open("/dev/mem", O_RDWR | O_SYNC):
            /* Returns a pointer to the 4GB point in /dev/mem - the start of my reserved memory. Only mapping 4096 bytes. */
            reserved_memory = (char *) mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, RESERVED_MEMORY_OFFSET);
            if (reserved_memory == MAP_FAILED) {
                    printf("Failed to creating mapping.\n");
                    printf("ERRNO: %s\n", strerror(errno));
                    return -1;
            }
            sprintf(reserved_memory, "%s", buffer);
            return 0;
    }
Run Code Online (Sandbox Code Playgroud)

从保留内存的开头读取:

    #include <errno.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/mman.h>

    #define RESERVED_MEMORY_OFFSET  0x100000000     /* Offset is 4GB */

    int main() {
            int fd;
            char *reserved_memory;
            char buffer[13];

            fd = open("/dev/mem", O_RDWR | O_SYNC):
            /* Returns a pointer to the 4GB point in /dev/mem - the start of my reserved memory. Only mapping 4096 bytes. */
            reserved_memory = (char *) mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, fd, RESERVED_MEMORY_OFFSET);
            if (reserved_memory == MAP_FAILED) {
                    printf("Failed to creating mapping.\n");
                    printf("ERRNO: %s\n", strerror(errno));
                    return -1;
            }
            snprintf(buffer, 13, "%s", reserved_memory);
            printf("%s\n", buffer);
            return 0;
    }
Run Code Online (Sandbox Code Playgroud)

特别感谢@knm241!