web-dev-qa-db-ja.com

Cの共有メモリにセマフォを作成するにはどうすればよいですか?

私のタスクは、2つの異なるCファイルを作成してから、プロセスの同期にセマフォを使用することです(両方のCファイルを同時に実行します)。

私の主な関心事は、両方のプロセス(Cファイルの実行可能ファイル)のセマフォにアクセスする場合、共有メモリにセマフォを作成する必要があるということです。また、バイナリセマフォを作成する必要があります。

それは私の最初のプログラムなので、誰かがこれを始める方法を提案できますか?

スレッド内で共有メモリ、使用済みセマフォを作成して使用することができます。 YouTube の講義もいくつか見ましたが、適切な解決策が見つかりませんでした。

9

クロスプロセスセマフォは、オペレーティングシステム固有の操作です。

これらの共有のほとんどは、セマフォの名前としてダビングする仮想パスを介して、1つのプロセスでセマフォを作成することです。権限が正しく設定されている場合、同じ仮想パスを使用して、別のプロセスでセマフォを開くことができます。これらの仮想パスは、見慣れているように見えても、通常は実際のファイルシステムパスではありません。

POSIX/System Vベースのシステムでは、通常2つのオプションがあります。 2つのオプションの違いは、 この回答 で非常によく説明されています。

System Vセマフォ

これらは、 semget() で取得できるパスベースのセマフォです。

_#include <sys/types.h>
#include <sys/ipc.h>    
#include <sys/sem.h>

int sem;
int sem_id = 1;
key_t key;

key = ftok("/virtualpathtosemaphore", 1);
// create a new semaphore
sem = semget(key, 1, IPC_CREAT);
// use sem = semget(key, 1, 0); to attach to an existing semaphore
// flags also contain access rights, to take care to set them appropriately

// increment semaphore
struct sembuf semopinc = {
  .sem_num = 0,
  .sem_op = 1,
  .sem_flg = 0
};    
semop(sem, &semopinc, 1);

/* decrement semaphore, may block */
struct sembuf semopdec = {
  .sem_num = 0,
  .sem_op = -1,
  .sem_flg = 0
};   
semop(sem, &semopdec, 1);
_

System Vセマフォは明示的にリンクが解除されるまで存続するため、セマフォをクリーンアップすることが重要であることに注意してください。これは、プロセスがセマフォをクリーンアップせずにクラッシュした場合の一種の問題です(たとえば、FreeBSDにはユーティリティipcrm do remove dangling System V IPCオブジェクト)が付属しています)。

POSIXセマフォ

これらは実際にはあまり広く実装されていないため、カーネルがそれらをサポートしているかどうかを確認してください。これらの名前付きバージョンは、 sem_open() を介して取得されます。

_#include <semaphore.h>

sem_t *sem;
sem = sem_open("/nameofsemaphore", O_CREAT, permissions, 0);
// use sem = sem_open("/nameofsemaphore", 0) to open an existing semaphore

/* increment semaphore */
sem_post(sem);

/* decrement semaphore */
sem_wait(sem);
_

POSIXセマフォは、セマフォへのハンドルを持つ最後のプロセスが終了すると、暗黙的に破棄されます。それらはSystemVセマフォよりも速いと噂されています

Windows

Windowsには独自のセマフォAPIがあります。セマフォは CreateSemaphore() によって作成されます。

Windowsは、POSIXと同じ命名トリックを使用しますが、名前空間の規則が異なります。

_HANDLE hSem;
hSem = CreateSemaphore(NULL, 0, LONG_MAX, _T("Local\\PathToMySemaphore");

// Use OpenSemaphore() to attach to an existing semaphore

// increment semaphore:
ReleaseSemaphore(hSem, 1, NULL);

// decrement semaphore
WaitForSingleObject(hSem, 0);
_

上記の例を適用するときは、エラーチェックを追加することを忘れないでください。また、コードを簡略化するために、アクセス許可を意図的に無視していることにも注意してください。関連するフラグを追加することを忘れないでください。

これらすべてに加えて、(実際のセマフォが到着する前に一般的に行われているように)バイナリミューテックスの形式としてファイルロックを悪用することもできます。

6
dhke

Ubuntu GNU/Linuxを使用しているとおっしゃっていたので、...

名前付きセマフォを使用してください!

#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>

// On first process (the one that creates the semaphore)

char semaphoreName[1 + 6 + 1];
semaphoreName[0] = '/';
semaphoreName[1 + snprintf(&semaphore[1], 6 + 1, "%d", getpid())] = '/0';

sem_t *sem = sem_open(semaphoreName, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0);

// On second process

sem_t *sem = sem_open(semaphoreName, O_RDWR);
3
3442