Linux で複数の独立した C 実行可能ファイル間で変数を共有したいと考えています。つまり、プログラムは配列に書き込み、フラグを設定して、他のプログラムが使用できないようにし、この操作の後、フラグを設定解除し、別のプログラムが配列を読み取ります。すべてのプログラムで同じカスタム ヘッダー ファイル (変数を含む) を使用しようとしましたが、プログラムが呼び出されると変数の異なるインスタンスが作成されるようです。
2 に答える
ヘッダーで宣言する変数は、それらを含める場所にコピーを生成します (宣言しない限りextern
)。もちろん、個別のプロセスを扱う場合、すべてのプロセスには独自のメモリ空間があります。これを回避するには、より洗練された手法、つまりプロセス間通信 (IPC) を使用する必要があります。例えば:
- (命名) パイプ
- ソケット
- 共有メモリ
これにより、複数のプロセスが同じメモリ領域にアクセスしていくつかの変数を共有できるため、共有メモリが必要なようです。例として、この質問とその回答を見てください。
プログラムは、たとえば shmget を使用して共有メモリを作成し、shmatを使用して共有メモリ オブジェクトをアタッチする必要があります。複数のプロセスが同じメモリ領域にアクセスする場合、共有セマフォ ( semget、semop )などを使用して、変数の読み取り/書き込み中にプロセス同期を追加することは常に健全なアプローチです。
共有メモリを使い終わったら、そこからデタッチ ( shmdt )する必要があります。これにより、プロセスがカーネルにアクセスする必要がなくなったことをカーネルに伝えます。共有メモリ/セマフォ オブジェクトを作成したプロセスも、プログラムの最後でそれらを破棄する必要があります。そうしないと、おそらくマシンを再起動するまでメモリに常駐します (特にshmctl、semctlIPC_RMID
を参照)。
共有メモリオブジェクトの場合、「セグメントは、最後のプロセスがデタッチした後にのみ実際に破棄される」ことに注意してください。したがって、これが実際にすべてのプロセス ( shmdt ) で発生することを確認する必要があります。
コメントへの回答として、POSIX アプローチを次に示します。
System V 共有メモリ (shmget(2)、shmop(2) など) は、古い共有メモリ API です。POSIX 共有メモリは、よりシンプルで優れた設計のインターフェイスを提供します。一方、POSIX 共有メモリは、System V 共有メモリよりも (特に古いシステムで) 利用できる範囲がいくぶん少なくなります。
- shm_open - 共有メモリを取得する (ファイル記述子を介して)
- ftruncate - 共有メモリのサイズを設定する
- mmap - メモリへのポインタを取得する
- sem_open - セマフォを取得する
- sem_wait、sem_post - 読み取り/書き込み同期用
- shm_unlink、sem_close - 結局クリーンアップする
例については、この概要とこちらも参照してください。
最後に、注意してください
POSIX 共有メモリ オブジェクトにはカーネル永続性があります。共有メモリ オブジェクトは、システムがシャットダウンされるか、すべてのプロセスがオブジェクトのマップを解除し、shm_unlink(3) で削除されるまで存在します。
共有メモリ オブジェクトの永続性を考慮するために、例外的な終了 (SIGINT、SIGTERM など) の場合にクリーンアップ操作を実行するシグナル ハンドラをアプリケーションに追加することを忘れないでください。
shm_open
および... を介した POSIX 共有メモリの使用を検討してくださいshm_unlink
。個人的には、 などの古い System-V IPC 呼び出しよりも使いやすく、より簡単だと感じてshmget
います。 、 などread
の呼び出しで使用できますwrite
。それ以外の場合、通常のポインターを介してファイル記述子によって表される共有メモリ オブジェクトにアクセスする場合は、mmap
によって返されるファイル記述子でを使用できますshm_open
。