Linux メモリ管理関連関数: 1. kmalloc()、カーネル モードでのメモリ割り当てに使用; 2. vmalloc()、一般にソフトウェア内にのみ存在する関数に使用 (対応するハードウェアの意味はない) より大きなシーケンシャル バッファメモリの割り当て; 3. alloc_page() および alloc_pages() 関数はカーネル空間に割り当てることができます; 4. __get_free_pages() 一連の関数は 1 つ以上のページの仮想アドレスを返します; 5. kmem_cache_alloc() など。
#このチュートリアルの動作環境: linux7.3 システム、Dell G3 コンピューター。
この記事では、Linux の基礎となるメモリ割り当てメカニズムをより深く理解できるように、Linux カーネルのいくつかの一般的なメモリ割り当て関数とその類似点と相違点について説明します。
1.kmalloc()
kmalloc() 関数は、一般的な malloc() 関数に似ています。前者はカーネル状態に使用されます。メモリ、割り当て、後者はユーザー モードで使用されます。
kmalloc() 関数は、物理メモリ内に 連続 ストレージ スペースを割り当てます。malloc() 関数と同様に、内部の元のデータはクリアされません。メモリが十分であれば、その割り当て速度は非常に速くなります。速い。 。そのプロトタイプは次のとおりです。
static inline void *kmalloc(size_t size, gfp_t flags); /*返回的是虚拟地址*/
- size: 割り当てられるメモリ サイズ。 Linux のメモリ管理メカニズムにより、メモリはページ サイズに従ってしか割り当てられません (通常、32 ビット マシンの場合は 4KB、64 ビット マシンの場合は 8KB)。その結果、数バイトだけが必要な場合でもシステムが返されることになります。メモリ 1 ページのメモリは明らかに非常に無駄です。したがって、malloc とは異なり、kmalloc の処理方法は次のとおりです: カーネルはまず、異なるサイズ (32B、64B、128B、...、128KB) の一連のメモリ プールを割り当てます。メモリを割り当てる必要がある場合、システムはより大きなメモリ プールを割り当てます。以上 メモリを必要とする最小のメモリ プールを指定します。つまり、kmalloc によって割り当てられるメモリの最小値は 32 バイト、最大値は 128KB です。 128KB を超える場合は、vmalloc() などの他のメモリ割り当て関数をサンプリングする必要があります。
-
flag: このパラメータは、関数の動作を制御するために使用されます。最も一般的に使用されるパラメータは GFP_KERNEL です。これは、現在十分なメモリが割り当てられていない場合、プロセスが次の処理に進むことを意味します。スリープし、システムがバッファの内容を保存するのを待ちます。ハード ディスクに SWAP した後、十分なメモリを取得し、プロセスを起動してメモリを割り当てます。その他のフラグについては、以下の図を参照してください。
- GFP_ KERNEL フラグを使用してメモリを適用する場合、一時的に満たせない場合、プロセスはスリープしてページを待ちます。ブロッキングの原因となるため、割り込みコンテキストで使用することはできません。または、スピン ロックを保持するときに GFP_KERNE を使用してメモリを適用することもできません。したがって、割り込みハンドラー、タスクレット、カーネル タイマーなどの非プロセス コンテキストではブロックできません。この場合、ドライバーは GFP_ATOMIC フラグを使用してメモリを適用する必要があります。 GFP_ATOMICフラグを使用してメモリを申請した場合、空きページがない場合は待たずに直接リターンします。
- 上記の表にリストされているフラグに加えて、次の も含まれます:
- _ _GFP_DMA (DMA 可能なメモリ領域に割り当てられる必要があります)
- _ _GFP_HIGHMEM (割り当てられたメモリがハイメモリに配置できることを示します)
- _ _GFP_COLD (長期間アクセスされていないページを要求します)
- _ _GFP_NOWARN (割り当てが満たされない場合にカーネルが警告を発行しないようにします)
- _ _GFP_HIGH (優先度の高い要求。緊急用にカーネルによって予約された最後のメモリ ページを取得できます)
- _ _GFP_REPEAT (割り当てが失敗した場合はベストエフォートで再試行)
- _ _GFP_NOFAIL (マークはアプリケーションの成功のみを許可します。推奨されません)
- _ _GFP_NORETRY (アプリケーションを取得できない場合は、すぐに諦めます)
- kmalloc() を使用するために適用されるメモリは、
kfree ()
Release を使用する必要があります。この関数の使用法は、ユーザー空間での free() と似ています。
2. vmalloc()
vmalloc()
は通常、ソフトウェア内でのみ使用されます (対応するハードウェアの意味) は、より大きなシーケンシャル バッファにメモリを割り当てます。メモリに割り当てるのに十分な大きさの連続した物理スペースがない場合、この関数を使用して連続した仮想アドレスを割り当てることができますが、不連続な物理アドレス #メモリ。新しいページテーブルを作成する必要があるため、そのオーバーヘッドは kmalloc や、後で説明する __get_free_pages()
関数よりもはるかに大きくなります。また、vmalloc()
は、内部実装で GFP_KERNEL フラグを指定した kmalloc()
を使用するため、アトミック コンテキストでは使用できません。その関数プロトタイプは次のとおりです:
void *vmalloc(unsigned long size); void vfree(const void *addr);
- 使用 vmalloc 函数的一个例子函数是
create_module()
系统调用,它利用 vmalloc()函数来获取被创建模块需要的内存空间。 - 内存分配是一项要求严格的任务,无论什么时候,都应该对返回值进行检测。
- 在驱动编程中可以使用
copy_from_user()
对内存进行使用。下面举一个使用vmalloc函数的示例:
static int xxx(...) { ... cpuid_entries = vmalloc(sizeof(struct kvm_cpuid_entry) * cpuid->nent); if(!cpuid_entries) goto out; if(copy_from_user(cpuid_entries, entries, cpuid->nent * sizeof(struct kvm_cpuid_entry))) goto out_free; for(i=0; i<cpuid->nent; i++){ vcpuid->arch.cpuid_entries[i].eax = cpuid_entries[i].eax; ... vcpuid->arch.cpuid_entries[i].index = 0; } ... out_free: vfree(cpuid_entries); out: return r; }
3、页分配函数
在linux中,内存分配是以页为单位的,32位机中一页为4KB,64位机中,一页为8KB,但具体还有根据平台而定。
根据返回值类型的不同,页分配函数分为两类,一是返回物理页地址,二是返回虚拟地址。虚拟地址和物理地址起始相差一个固定的偏移量。
#define __pa(x) ((x) - PAGE_OFFSET) static inline unsigned long virt_to_phys(volatile void *address) { return __pa((void *)address); } #define __va(x) ((x) + PAGE_OFFSET) static inline void* phys_to_virt(unsigned long address) { return __va(address); }
根据返回页面数目分类,分为仅返回单页面的函数和返回多页面的函数。
3.1 alloc_page()和alloc_pages()函数
该函数定义在头文件/include/linux/gfp.h
中,它既可以在内核空间分配,也可以在用户空间分配,它返回分配的第一个页的描述符而非首地址,其原型为:
#define alloc_page(gfp_mask) alloc_pages(gfp_mask, 0) #define alloc_pages(gfp_mask, order) alloc_pages_node(numa_node_id(), gfp_mask, order) //分配连续2^order个页面 static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask, unsigned int order) { if(unlikely(order >= MAX_ORDER)) return NULL; if(nid < 0) nid = numa_node_id(); return __alloc_pages(gfp_mask, order, noed_zonelist(nid, gfp_mask)); }
3.2 __get_free_pages()系列函数
它是kmalloc函数实现的基础,返回一个或多个页面的虚拟地址。该系列函数/宏包括 get_zeroed_page()
、_ _get_free_page()
和_ _get_free_pages()
。在使用时,其申请标志的值及含义与 kmalloc()
完全一样,最常用的是 GFP_KERNEL 和 GFP_ATOMIC。
/*分配多个页并返回分配内存的首地址,分配的页数为2^order,分配的页不清零。 order 允许的最大值是 10(即 1024 页)或者 11(即 2048 页),依赖于具体 的硬件平台。*/ unsigned long __get_free_pages(gfp_t gfp_mask, unsigned int order) { struct page *page; page = alloc_pages(gfp_mask, order); if(!page) return 0; return (unsigned long)page_address(page); } #define __get_free_page(gfp_mask) __get_free_pages(gfp_mask, 0) /*该函数返回一个指向新页的指针并且将该页清零*/ unsigned long get_zeroed_page(unsigned int flags);
- 使用
_ _get_free_pages()
系列函数/宏申请的内存应使用free_page(addr)
或free_pages(addr, order)
函数释放:
#define __free_page(page) __free_pages((page), 0) #define free_page(addr) free_pages((addr), 0) void free_pages(unsigned long addr, unsigned int order) { if(addr != 0){ VM_BUG_ON(!virt_addr_valid((void*)addr)); __free_pages(virt_to_page((void *)addr), order); } } void __free_pages(struct page *page, unsigned int order) { if(put_page_testzero(page)){ if(order == 0) free_hot_page(page); else __free_pages_ok(page, order); } }
free_pages()函数是调用__free_pages()函数完成内存释放的。
4、slab缓存
- 当在驱动程序中,遇到反复分配、释放同一大小的内存块时(例如,inode、task_struct等),建议使用内存池技术(对象在前后两次被使用时均分配在同一块内存或同一类内存空间,且保留了基本的数据结构,这大大提高了效率)。在linux中,有一个叫做slab分配器的内存池管理技术,内存池使用的内存区叫做后备高速缓存。
- salb相关头文件在linux/slab.h中,在使用后备高速缓存前,需要创建一个
kmem_cache
的结构体。
4.1 创建slab缓存区
该函数创建一个slab缓存(后备高速缓冲区),它是一个可以驻留任意数目全部同样大小的后备缓存。其原型如下:
struct kmem_cache *kmem_cache_create(const char *name, size_t size, \ size_t align, unsigned long flags,\ void (*ctor)(void *, struct kmem_cache *, unsigned long),\ void (*dtor)(void *, struct kmem_cache *, unsigned ong)));
其中:
name:创建的缓存名;
size:可容纳的缓存块个数;
align:后备高速缓冲区中第一个内存块的偏移量(一般置为0);
flags:控制如何进行分配的位掩码,包括 SLAB_NO_REAP
(即使内存紧缺也不自动收缩这块缓存)、SLAB_HWCACHE_ALIGN
( 每 个 数 据 对 象 被 对 齐 到 一 个 缓 存 行 )、SLAB_CACHE_DMA
(要求数据对象在 DMA 内存区分配)等);
ctor:是可选的内存块对象构造函数(初始化函数);
dtor:是可选的内存对象块析构函数(释放函数)。
4.2 分配slab缓存函数
一旦创建完后备高速缓冲区后,就可以调用kmem_cache_alloc()
在缓存区分配一个内存块对象了,其原型如下:
void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags);
cachep指向开始分配的后备高速缓存,flags与传给kmalloc函数的参数相同,一般为GFP_KERNEL。
4.3 释放slab缓存
该函数释放一个内存块对象:
void *kmem_cache_free(struct kmem_cache *cachep, void *objp);
4.4 销毁slab缓存
与kmem_cache_create
对应的是销毁函数,释放一个后备高速缓存:
int kmem_cache_destroy(struct kmem_cache *cachep);
它必须等待所有已经分配的内存块对象被释放后才能释放后备高速缓存区。
4.5 slab缓存使用举例
创建一个存放线程结构体(struct thread_info)的后备高速缓存,因为在linux中涉及频繁的线程创建与释放,如果使用__get_free_page()函数会造成内存的大量浪费,效率也不高。所以在linux内核的初始化阶段就创建了一个名为thread_info的后备高速缓存,代码如下:
/* 创建slab缓存 */ static struct kmem_cache *thread_info_cache; thread_info_cache = kmem_cache_create("thread_info", sizeof(struct thread_info), \ SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL); /* 分配slab缓存 */ struct thread_info *ti; ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL); /* 使用slab缓存 */ ... /* 释放slab缓存 */ kmem_cache_free(thread_info_cache, ti); kmem_cache_destroy(thread_info_cache);
5、内存池
在 Linux 内核中还包含对内存池的支持,内存池技术也是一种非常经典的用于分配大量小对象的后备缓存技术。
5.1 创建内存池
mempool_t *mempool_create(int min_nr, mempool_alloc_t *alloc_fn, \ mempool_free_t *free_fn, void *pool_data);
mempool_create()函数用于创建一个内存池,min_nr 参数是需要预分配对象的数目,alloc_fn 和 free_fn 是指向内存池机制提供的标准对象分配和回收函数的指针,其原型分别为:
typedef void *(mempool_alloc_t)(int gfp_mask, void *pool_data); typedef void (mempool_free_t)(void *element, void *pool_data);
pool_data 是分配和回收函数用到的指针,gfp_mask 是分配标记。只有当_ _GFP_WAIT
标记被指定时,分配函数才会休眠。
5.2 分配和回收对象
在内存池中分配和回收对象需由以下函数来完成:
void *mempool_alloc(mempool_t *pool, int gfp_mask); void mempool_free(void *element, mempool_t *pool);
mempool_alloc()用来分配对象,如果内存池分配器无法提供内存,那么就可以用预分配的池。
5.3 销毁内存池
void mempool_destroy(mempool_t *pool);
mempool_create()函数创建的内存池需由 mempool_destroy()来回收。
相关推荐:《Linux视频教程》
以上がLinuxのメモリ管理に関連するいくつかの関数の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

