linux系统编程--内存映射区概念及相应函数
程序员文章站
2022-06-20 14:26:27
...
0基本概念
1查看(系统的fifo文件):
- man shm_overview
- ls /dev/shm
2分类
- 内存映射文件
- 匿名内存映射(亲缘进程)
- 共享内存区对象(非亲缘进程)
3创建/打开文件int shm_open(const char *name, int oflag, mode_t mode)
3.1参数
参数 | 含义 |
---|---|
name | posix IPC名字,格式为/somename |
oflag | 标志 |
mode | 权限 |
3.2标志
标志 | 作用 |
---|---|
O_CREAT | 没有该对象则创建 |
O_EXCL | 如果O_CREAT指定,但name不存在,就返回错误 |
O_NONBLOCK | 以非阻塞方式打开消息队列 |
O_RDONLY | 只读 |
O_RDWR | 读写 |
O_WRONLY | 只写 |
O_TRUNC | 若存在则截断 |
3.3权限
权限 | 作用 |
---|---|
S_IWUSR | 用户/属主写 |
S_IRUSR | 用户/属主读 |
S_IWGRP | 组成员写 |
S_IRGRP | 组成员读 |
S_IWOTH | 其他用户写 |
S_IROTH | 其他用户读 |
3.5返回值
返回值 | 含义 |
---|---|
-1 | 出错 |
其他 | 共享内存描述符 |
示例
4删除int shm_unlink(const char *name)
4.1参数
参数 | 含义 |
---|---|
name | posix IPC名字 |
4.3返回值
返回值 | 含义 |
---|---|
-1 | 出错 |
0 | 成功 |
1mmap
1.1作用
- 将磁盘文件的数据映射到内存,用户通过修改内存就能修改磁盘文件
映射区就在动态库加载区,然后mmap函数将此盘中的file文件直接映射到映射区 这时候多个进程访问同一个逻辑内存,进程直接访问内存,不用read()/write()非常方便
1.2函数原型
void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset)
1.2.1权限
参数 | 含义 |
---|---|
PROT_EXEC | 页内容可以被执行 |
PROT_READ | 页内容可以被读取 这个权限必须要有 |
PROT_WRITE | 页可以被写入 |
PROT_NONE | 页不可访问,不能与文件的打开模式冲突 |
1.2.2 映射对象的类型
参数 | 含义 |
---|---|
MAP_SHARED | 变动共享 (修改了内存数据会同步到磁盘) |
MAP_PRIVATE | 变动私有(修改了内存数据不会同步到磁盘) |
MAP_ANON | 匿名内存映射(匿名内存映射(亲缘进程)) |
1.2.3fd文件描述符
- 磁盘中要映射文件的文件描述符。
- 得到方式:open()
1.2.4映射区大小
- 映射区的大小基本以4k的大小去增加,不能为零。
- 基本就是映射文件大小
1.2.5off_t offset
- 映射的时候文件指针的偏移量
- 必须是4k的整数倍
1.2.6返回值
返回值 | 含义 |
---|---|
MAP_FAILED | 失败 |
非MAP_FAILED | 共享内存地址 |
2munmap
int munmap(void *start,size_t length)
2.1 参数
-
start 映射内存起始地址 mmap的返回值
-
length 内存大小 mmap的第二个参数
返回值
No. 返回值 含义
1 0 成功
2 -1 失败
2.2 示例
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include<sys/mman.h>
int main(){
//打开一个文件
int fd =open("english.txt",O_RDWR);
int length=lseek(fd,0,SEEK_END);
//创建文件内存映射区
void *buf=mmap(NULL,length,PROT_READ,MAP_SHARED,fd,0);
if(MAP_FAILED==buf){
perror("nmap,error");
return 1;
}
printf("%s\n",(char *)buf);
munmap(buf,length);
return 0;
}
3文件控制
3.1获取文件信息int fstat(int fd,struct stat *buf)
3.1.1参数
参数 | 含义 |
---|---|
fd | 文件描述描述符 |
buf | struct stat |
3.1.2struct stat
No. 参数 | 含义 |
---|---|
st_mode | 权限 |
st_size | 大小 |
st_uid | 属主ID |
st_guid | 组ID |
3.1.3返回值
返回值 | 含义 |
---|---|
-1 | 出错 |
0 | 成功 |
3.1.4实例:获取文件大小
int fd=open(argv[optind],O_RDWR);
if(-1==fd){
perror("open error");
return 1;
}
struct stat st;
if(-1==fstat(fd,&st)){
perror("查看错误");
return 1;
}
printf("%s :size :%d\n",argv[optind],st.st_size);
return 0;
3.2修改文件大小int ftruncate(int fd, off_t length)
3.2.1参数
参数 | 含义 |
---|---|
fd | 文件描述描述符 |
length | 文件大小,如果原来的文件大小比参数length大,超过的部分删除。 |
3.2.2返回值
返回值 |含义
–|--
-1 |出错
0 | 成功
3.3.3实例:设置文件大小
if(-1==ftruncate(fd,new_size)){
perror("修改错误");
return 1;
}
if(-1==fstat(fd,&st)){
perror("查看错误");
return 1;
}
printf("%s :size :%d\n",argv[optind],st.st_size);
close(fd);
4mmap注意事项
-
如果对mmap的返回值buf进行++操作 munmap是否可以成功?
- 不能
- 可以 char *pt=buf; pt ++;
-
PROT_READ | PROT_WRITE什么意思?
- 相当于权限为两个权限参数集合
-
如果open的时候是O_CREAT,mmap时port参数指定PROT_READ | PROT_WRITE 时会怎样?
- 出现错误mmap调用失败 open文件指定权限应该大于等于mmap第三个参数port指定的权限
-
文件偏移量为1000时会怎麼样?
- 错误无效参数
-
mmap什么情况调用失败?:
- 第2个参数length=0;
- 第3个参数port必须有PROT_READ
- 第4个参数fd文件打开时的权限必须大于等于port
- 第5个参数必须时4k(4096)的整数倍
-
可以open的时候O_CREAT一个新文件来创建映射区吗?
- 可以 但是因为创建完后文件大小为0,需要做文件扩展lseek()truncate(path,length)
-
mmap后关闭文件描述符,对mmap有没有影响
- 没有
-
对buf越界操作会怎麼样:
- 此内存被占用->段错误
- 此内存没有被占用 写的数据无法映射到文件将丢失
上一篇: web开发之字体应用