PHP ソース コードの簡単な説明 30: PHP メモリ プールのストレージ層
この記事では、主に PHP のソース コード 30 について紹介します。これは、特定の参照値を持っています。
PHP ソースコードの話 30: PHP メモリ プールのストレージ層
[概要]
PHP のメモリ マネージャーは階層構造になっています。このマネージャーには、ストレージ層、ヒープ層、emalloc/efree 層の 3 つの層があります。ストレージ層は実際には、malloc() や mmap() などの関数を通じてシステムからメモリを適用し、free() 関数を通じて要求されたメモリを解放します。ストレージ層は通常、比較的大きなメモリ ブロックに適用されます。ここで適用される大きなメモリは、ストレージ層の構造に必要なメモリを意味するものではなく、ヒープ層がストレージ層の割り当てメソッドを呼び出すときに適用されるメモリを意味します。セグメント形式ではメモリ割り当て方法が比較的大きいため、ストレージ層の役割はメモリ割り当て方法をヒープ層に対して透過的にすることです。
最初にストレージ層の構造を見てみましょう:
[構造]
/* Heaps with user defined storage */ typedef struct _zend_mm_storage zend_mm_storage; typedef struct _zend_mm_segment { size_t size; struct _zend_mm_segment *next_segment; } zend_mm_segment; typedef struct _zend_mm_mem_handlers { const char *name; zend_mm_storage* (*init)(void *params); // 初始化函数 void (*dtor)(zend_mm_storage *storage); // 析构函数 void (*compact)(zend_mm_storage *storage); zend_mm_segment* (*_alloc)(zend_mm_storage *storage, size_t size); // 内存分配函数 zend_mm_segment* (*_realloc)(zend_mm_storage *storage, zend_mm_segment *ptr, size_t size); // 重新分配内存函数 void (*_free)(zend_mm_storage *storage, zend_mm_segment *ptr); // 释放内存函数 } zend_mm_mem_handlers; struct _zend_mm_storage { const zend_mm_mem_handlers *handlers; // 处理函数集 void *data;};
メモリ割り当て方法、呼び出される関数は _zend_mm_storage 構造体に設定された処理関数、およびメモリセグメント化して形で表現します。
[4 つのメモリ スキーム]
PHP には、ストレージ層に 4 つのメモリ割り当てスキームがあります: malloc、win32、mmap_anon、mmap_zero デフォルトでは、ZEND_WIN32 マクロが設定されている場合は、malloc がメモリの割り当てに使用されます。 Windows のバージョンを変更し、HeapAlloc を呼び出してメモリを割り当てます。残りの 2 つのメモリ スキームは匿名メモリ マッピングであり、PHP のメモリ スキームは変数を設定することで変更できます。
公式の説明は次のとおりです。
Zend MM は ZEND_MM_MEM_TYPE および ZEND_MM_SEG_SIZE 環境
変数を使用して調整できます。デフォルト値は「malloc」および「256K」です。
「mmap_anon」、「mmap_zero」、および「win32」ストレージ マネージャーも使用できます。
コードでは、これら 4 つのメモリ割り当てスキームに対して、zend_mm_mem_handlers の各処理関数がそれぞれ実装されています。コードの簡単な説明は次のとおりです:
/* 使用mmap内存映射函数分配内存 写入时拷贝的私有映射,并且匿名映射,映射区不与任何文件关联。*/ # define ZEND_MM_MEM_MMAP_ANON_DSC {"mmap_anon", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_anon_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free} /* 使用mmap内存映射函数分配内存 写入时拷贝的私有映射,并且映射到/dev/zero。*/ # define ZEND_MM_MEM_MMAP_ZERO_DSC {"mmap_zero", zend_mm_mem_mmap_zero_init, zend_mm_mem_mmap_zero_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_mmap_zero_alloc, zend_mm_mem_mmap_realloc, zend_mm_mem_mmap_free} /* 使用HeapAlloc分配内存 windows版本 关于这点,注释中写的是VirtualAlloc() to allocate memory,实际在程序中使用的是HeapAlloc*/ # define ZEND_MM_MEM_WIN32_DSC {"win32", zend_mm_mem_win32_init, zend_mm_mem_win32_dtor, zend_mm_mem_win32_compact, zend_mm_mem_win32_alloc, zend_mm_mem_win32_realloc, zend_mm_mem_win32_free} /* 使用malloc分配内存 默认为此种分配 如果有加ZEND_WIN32宏,则使用win32的分配方案*/ # define ZEND_MM_MEM_MALLOC_DSC {"malloc", zend_mm_mem_dummy_init, zend_mm_mem_dummy_dtor, zend_mm_mem_dummy_compact, zend_mm_mem_malloc_alloc, zend_mm_mem_malloc_realloc, zend_mm_mem_malloc_free}static const zend_mm_mem_handlers mem_handlers[] = {#ifdef HAVE_MEM_WIN32 ZEND_MM_MEM_WIN32_DSC,#endif#ifdef HAVE_MEM_MALLOC ZEND_MM_MEM_MALLOC_DSC,#endif#ifdef HAVE_MEM_MMAP_ANON ZEND_MM_MEM_MMAP_ANON_DSC,#endif#ifdef HAVE_MEM_MMAP_ZERO ZEND_MM_MEM_MMAP_ZERO_DSC,#endif {NULL, NULL, NULL, NULL, NULL, NULL}};
[匿名メモリ マッピングの利点について]
mmem_zero ソリューション:
(SVR 4) /dev/zero メモリ マッピング
1。疑似デバイス「/dev/zero」をパラメータとして mmap に渡してマッピング領域を作成することができます。 /dev/zero の特別な点は、このデバイス ファイルに対するすべての読み取り操作が値 0 を持つ指定された長さのバイト ストリームを返し、書き込まれた内容はすべて破棄されることです。私たちの関心は、これを使用してマッピング領域を作成することにあります。/dev/zero で作成されたマッピング領域の内容は 0 に初期化されます。
2. /dev/zero を使用する利点は、mmap がマッピング領域を作成するときに、常に存在するファイルを必要としないことです。擬似ファイル /dev/zero だけで十分です。欠点は、関連するプロセス間でのみ使用できることです。関連するプロセス間の通信と比較して、スレッド間通信を使用する方が効率的です。使用するテクノロジーに関係なく、共有データへのアクセスは同期する必要があります。
mmem_anon ソリューション:
(4.4 BSD) 匿名メモリ マッピング
1. 匿名メモリ マッピングと /dev/zero タイプの使用には実ファイルは必要ありません。匿名マッピングを使用するには、MAP_ANON フラグを mmap に渡し、fd パラメータを -1 に設定する必要があります。
2. いわゆる匿名とは、マッピング領域が fd を通じてファイル パス名に関連付けられていないことを意味します。血のつながったプロセス間では、匿名メモリ マッピングが使用されます。
[win32 スキームでのヒープ メモリ割り当ての宣言]
windows API
関数 HeapAlloc は次のように宣言されます。
WINBASEAPI __out_opt HANDLE WINAPI HeapCreate( __in DWORD flOptions, __in SIZE_T dwInitialSize, __in SIZE_T dwMaximumSize); WINBASEAPI BOOL WINAPI HeapDestroy( __in HANDLE hHeap); WINBASEAPI __bcount(dwBytes)LPVOID WINAPI HeapAlloc( __in HANDLE hHeap, __in DWORD dwFlags, __in SIZE_T dwBytes); WINBASEAPI BOOL WINAPI HeapFree( __inout HANDLE hHeap, __inDWORD dwFlags, __deref LPVOID lpMem); WINBASEAPI SIZE_T WINAPI HeapSize( __in HANDLE hHeap, __in DWORD dwFlags, __in LPCVOID lpMem);
hHeap はプロセス ヒープ メモリの開始位置です。
dwFlags は、ヒープ メモリを割り当てるためのフラグです。
dwBytes は、割り当てられたヒープ メモリのサイズです。
[初期化]
zend_mm_startup が開始されると、プログラムは次のコードに示すように、構成に従ってメモリ割り当てプランとセグメント割り当てサイズを設定します。
ZEND_API zend_mm_heap *zend_mm_startup(void){ int i; size_t seg_size; char *mem_type = getenv("ZEND_MM_MEM_TYPE"); char *tmp; const zend_mm_mem_handlers *handlers; zend_mm_heap *heap; if (mem_type == NULL) { i = 0; } else { for (i = 0; mem_handlers[i].name; i++) { if (strcmp(mem_handlers[i].name, mem_type) == 0) { break; } } if (!mem_handlers[i].name) { fprintf(stderr, "Wrong or unsupported zend_mm storage type '%s'\n", mem_type); fprintf(stderr, " supported types:\n"); for (i = 0; mem_handlers[i].name; i++) { fprintf(stderr, "'%s'\n", mem_handlers[i].name); } exit(255); } } handlers = &mem_handlers[i]; tmp = getenv("ZEND_MM_SEG_SIZE"); if (tmp) { seg_size = zend_atoi(tmp, 0); if (zend_mm_low_bit(seg_size) != zend_mm_high_bit(seg_size)) { fprintf(stderr, "ZEND_MM_SEG_SIZE must be a power of two\n"); exit(255); } else if (seg_size < ZEND_MM_ALIGNED_SEGMENT_SIZE + ZEND_MM_ALIGNED_HEADER_SIZE) { fprintf(stderr, "ZEND_MM_SEG_SIZE is too small\n"); exit(255); } } else { seg_size = ZEND_MM_SEG_SIZE; } //....代码省略}
行 1121 ~1138 は mem_handlers 配列全体を走査し、ZEND_MM_MEM_TYPE 変数が設定されていない場合はデフォルトで malloc スキームが使用され、ZEND_MM_MEM_TYPE の場合はデフォルトで win32 スキームが使用されます。変数が設定されている場合、設定スキームが使用されます。
1140行目から1152行目は、ZEND_MM_SEG_SIZE変数が設定されている場合、設定されたサイズが使用され、設定されたサイズが2の倍数以上かどうかを判定します。 ZEND_MM_ALIGNED_SEGMENT_SIZE ZEND_MM_ALIGNED_HEADER_SIZE に等しい; if 設定がない場合、デフォルトの ZEND_MM_SEG_SIZE は使用されません。
[付録]
関数の説明:
mmap はファイルまたは他のオブジェクトをメモリにマップします。ファイルは複数のページにマップされ、ファイルのサイズがすべてのページのサイズの合計と異なる場合、最後のページの未使用領域はクリアされます。 munmap は逆の操作を実行し、特定のアドレス範囲のオブジェクト マッピングを削除します。
ファイル マッピングに基づいて、mmap および munmap の実行中のいつでも、マップされたファイルの st_atime が更新される可能性があります。上記の状況で st_atime フィールドが更新されない場合、このフィールドの値は、マップされた領域の最初のページに初めてインデックスが付けられたときに更新されます。 PROT_WRITE フラグと MAP_SHARED フラグを使用して確立されたファイル マッピングの場合、その st_ctime と st_mtime
は、マッピング領域への書き込み後、MS_SYNC フラグと MS_ASYNC フラグを使用して msync() が呼び出される前に更新されます。 ######使用法:######
#include void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void *start, size_t length);
参数:
start:映射区的开始地址。
length:映射区的长度。
prot:期望的内存保护标志,不能与文件的打开模式冲突。是以下的某个值,可以通过or运算合理地组合在一起
PROT_EXEC //页内容可以被执行
PROT_READ //页内容可以被读取
PROT_WRITE //页可以被写入
PROT_NONE //页不可访问
flags:指定映射对象的类型,映射选项和映射页是否可以共享。它的值可以是一个或者多个以下位的组合体
MAP_FIXED //使用指定的映射起始地址,如果由start和len参数指定的内存区重叠于现存的映射空间,重叠部分将会被丢弃。如果指定的起始地址不可用,操作将会失败。并且起始地址必须落在页的边界上。
MAP_SHARED //与其它所有映射这个对象的进程共享映射空间。对共享区的写入,相当于输出到文件。直到msync()或者munmap()被调用,文件实际上不会被更新。
MAP_PRIVATE //建立一个写入时拷贝的私有映射。内存区域的写入不会影响到原文件。这个标志和以上标志是互斥的,只能使用其中一个。
MAP_DENYWRITE //这个标志被忽略。
MAP_EXECUTABLE //同上
MAP_NORESERVE //不要为这个映射保留交换空间。当交换空间被保留,对映射区修改的可能会得到保证。当交换空间不被保留,同时内存不足,对映射区的修改会引起段违例信号。
MAP_LOCKED //锁定映射区的页面,从而防止页面被交换出内存。
MAP_GROWSDOWN //用于堆栈,告诉内核VM系统,映射区可以向下扩展。
MAP_ANONYMOUS //匿名映射,映射区不与任何文件关联。
MAP_ANON //MAP_ANONYMOUS的别称,不再被使用。
MAP_FILE //兼容标志,被忽略。
MAP_32BIT //将映射区放在进程地址空间的低2GB,MAP_FIXED指定时会被忽略。当前这个标志只在x86-64平台上得到支持。
MAP_POPULATE //为文件映射通过预读的方式准备好页表。随后对映射区的访问不会被页违例阻塞。
MAP_NONBLOCK //仅和MAP_POPULATE一起使用时才有意义。不执行预读,只为已存在于内存中的页面建立页表入口。
fd:有效的文件描述词。如果MAP_ANONYMOUS被设定,为了兼容问题,其值应为-1。
offset:被映射对象内容的起点。
返回说明:
成功执行时,mmap()返回被映射区的指针,munmap()返回0。失败时,mmap()返回MAP_FAILED[其值为(void *)-1],munmap返回-1。errno被设为以下的某个值
EACCES:访问出错
EAGAIN:文件已被锁定,或者太多的内存已被锁定
EBADF:fd不是有效的文件描述词
EINVAL:一个或者多个参数无效
ENFILE:已达到系统对打开文件的限制
ENODEV:指定文件所在的文件系统不支持内存映射
ENOMEM:内存不足,或者进程已超出最大内存映射数量
EPERM:权能不足,操作不允许
ETXTBSY:已写的方式打开文件,同时指定MAP_DENYWRITE标志
SIGSEGV:试着向只读区写入
SIGBUS:试着访问不属于进程的内存区
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!
相关推荐:
以上がPHP ソース コードの簡単な説明 30: PHP メモリ プールのストレージ層の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

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

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Laravelは、直感的なフラッシュメソッドを使用して、一時的なセッションデータの処理を簡素化します。これは、アプリケーション内に簡単なメッセージ、アラート、または通知を表示するのに最適です。 データは、デフォルトで次の要求のためにのみ持続します。 $リクエスト -

PHPクライアントURL(CURL)拡張機能は、開発者にとって強力なツールであり、リモートサーバーやREST APIとのシームレスな対話を可能にします。尊敬されるマルチプロトコルファイル転送ライブラリであるLibcurlを活用することにより、PHP Curlは効率的なexecuを促進します

Laravelは簡潔なHTTP応答シミュレーション構文を提供し、HTTP相互作用テストを簡素化します。このアプローチは、テストシミュレーションをより直感的にしながら、コード冗長性を大幅に削減します。 基本的な実装は、さまざまな応答タイプのショートカットを提供します。 Illuminate \ support \ facades \ httpを使用します。 http :: fake([[ 'google.com' => 'hello world'、 'github.com' => ['foo' => 'bar']、 'forge.laravel.com' =>

顧客の最も差し迫った問題にリアルタイムでインスタントソリューションを提供したいですか? ライブチャットを使用すると、顧客とのリアルタイムな会話を行い、すぐに問題を解決できます。それはあなたがあなたのカスタムにより速いサービスを提供することを可能にします

記事では、PHP 5.3で導入されたPHPの後期静的結合(LSB)について説明し、より柔軟な継承を求める静的メソッドコールのランタイム解像度を可能にします。 LSBの実用的なアプリケーションと潜在的なパフォーマ

JWTは、JSONに基づくオープン標準であり、主にアイデンティティ認証と情報交換のために、当事者間で情報を安全に送信するために使用されます。 1。JWTは、ヘッダー、ペイロード、署名の3つの部分で構成されています。 2。JWTの実用的な原則には、JWTの生成、JWTの検証、ペイロードの解析という3つのステップが含まれます。 3. PHPでの認証にJWTを使用する場合、JWTを生成および検証でき、ユーザーの役割と許可情報を高度な使用に含めることができます。 4.一般的なエラーには、署名検証障害、トークンの有効期限、およびペイロードが大きくなります。デバッグスキルには、デバッグツールの使用とロギングが含まれます。 5.パフォーマンスの最適化とベストプラクティスには、適切な署名アルゴリズムの使用、有効期間を合理的に設定することが含まれます。

記事では、入力検証、認証、定期的な更新など、脆弱性から保護するためのフレームワークの重要なセキュリティ機能について説明します。