Linuxメンテナンスモードは、起動時にinit =/bin/bashまたは単一パラメーターを追加することにより入力されます。 1.メンテナンスモードの入力:GRUBメニューを編集し、起動パラメーターを追加します。 2。ファイルシステムを読み取りおよび書き込みモードに再マウントします:Mount-Oremount、RW/。 3。ファイルシステムの修復:FSCK/dev/sda1などのFSCKコマンドを使用します。 4.データをバックアップし、データの損失を避けるために慎重に動作します。

この記事では、DebianシステムのHadoopデータ処理効率を改善する方法について説明します。最適化戦略では、ハードウェアのアップグレード、オペレーティングシステムパラメーターの調整、Hadoop構成の変更、および効率的なアルゴリズムとツールの使用をカバーしています。 1.ハードウェアリソースの強化により、すべてのノードが一貫したハードウェア構成、特にCPU、メモリ、ネットワーク機器のパフォーマンスに注意を払うことが保証されます。高性能ハードウェアコンポーネントを選択することは、全体的な処理速度を改善するために不可欠です。 2。オペレーティングシステムチューニングファイル記述子とネットワーク接続:/etc/security/limits.confファイルを変更して、システムによって同時に開くことができるファイル記述子とネットワーク接続の上限を増やします。 JVMパラメーター調整:Hadoop-env.shファイルで調整します

