MST

星途 面试题库

面试题:C语言内存映射中内存保护机制的实现

在Linux C语言内存映射场景下,如何利用系统提供的机制实现对映射内存区域的读写保护?请描述相关的系统调用及代码实现思路,并说明这种保护机制在实际应用中的意义。
46.8万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

相关系统调用

  1. mmap:用于创建内存映射。其原型为:
    void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
    
    • prot参数用于指定映射区域的保护权限。常用的标志有:
      • PROT_READ:表示映射区域可读。
      • PROT_WRITE:表示映射区域可写。
      • PROT_EXEC:表示映射区域可执行。
    • 通过合理设置prot参数,可以控制对映射内存区域的读写权限。例如,若只想让映射区域可读,可设置protPROT_READ
  2. mprotect:用于修改已映射内存区域的保护权限。其原型为:
    int mprotect(void *addr, size_t len, int prot);
    
    • addr是映射区域的起始地址。
    • len是需要修改权限的区域长度。
    • prot是新的保护权限设置,与mmap中的prot参数类似。

代码实现思路

  1. 使用mmap创建内存映射并设置初始保护权限
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/mman.h>
    #include <sys/stat.h>
    #include <unistd.h>
    
    int main() {
        int fd = open("testfile", O_RDWR);
        if (fd == -1) {
            perror("open");
            return 1;
        }
    
        struct stat sb;
        if (fstat(fd, &sb) == -1) {
            perror("fstat");
            close(fd);
            return 1;
        }
    
        void *ptr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        if (ptr == MAP_FAILED) {
            perror("mmap");
            close(fd);
            return 1;
        }
    
        // 此时映射区域可读可写
    
        // 关闭文件描述符,因为内存映射已经建立
        close(fd);
    
  2. 使用mprotect修改保护权限
    // 假设要将映射区域改为只读
    if (mprotect(ptr, sb.st_size, PROT_READ) == -1) {
        perror("mprotect");
        munmap(ptr, sb.st_size);
        return 1;
    }
    // 此时映射区域变为只读,若尝试写入会触发SIGSEGV信号
    
    // 后续操作...
    
    // 解除映射
    if (munmap(ptr, sb.st_size) == -1) {
        perror("munmap");
        return 1;
    }
    return 0;
    }
    

实际应用中的意义

  1. 数据安全:防止程序意外或恶意地修改关键数据。例如,对于存储在内存映射文件中的配置信息,将其设置为只读可以避免程序运行过程中无意的修改,保证配置的稳定性和正确性。
  2. 内存隔离:在多进程或多线程环境中,通过设置不同的读写保护权限,可以实现内存区域的隔离。比如,共享内存区域对于某些进程或线程可以设置为只读,防止其对共享数据的误操作,确保数据的一致性。
  3. 程序健壮性:当程序尝试访问受保护的内存区域时,会触发信号(如SIGSEGV),程序可以捕获该信号并进行相应的错误处理,从而提高程序的健壮性和稳定性。