MST

星途 面试题库

面试题:C语言在Linux下内存映射基础

在Linux环境下使用C语言进行内存映射,简述mmap函数的主要参数及其作用。假设要将一个文件映射到内存中进行读写操作,给出基本的代码框架,并说明如何处理映射后的内存数据与文件的同步问题。
16.6万 热度难度
编程语言C

知识考点

AI 面试

面试题答案

一键面试

mmap函数主要参数及其作用

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);

  1. addr
    • 作用:指定映射区的起始地址,通常设为NULL,让内核自动选择合适的地址。如果不为NULL,则必须是页对齐的地址,并且在指定了MAP_FIXED标志时,内核将按照指定地址进行映射。
  2. length
    • 作用:指定映射区的长度,单位是字节。这个长度必须是系统页大小(通常是4096字节)的整数倍。
  3. prot
    • 作用:指定映射区的保护方式。常用值有:
      • PROT_READ:映射区可读。
      • PROT_WRITE:映射区可写。
      • PROT_EXEC:映射区可执行。
      • PROT_NONE:映射区不可访问。
  4. flags
    • 作用:指定映射的类型和其他选项。常用值有:
      • MAP_SHARED:共享映射,对映射区的修改会反映到文件中,同时其他进程对该文件的映射也能看到这些修改。
      • MAP_PRIVATE:私有映射,对映射区的修改不会反映到文件中,而是产生一个写时复制(copy - on - write)的副本。
      • MAP_FIXED:使用指定的addr地址进行映射,如果addr地址不合适,映射将失败。通常不建议使用,除非对内存布局非常清楚。
  5. fd
    • 作用:要映射的文件描述符,通过open函数打开文件获得。
  6. offset
    • 作用:文件映射的偏移量,必须是系统页大小的整数倍。通常设为0,表示从文件开头开始映射。

基本代码框架

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

int main() {
    int fd;
    struct stat sb;
    char *p;

    // 打开文件
    fd = open("test.txt", O_RDWR);
    if (fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    // 获取文件状态
    if (fstat(fd, &sb) == -1) {
        perror("fstat");
        close(fd);
        exit(EXIT_FAILURE);
    }

    // 内存映射
    p = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if (p == MAP_FAILED) {
        perror("mmap");
        close(fd);
        exit(EXIT_FAILURE);
    }

    // 对映射内存进行读写操作示例
    strcpy(p, "Hello, mmap!");

    // 解除映射
    if (munmap(p, sb.st_size) == -1) {
        perror("munmap");
        close(fd);
        exit(EXIT_FAILURE);
    }

    // 关闭文件
    if (close(fd) == -1) {
        perror("close");
        exit(EXIT_FAILURE);
    }

    return 0;
}

映射后内存数据与文件的同步问题

  1. 使用msync函数
    • 在使用MAP_SHARED映射时,如果需要确保映射内存中的数据被写回到文件,可以使用msync函数。其原型为int msync(void *addr, size_t length, int flags);
    • 参数
      • addr:映射内存区的起始地址,即mmap返回的地址。
      • length:要同步的内存区长度。
      • flags:常用标志有MS_SYNC(同步写回,等待写操作完成)、MS_ASYNC(异步写回,不等待写操作完成)、MS_INVALIDATE(使其他进程对该映射的缓存失效)。
    • 例如,在上述代码对映射内存进行写操作后,要将数据同步到文件,可以在munmap之前添加:
if (msync(p, sb.st_size, MS_SYNC) == -1) {
    perror("msync");
    exit(EXIT_FAILURE);
}
  1. 解除映射时
    • 当调用munmap解除映射时,如果映射类型是MAP_SHARED,系统通常会自动将映射内存中修改的数据写回到文件,但为了确保数据一致性,建议在munmap之前显式调用msync进行同步。