このガイドでは、Debian SystemsでSyslogの使用方法を学ぶように導きます。 Syslogは、ロギングシステムとアプリケーションログメッセージのLinuxシステムの重要なサービスです。管理者がシステムアクティビティを監視および分析して、問題を迅速に特定および解決するのに役立ちます。 1. syslogの基本的な知識Syslogのコア関数には以下が含まれます。複数のログ出力形式とターゲットの場所(ファイルやネットワークなど)をサポートします。リアルタイムのログ表示およびフィルタリング機能を提供します。 2。syslog(rsyslogを使用)をインストールして構成するDebianシステムは、デフォルトでrsyslogを使用します。次のコマンドでインストールできます:sudoaptupdatesud

Debianシステムに適したHadoopバージョンを選択する場合、次の重要な要因を考慮する必要があります。1。安定性と長期的なサポート:安定性とセキュリティを追求するユーザーにとって、Debian11(Bullseye)などのDebianの安定したバージョンを選択することをお勧めします。このバージョンは完全にテストされており、最大5年のサポートサイクルがあり、システムの安定した動作を確保できます。 2。パッケージの更新速度:最新のHadoop機能と機能を使用する必要がある場合は、DebianのUnstableバージョン(SID)を検討できます。ただし、不安定なバージョンには互換性の問題と安定性のリスクがあることに注意する必要があります。 3。コミュニティのサポートとリソース:Debianには、豊富なドキュメントを提供できるコミュニティサポートが大きくなり、

