mmap函数
1.内存映射方式来修改文件中的记录
1)解释部分
这段代码主要演示了如何使用内存映射方式来修改文件中的记录。具体来说,它的实现过程如下:
- 定义了一个存放记录的结构体
RECORD
,其中包含了记录的编号和内容。 - 创建了一个文件
records.dat
,并在其中写入测试数据。这些数据包含了50条记录,每条记录都有一个编号和内容,编号从0到49,内容为No.0
到No.49
。 - 使用传统的方式来修改文件中的记录。具体来说,先打开文件,并将文件指针定位到第10条记录的位置。然后从文件中读取该记录的内容,修改它的编号和内容,并将修改后的内容写回到文件中。最后关闭文件。
- 使用内存映射方式来修改文件中的记录。具体来说,先打开文件,并使用
mmap
函数将文件映射到内存中。然后直接在内存中修改第10条记录的内容,并使用msync
函数将修改后的内容异步写回到文件中。最后使用munmap
函数释放映射的内存段,并关闭文件。
需要注意的是,内存映射方式的修改过程相对来说更加高效,因为它不需要频繁地进行文件读写操作,而是直接在内存中修改数据。此外,由于内存映射方式可以将文件映射到多个进程的内存空间中,因此多个进程可以同时访问同一个文件,从而实现进程间的通信。
2)代码区
1 |
|
3)运行结果
2.使用内存映射的方式来操作一个文件
1)解释部分
这段代码主要演示了如何使用内存映射的方式来操作一个文件,将文件映射到内存中,然后读取或写入数据。
map_normalfile1.c:
- 定义了一个结构体
people
,它包含一个名字和一个年龄。 - 打开一个文件,使用
lseek
函数将文件大小扩展到people
结构体的大小的 5 倍,然后将指针移到文件末尾,写入一个空字符,这样就创建了一个大小为people
结构体大小的 5 倍的文件。 - 使用
mmap
函数将该文件映射到内存中,映射的大小为people
结构体大小的 10 倍。 - 使用
memcpy
函数将每个people
结构体的名字设置为一个字母,然后将年龄依次设置为 20 到 29。 - 程序等待 10 秒钟,然后使用
munmap
函数释放内存映射,并输出提示信息。
map_normalfile2.c:
- 定义了一个结构体
people
,它包含一个名字和一个年龄。 - 打开一个文件,使用
mmap
函数将该文件映射到内存中,映射的大小为people
结构体大小的 10 倍。 - 循环遍历每个
people
结构体,输出它的名字和年龄。 - 使用
munmap
函数释放内存映射。
这两段代码可以一起使用,先运行 map_normalfile1.c 将数据写入文件并映射到内存中,然后运行 map_normalfile2.c 从内存中读取数据并输出。通过这种方式,可以实现进程间的数据共享和通信。
2)代码区
1 |
|
1 |
|
3)运行结果
3.父子进程通过匿名映射实现共享内存
1)解释部分
这段代码演示了如何使用内存映射实现进程间通信,父进程和子进程可以通过共享内存来交换数据。
- 定义了一个结构体
people
,它包含一个名字和一个年龄。 - 使用
mmap
函数将一块共享内存映射到进程的地址空间中。这个共享内存的大小为people
结构体大小的 10 倍,标识为MAP_SHARED | MAP_ANONYMOUS
,表示该内存区域是可共享的,并且没有关联到任何文件。 - 创建一个子进程,子进程在两秒钟后读取共享内存中的前五个
people
结构体数据,并更新第一个people
结构体的年龄。然后释放共享内存并退出子进程。 - 父进程循环遍历前五个
people
结构体,将每个people
的名字设置为递增的字母,并将年龄设置为 20 到 24。然后等待 5 秒钟后读取共享内存中的第一个people
结构体,并输出它的年龄。最后释放共享内存并退出父进程。
通过共享内存来传递数据,可以避免复制数据的开销,提高程序的效率。但需要注意的是,在共享内存中操作数据时需要考虑同步和互斥,否则可能会发生数据竞争和死锁等问题。
2)代码区
1 |
|
3)运行结果
4.对mmap返回地址访问
1)解释部分
这段代码演示了如何使用 mmap()
函数创建一个映射文件,并在其中进行页级别的内存操作。
- 定义了一个结构体
people
,它包含一个名字和一个年龄。 - 使用
sysconf()
函数获取操作系统的页面大小,并输出。 - 使用
open()
函数创建一个新的文件,设置O_CREAT
标志表示如果文件不存在就创建它,设置O_RDWR
标志表示文件可读可写,设置O_TRUNC
标志表示清空文件内容。 - 使用
lseek()
函数设置文件偏移量为两页大小减去 100,然后使用write()
函数写入一个字节的空字符,以扩展文件大小为两页。 - 将
off
的值设置为一个页大小,表示将映射文件的第一个页保留不使用,而将后面的两页用于内存映射。 - 使用
mmap()
函数将映射文件的第二个页和第三个页映射到当前进程的地址空间中,并返回一个指向people
结构体数组的指针p_map
。设置MAP_SHARED
标志表示这是一个共享映射,即多个进程可以共同访问该映射区域。 - 在一个循环中,对于每两个页,分别访问该页的倒数第二个元素、倒数第一个元素和下一个页的第一个元素,并将它们的年龄设置为 100。在访问每个元素之后,程序会输出一条提示信息。
- 最后,使用
munmap()
函数释放映射内存,并关闭文件句柄。
该程序展示了如何使用 mmap()
函数将一个文件映射到内存中,并对映射内存进行操作。在这个例子中,程序通过映射文件的第二个页和第三个页,实现了页级别的内存操作,可以方便地进行内存分页相关的实验和研究。
2)代码区
1 |
|
mmap函数
https://ahaostillcoding.github.io/2023/04/24/mmap函数/