8

たとえば、次のように、コンパイル時に C プログラムのすべての変数を宣言したいと考えています。

char cache[CACHE_SIZE];
char udp_ring[MAX_UDP_PACKET_SIZE*MAX_REQUESTS];
int  num_packets;
char error_codes[NUM_ERRORS][MAX_ERROR_STRING]= {
    {"Unknown user\n"},
    {"Wrong password\n"},
    ....
};

問題は、変数が BSS または DATA セグメントに入るとき、C プログラムの変数のサイズに制限があるかということです。たとえば、8 GB の RAM の CACHE_SIZE を宣言すると、機能しますか? 32ビットと64ビットで違いはありますか? プログラムを Linux で実行する予定で、RLIMIT_DATA 構成に制限はありません。

4

2 に答える 2

6

カーネルがプロセスに処理を許可するのと同じくらい多くの仮想メモリを管理できます。これはアーキテクチャに依存します。

たとえば、x86 アーキテクチャ (x86-64 ロング モードなし) では、Linux はデフォルトで、プロセスが参照する仮想メモリをプロセス用に 3GB、カーネル用に 1GB に分割します (PAE が有効になっている場合でも)。 3GB を超える仮想メモリを処理できる (テキスト セクション、データ、bss、ヒープ、スタック、共有オブジェクトなどを含む)

すべてのバッファーを静的に割り当て、カーネルがプロセスの仮想アドレス空間に収まらない場合、起動時に強制終了されます。8GB バッファーを使用すると、ほとんどの場合、32 ビット アーキテクチャでこの動作が発生します。

mallocglibc のメモリ管理関数 ( 、...)に依存したくない場合は、独自のメモリ管理ライブラリをロールして、プロセスにそれをLD_PRELOADトリックで強制的に使用させることができます。そのようにして、malloc/calloc/realloc/free(を使用してsbrk()) 実装マッチングを定義できます。あなた自身の要件。

于 2012-08-25T23:00:08.733 に答える
4

とリンクしたくない場合は、syscallglibcを実行できるようにするためのいくつかの奇妙な方法を見つける必要があります( syscalls (2)のマニュアルページにリストされています)。すべてのアプリケーションは、いくつかのシステムコールを実行する必要があります(たとえば、 open(2)read(2)write(2) ...)。Glibcは、syscallにCインターフェイスを提供するためにも使用されます。アセンブリのハウツーでは、libcを使用せずに、アセンブリコードを直接使用して(Casm命令などを介して)syscallを呼び出す方法を説明しています。廃止された_syscall(2)のマニュアルページも参照してください。VDSOも探してください。

mmap(2)munmap(2)syscallsを使用してアドレス空間を変更できます。これは、メモリの割り当てと解放の基本的な操作です。Glibcはそれらを使用してとを実装mallocfreeます。

.data初期化(セグメント)またはクリア(セグメント)のいずれであっても、すべての変数をグローバルまたは静的として宣言することに.bssは、重大な欠点があります。動的にメモリリソースを使用することはできません。また、初期化されたデータがたくさんあると、かなりのコストがかかります。ELF実行可能ファイルは巨大になります。

しかし、Glibcを避けたい理由を本当に説明する必要があります。Cでコーディングする場合、これを回避するのは困難です。dietlibcのようなより軽い代替手段を使用できます。

于 2012-08-26T07:04:38.427 に答える