面试题答案
一键面试相关系统调用
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
参数,可以控制对映射内存区域的读写权限。例如,若只想让映射区域可读,可设置prot
为PROT_READ
。
mprotect
:用于修改已映射内存区域的保护权限。其原型为:int mprotect(void *addr, size_t len, int prot);
addr
是映射区域的起始地址。len
是需要修改权限的区域长度。prot
是新的保护权限设置,与mmap
中的prot
参数类似。
代码实现思路
- 使用
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);
- 使用
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; }
实际应用中的意义
- 数据安全:防止程序意外或恶意地修改关键数据。例如,对于存储在内存映射文件中的配置信息,将其设置为只读可以避免程序运行过程中无意的修改,保证配置的稳定性和正确性。
- 内存隔离:在多进程或多线程环境中,通过设置不同的读写保护权限,可以实现内存区域的隔离。比如,共享内存区域对于某些进程或线程可以设置为只读,防止其对共享数据的误操作,确保数据的一致性。
- 程序健壮性:当程序尝试访问受保护的内存区域时,会触发信号(如
SIGSEGV
),程序可以捕获该信号并进行相应的错误处理,从而提高程序的健壮性和稳定性。