C语言使用mmap函数写入内存
在本文中,我们将学习 mmap()
函数,它需要多少个参数,以及如何在 C 编程中使用 mmap() 写入内存。
C 中的 mmap() 函数
我们使用这个函数来映射进程地址空间和设备或文件。 mmap()
函数请求内存 n 字节的可写匿名和私有映射。
匿名映射和私有映射意味着它不受文件支持,也不与其他进程共享。 要使用 mmap()
,我们必须包含头文件。
#include <sys/mman.h>
It takes six arguments:
void * mmap (
void *address,
size_t length,
int protect,
int flags,
int filedes,
off_t offset
)
在开始使用这个函数之前,让我们讨论一下参数。
-
address - 它提供用于映射的首选起始地址。 如果没有其他映射,内核将选择附近的页面边界,创建一个映射。
否则,内核将选择新地址。 如果此参数的值为 NULL,则内核会将映射放置在它认为合适的位置。
- length - 映射的字节数。
- protect - 它控制允许什么类型的访问。 例如,用于读访问的 PROT_READ,用于写访问的 PROT_WRITE,以及用于执行的 PROT_EXEC。
-
flags - 用于控制地图的性质。 下面列出了一些常见和有用的标志:
- MAP_SHARED - 与其他进程共享映射。
- MAP_FIXED - 系统被迫使用通过地址参数给出的相同映射地址。
- MAP_ANONYMOUS / MAP_ANON - 它创建匿名映射。
- MAP_PRIVATE - 映射将是私有的,并且在使用此标志时对其他人不可见。
- filedes - 应该映射文件描述符。
- offset - 文件映射从这个偏移量开始。
如果 mmap()
成功运行,我们会得到 0。 否则,返回 MAP_FAILED。
C语言使用mmap()写入内存
让我们通过练习不同的例子来理解 mmap()。
示例代码(用于内存分配):
#include <stdio.h>
#include <sys/mman.h>
int main(){
int N=5;
int *ptr = mmap ( NULL, N*sizeof(int),
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS,
0, 0 );
if(ptr == MAP_FAILED){
printf("Mapping Failed\n");
return 1;
}
for(int i=0; i<N; i++)
ptr[i] = i*10;
for(int i=0; i<N; i++)
printf("[%d] ",ptr[i]);
printf("\n");
int err = munmap(ptr, 10*sizeof(int));
if(err != 0){
printf("Unmapping Failed\n");
return 1;
}
return 0;
}
输出:
[0] [10] [20] [30] [40]
我们使用 mmap()
函数来分配内存,在分配时我们使用 PROT_READ | PROT_WRITE
保护来对映射区域进行读写操作。
我们使用 MAP_PRIVATE 标志是因为我们不想与其他进程共享映射区域,而使用 MAP_ANONYMOUS 是因为我们还没有映射文件。
出于同样的原因,文件描述符和偏移量被设置为 0。
示例代码(用于进程间通信):
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/mman.h>
int main(){
int Number=5;
int *ptr = mmap(NULL,Number*sizeof(int),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS,
0,0);
if(ptr == MAP_FAILED){
printf("Mapping Failed\n");
return 1;
}
for(int i=0; i < Number; i++){
ptr[i] = i + 7;
}
printf("Initial array's values:");
for (int i = 0; i < Number; i++ ){
printf(" %d", ptr[i] );
}
printf("\n");
pid_t child_pid = fork();
if ( child_pid == 0 ){
//child
for (int i = 0; i < Number; i++){
ptr[i] = ptr[i] * 5;
}
}else{
//parent
waitpid ( child_pid, NULL, 0);
printf("\nParent:\n");
printf("Updated array's values:");
for (int i = 0; i < Number; i++ ){
printf(" %d", ptr[i] );
}
printf("\n");
}
int err = munmap(ptr, Number*sizeof(int));
if(err != 0){
printf("Unmapping Failed\n");
return 1;
}
return 0;
}
输出:
Initial array's values: 7 8 9 10 11
Initial array's values: 7 8 9 10 11
Parent:
Updated array's values: 35 40 45 50 55
我们最初用一些值初始化数组。 然后,孩子的过程改变了价值观。
此外,值由父进程读取,子进程更改了这些值,因为映射内存正在与两个(子进程和父进程)共享。 我们还使用 munmap()
来删除内存映射。
相关文章
在 C 语言中使用 typedef enum
发布时间:2023/05/07 浏览次数:181 分类:C语言
-
本文介绍了如何在 C 语言中使用 typedef enum。使用 enum 在 C 语言中定义命名整数常量 enum 关键字定义了一种叫做枚举的特殊类型。
C 语言中的 extern 关键字
发布时间:2023/05/07 浏览次数:114 分类:C语言
-
本文介绍了如何在 C 语言中使用 extern 关键字。C 语言中使用 extern 关键字来声明一个在其他文件中定义的变量
C 语言中的 #ifndef
发布时间:2023/05/07 浏览次数:186 分类:C语言
-
本文介绍了如何在 C 语言中使用 ifndef。在 C 语言中使用 ifndef 保护头文件不被多次包含 C 语言中的头文件用于定义同名源文件中实现的函数的接口。