linux mem_map
时间: 2023-10-16 19:13:07 浏览: 55
在 Linux 中,`mem_map` 是一个指向物理内存页框描述符结构的指针数组,用于跟踪内核对物理内存的使用情况。每个物理内存页框都有一个对应的描述符结构。这个数组的每个元素都是一个 `struct page` 结构体,它包含了描述该页框的各种信息,如页框的状态、使用计数、属性等。这些信息可以帮助内核进行内存管理,如分配、释放、映射、缓存等操作。
当内核需要分配一块物理内存时,它会在 `mem_map` 中寻找一个未被占用的页框描述符结构。内核会将该页框描述符结构中的状态设置为已使用,同时返回该页框的虚拟地址,以便进程可以使用。当释放内存时,内核会将页框描述符结构的状态设置为未使用,以便下次可以再次使用。
总之,`mem_map` 是 Linux 内核用于管理物理内存的重要数据结构之一。
相关问题
linux mem_map报错undefined
`mem_map`是Linux内核中用于管理物理内存的数据结构之一,用于跟踪物理内存页面的使用情况。如果在使用`mem_map`时发生undefined错误,可能是由于未包含相应的头文件或未正确初始化该数据结构导致的。可以检查代码中是否包含了`<linux/mm.h>`头文件,并且确保在使用`mem_map`之前已经初始化了相关的数据结构。此外,也可以查看系统日志或调试信息以获取更多有关错误的信息。
此应用程序执行到最后会出现错误提示“trying to free free page”,这是由于sys_shmget函数在 使用get_free_page函数申请到一个物理页时,将此物理页在mem_map中记录的引用计数设置为1,而再次调 用sys_shmget函数使用key从vector中获取共享的物理页时,没有增加此物理页在mem_map中的引用计数。 所以,当生产者进程和消费者进程退出时,都会调用free_page函数释放此物理页,每调用一次就会将 mem_map中的引用计数减1,导致一个物理页的引用计数被减为了负数,这是Linux物理页管理程序所不允许 的,所以执行了mm/memory.c中free_page函数的最后一行(第310行)代码打印出错信息。请读者改进 sys_shmget函数,当能够使用key从vector中获取共享的物理页时,将此物理页在mem_map中的引用计数增 加1该如何修改。
可以在sys_shmget函数中找到使用get_free_page函数申请到一个物理页的代码,在此代码后面添加mem_map引用计数增加的代码即可。具体实现如下:
```C
unsigned long sys_shmget(key_t key, size_t size, int shmflg)
{
struct shmid_ds *buf;
struct shminfo *inf;
struct shm_file_data *shm_file;
struct page *page;
unsigned long addr;
int shmid, err, temp;
int i;
down(&shm_ids.sem);
// 查找 key 对应的共享内存是否已经存在
for (i = 0; i < SHM_NR; i++) {
if (shm_ids.used_ids[i] &&
shm_ids.shm_file[i]->key == key) {
shm_file = shm_ids.shm_file[i];
break;
}
}
// 如果 key 对应的共享内存不存在,就创建一个新的共享内存
if (i == SHM_NR) {
if (!(shmflg & IPC_CREAT)) { // 如果没有创建新的共享内存的权限
up(&shm_ids.sem);
return -EINVAL;
}
// 查找一个空闲的共享内存结构体
for (i = 0; i < SHM_NR; i++) {
if (!shm_ids.used_ids[i]) {
shm_file = kmalloc(sizeof(struct shm_file_data), GFP_KERNEL);
if (!shm_file) {
up(&shm_ids.sem);
return -ENOMEM;
}
// 申请一个物理页
page = get_free_page();
if (!page) {
up(&shm_ids.sem);
kfree(shm_file);
return -ENOMEM;
}
// 将物理页映射到内核空间
addr = (unsigned long) page_address(page);
if (!addr) {
up(&shm_ids.sem);
free_page((unsigned long) page);
kfree(shm_file);
return -ENOMEM;
}
// 初始化共享内存结构体
shm_file->key = key;
shm_file->page = page;
shm_file->attached = 0;
// 将共享内存结构体添加到 vector 中
temp = find_empty_slot();
if (temp == -1) {
up(&shm_ids.sem);
free_page((unsigned long) page);
kfree(shm_file);
return -EINVAL;
}
shm_ids.used_ids[temp] = 1;
shm_ids.shm_file[temp] = shm_file;
// 设置物理页在 mem_map 中的引用计数
atomic_inc(&mem_map[MAP_NR(page->phys_addr)].count);
buf = (struct shmid_ds *) getname(kernel_stack, (char *) arg2);
if (!buf) {
up(&shm_ids.sem);
free_page((unsigned long) page);
kfree(shm_file);
return -EFAULT;
}
// 初始化共享内存的元信息
buf->shm_nattch = 0;
buf->shm_page = page;
buf->shm_segsz = PAGE_SIZE;
putname((char *) arg2);
up(&shm_ids.sem);
return temp;
}
}
up(&shm_ids.sem);
return -EINVAL;
}
// 如果 key 对应的共享内存已经存在,就返回共享内存的编号
shmid = i;
shm_file = shm_ids.shm_file[shmid];
// 设置物理页在 mem_map 中的引用计数
atomic_inc(&mem_map[MAP_NR(shm_file->page->phys_addr)].count);
up(&shm_ids.sem);
return shmid;
}
```
在上述代码中,我们在申请到物理页后,添加了以下代码:
```C
// 设置物理页在 mem_map 中的引用计数
atomic_inc(&mem_map[MAP_NR(page->phys_addr)].count);
```
这样,在使用key从vector中获取共享的物理页时,就会增加此物理页在mem_map中的引用计数,从而避免了引用计数被减为负数的问题。
相关推荐
![rar](https://img-home.csdnimg.cn/images/20210720083606.png)
![docx](https://img-home.csdnimg.cn/images/20210720083331.png)
![doc](https://img-home.csdnimg.cn/images/20210720083327.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)
![](https://csdnimg.cn/download_wenku/file_type_ask_c1.png)