この記事では、Tigervncを使用してDebian Systemsでファイルを共有する方法について説明します。最初にtigervncサーバーをインストールしてから構成する必要があります。 1. TigerVNCサーバーをインストールし、端末を開きます。ソフトウェアパッケージリストの更新リスト:sudoaptupdate tigervnc server:sudoaptinstaltaltigervnc-standalone-servertigervnc-common2。tigervncサーバーを構成するVNCサーバーパスワードを設定します。

Debian Mail Serverのファイアウォールの構成は、サーバーのセキュリティを確保するための重要なステップです。以下は、iPtablesやFirewalldの使用を含む、一般的に使用されるファイアウォール構成方法です。 iPtablesを使用してファイアウォールを構成してIPTablesをインストールします(まだインストールされていない場合):sudoapt-getupdatesudoapt-getinstalliptablesview現在のiptablesルール:sudoiptables-l configuration

Debian Mail ServerにSSL証明書をインストールする手順は次のとおりです。1。最初にOpenSSL Toolkitをインストールすると、OpenSSLツールキットがシステムに既にインストールされていることを確認してください。インストールされていない場合は、次のコマンドを使用してインストールできます。sudoapt-getUpdatesudoapt-getInstalopenssl2。秘密キーと証明書のリクエストを生成次に、OpenSSLを使用して2048ビットRSA秘密キーと証明書リクエスト(CSR)を生成します:Openss

