一、mmap设备操作
1、mmap系统调用
void *mmap(void * addr, size_t len, int prot, int flags, int fd, off_t offset)
返回值:内存映射的首地址(虚拟映射区首地址)。
功能:内存映射函数mmap,负责把文件内容映射到进程的虚拟内存空间,通过对这段内存的读取和修改(使用指针),来实现对文件的读取和修改,而不需要再调用read,write等操作。实际上内核和应用程序都是使用的虚拟地址,我们不会对物理地址直接操作,而是通过映射将物理地址转化为虚拟地址,然后对虚拟地址操作来实现对物理地址的操作。
参数:addr:指定映射的起始地址,通常设为NULL,由系统指定。
len:映射到内存的文件长度
prot:映射区的保护方式,可以是:
PROT_EXEC:映射区可被执行
PROT_READ:映射区可被读取
PROT_WRITE:映射区可被写入
flags:映射区的特性,可以是:
MAP_SHARED:写入映射区的数据会复制回文件,且允许其他映射该文件的进程共享。
MAP_PRIVATE:对映射区的写入操作会产生一个映射区的复制(copy-on-write),对此区域所做的修改不会写回原文件。
fd:由open返回的文件描述符,代表要映射的文件
offset:以文件开始处的偏移量,必须是分页大小的整数倍,通常为0,表示从文件头开始映射。
解除映射
int munmap(void *start, size_t length)
功能:取消参数start所指向的映射内存,参数length表示欲取消的内存大小。
返回值:解除成功返回0,否则返回-1,错误原因存于errno中。
实例分析:mmap系统调用
//printf输入输出函数需要的头文件
#include <stdio.h>
//open系统调用需要的头文件
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
//close需要的头文件
#include<unistd.h>
//mmap/munmap需要的头文件
#include<sys/mman.h>
//strcpy需要的头文件
#include<string.h>
int main()
{
int fd;
char *start;
char buf[100];
/*打开文件*/
fd = open("testfile",O_RDWR);
start=mmap(NULL,100,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0); //注意:mmap不会改变原有文件的长度,也就是说原有文件有多长,我们才能写入多长,多出来的部分,会被舍弃。
/* 读出数据 */
strcpy(buf,start);
printf("buf = %s\n",buf);
/* 写入数据 */
strcpy(start,"Buf Is Not Null!"); //mmap不会影响原有文件的长度;所以原来有多长,就会写入多长
munmap(start,100); /*解除映射*/
close(fd);
return 0;
}
2、虚拟内存区域
虚拟内存区域是进程的虚拟地址空间中的一个同质区间,即具有同样特性的连续地址范围。一个进程的内存映像由下面几个部分组成:程序代码、数据、BSS和栈区域,以及内存映射的区域。
一个进程的内存区域可以通过查看/proc/pid(1)/maps
001f6000-00231000 r-xp 00000000 fd:00 263878 /lib/libsepol.so.1
00231000-00232000 rw-p 0003a000 fd:00 263878 /lib/libsepol.so.1
00232000-0023c000 rw-p 00232000 00:00 0
0023e000-00253000 r-xp 00000000 fd:00 263879 /lib/libselinux.so.1
00253000-00255000 rw-p 00015000 fd:00 263879 /lib/libselinux.so.1
00451000-00452000 r-xp 00451000 00:00 0 [vdso]
009a2000-009bb000 r-xp 00000000 fd:00 263818 /lib/ld-2.5.so
009bb000-009bc000 r--p 00019000 fd:00 263818 /lib/ld-2.5.so
009bc000-009bd000 rw-p 0001a000 fd:00 263818 /lib/ld-2.5.so
每一行的域为:
start_end perm offset major:minor inode
start:该区域起始虚拟地址
end:该区域结束