Linux内核多大 包含所有驱动,Linux 内核驱动中申请大块内存

本文介绍了一种在Linux内核中管理大内存的方法,针对kmalloc无法满足的大内存需求,提供了一套自定义的内存管理方案。该方案能够有效地管理更大的内存区域,并通过实例代码展示了如何实现这一功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在linux的内核模块中要申请内存,一般都是使用kmalloc的方式申请一块指定大小的内存,但这个函数有一定的限制,一般只能申请到几M到十几M的内存空间,申请内存太多将会失败。这样的限制是好的,保证具有完全权限的内核程序不会无意地过度浪费内存资源(例如通过变量a进行kmalloc(a),但因为程序员的问题,导致a是一个非常大的数字,如果不限制就会因为内存不足就导致内核崩溃了。),如果要进行DMA操作,使用几M的内存已经能达到很好的效率。

但是肯定有在内核中使用超大块内存的情况,例如vmware,它可以预分配虚拟机的所有内存。这时候,就应该自己去按页分配并自己进行页管理。

这里有一个我以前写的内核中大型内存数组管理函数,提供给大家参考参考。没有写太多的注释,仅供有兴趣的参考哈

kvector.h

#ifndef _HOVERLEES_KVECTOR_H

#define _HOVERLEES_KVECTOR_H

#include

#define ELEMENT_LENGTH8

#define INDEX_LINK_EACH_NUM (PAGE_SIZE/sizeof(void*)-1)

#define ELEMENTS_PER_PAGE PAGE_SIZE/ELEMENT_LENGTH

typedef struct _index_link_node{

void* data_pages[INDEX_LINK_EACH_NUM];

struct _index_link_node * next;

}index_link_node;

typedef struct _kvector{

int size;

int current_index_pos;

int total_index_elements;

int index_node_num;

index_link_node* index;

}kvector;

typedef int (*KVECTOR_EACH_PAGE_CB)(void* p,void* param);

/*初始化数组*/

int kvector_init(kvector* vector,int init_size);

/*销毁数组*/

void kvector_destroy(kvector* vector);

/*数组大小更改*/

int kvector_resize(kvector* vector,int new_size);

/*设置数组中的第index个元素*/

int kvector_set(kvector* vector,int index,void* mem);

/*取得数组中的第index个元素*/

int kvector_get(kvector* vector,int index,void* mem);

void kvector_foreach_page(kvector* vector,KVECTOR_EACH_PAGE_CB callback,void* param);

#endif

kvector.c

#include "kvector.h"

void kvector_destroy(kvector* vector);

void* kvector_get_free_page(void){

void* r=(void*) get_zeroed_page(GFP_KERNEL);

return r;

}

void kvector_free_page(void* p){

free_page((unsigned long)p);

}

int kvector_index_add_link_node(kvector* vector){

index_link_node* p;

index_link_node* r=(index_link_node*)kvector_get_free_page();

if(!r) return 0;

r->next=NULL;

if(vector->index==NULL){

vector->index=r;

}

else{

p=vector->index;

while(p->next!=NULL){

p=p->next;

}

p->next=r;

}

vector->total_index_elements+=INDEX_LINK_EACH_NUM;

vector->index_node_num++;

return 1;

}

int kvector_add_data_page(kvector* vector){

index_link_node* node;

int r,i;

void* page;

int cpage=vector->current_index_pos/INDEX_LINK_EACH_NUM;

if(vector->current_index_pos>=vector->total_index_elements){

r=kvector_index_add_link_node(vector);

if(!r) return 0;

}

page=kvector_get_free_page();

if(!page) return 0;

node=vector->index;

for(i=0;i

node=node->next;

}

i=vector->current_index_pos%INDEX_LINK_EACH_NUM;

node->data_pages[i]=page;

vector->current_index_pos++;

return 1;

}

int kvector_init(kvector* vector,int init_size){

int r;

int i;

int init_page_num;

init_page_num=init_size/(ELEMENTS_PER_PAGE)+(init_size%(ELEMENTS_PER_PAGE)==0 ? 0:1);

vector->size=init_size;

vector->current_index_pos=0;

vector->total_index_elements=0;

vector->index_node_num=0;

vector->index=NULL;

for(i=0;i

r=kvector_add_data_page(vector);

if(!r){

kvector_destroy(vector);

return 0;

}

}

return 1;

}

int kvector_resize(kvector* vector,int new_size){

int add_page_num;

int i,r;

if(new_sizesize) return vector->size;

add_page_num=(new_size/(ELEMENTS_PER_PAGE)+(new_size%(ELEMENTS_PER_PAGE)==0 ? 0:1))-vector->current_index_pos;

for(i=0;i

r=kvector_add_data_page(vector);

if(!r){

return vector->size;

}

vector->size+=(ELEMENTS_PER_PAGE);

}

return vector->size;

}

void kvector_destroy(kvector* vector){

index_link_node *node,*t;

int i,j;

i=0;

node=vector->index;

while(node!=NULL){

for(j=0;j

if(i>=vector->current_index_pos) break;

kvector_free_page(node->data_pages[j]);

i++;

}

t=node;

node=node->next;

kvector_free_page(t);

}

}

void kvector_foreach_page(kvector* vector,KVECTOR_EACH_PAGE_CB callback,void* param){

index_link_node *node;

int i,j;

i=0;

node=vector->index;

while(node!=NULL){

for(j=0;j

if(i>=vector->current_index_pos) break;

if(!callback(node->data_pages[j],param)) return;

i++;

}

node=node->next;

}

}

int kvector_set(kvector* vector,int index,void* mem){

index_link_node* node;

int page_index;

int page_mem_index;

int node_index;

int node_page_index;

char* page_mem;

int i;

if(index>vector->size) return 0;

page_index=index/(ELEMENTS_PER_PAGE);

page_mem_index=index%(ELEMENTS_PER_PAGE);

node_index=page_index/INDEX_LINK_EACH_NUM;

node_page_index=page_index%INDEX_LINK_EACH_NUM;

node=vector->index;

for(i=0;i

node=node->next;

}

page_mem=(char*)node->data_pages[node_page_index];

page_mem+=(page_mem_index*ELEMENT_LENGTH);

memcpy(page_mem,mem,ELEMENT_LENGTH);

return 1;

}

int kvector_get(kvector* vector,int index,void* mem){

index_link_node* node;

int page_index;

int page_mem_index;

int node_index;

int node_page_index;

char* page_mem;

int i;

if(index>vector->size) return 0;

page_index=index/(ELEMENTS_PER_PAGE);

page_mem_index=index%(ELEMENTS_PER_PAGE);

node_index=page_index/INDEX_LINK_EACH_NUM;

node_page_index=page_index%INDEX_LINK_EACH_NUM;

node=vector->index;

for(i=0;i

node=node->next;

}

page_mem=(char*)node->data_pages[node_page_index];

page_mem+=(page_mem_index*ELEMENT_LENGTH);

memcpy(mem,page_mem,ELEMENT_LENGTH);

return 1;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值