Debianシステムでのメールサーバーの仮想ホストの構成には、通常、Apache Httpserverではなく、Apache Httpserverではなく、Mail Serverソフトウェア(Postfix、Eximなど)のインストールと構成が含まれます。以下は、メールサーバーの構成のための基本的な手順です仮想ホスト:ポストフィックスメールサーバー更新システムパッケージ:sudoaptupdatesudoaptupgradeポストフィックス:sudoapt


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

SublimeText3 Linux 新バージョン
SublimeText3 Linux 最新バージョン

Dreamweaver Mac版
ビジュアル Web 開発ツール

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

mPDF
mPDF は、UTF-8 でエンコードされた HTML から PDF ファイルを生成できる PHP ライブラリです。オリジナルの作者である Ian Back は、Web サイトから「オンザフライ」で PDF ファイルを出力し、さまざまな言語を処理するために mPDF を作成しました。 HTML2FPDF などのオリジナルのスクリプトよりも遅く、Unicode フォントを使用すると生成されるファイルが大きくなりますが、CSS スタイルなどをサポートし、多くの機能強化が施されています。 RTL (アラビア語とヘブライ語) や CJK (中国語、日本語、韓国語) を含むほぼすべての言語をサポートします。ネストされたブロックレベル要素 (P、DIV など) をサポートします。

VSCode Windows 64 ビットのダウンロード
Microsoft によって発売された無料で強力な IDE エディター
