2009-05-07 13 views
2

AIX(と誰かが気にするHPUX)は、複数のプロセスで共有されているメモリマップファイルの細かい部分(たとえばレコード)を簡単に同期できるようにする、msemaphoresという素晴らしい機能があります。 Linuxに匹敵するものを誰かが知っていますか?msemaphore on linux?

明らかに、msemaphore関数は、関連リンクhereに従って記述されています。

答えて

0

Linuxでは、SysV共有メモリで必要なものを達成できます。クイックグーグルが助けになるかもしれないthis (rather old) guideとなった。

+0

ありがとう:

確かに、あなたも、この面でmsemのAPIを実装することができます。 Msemaphoresは、自分で構築するのではなく、すでに実装されていたと思っていた便利さとシンプルさを提供します。 – Duck

1

POSIX semaphoresは、sem_init(3)の2番目の引数 "pshared"がtrueの場合、プロセス間で共有されるメモリに配置できます。これはmsemと同じであるようです。

#include <semaphore.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <sys/mman.h> 
#include <time.h> 
#include <unistd.h> 
int main() { 
    void *shared; 
    sem_t *sem; 
    int counter, *data; 
    pid_t pid; 
    srand(time(NULL)); 
    shared = mmap(NULL, sysconf(_SC_PAGE_SIZE), PROT_READ | PROT_WRITE, 
      MAP_ANONYMOUS | MAP_SHARED, -1, 0); 
    sem_init(sem = shared, 1, 1); 
    data = shared + sizeof(sem_t); 
    counter = *data = 0; 
    pid = fork(); 
    while (1) { 
     sem_wait(sem); 
     if (pid) 
      printf("ping>%d %d\n", data[0] = rand(), data[1] = rand()); 
     else if (counter != data[0]) { 
      printf("pong<%d", counter = data[0]); 
      sleep(2); 
      printf(" %d\n", data[1]); 
     } 
     sem_post(sem); 
     if (pid) sleep(1); 
    } 
} 

これはかなりダムテストですが、それは動作します:

$ cc -o test -lrt test.c 
$ ./test 
ping>2098529942 315244699 
pong<2098529942 315244699 
pong<1195826161 424832009 
ping>1195826161 424832009 
pong<1858302907 1740879454 
ping>1858302907 1740879454 
ping>568318608 566229809 
pong<568318608 566229809 
ping>1469118213 999421338 
pong<1469118213 999421338 
ping>1247594672 1837310825 
pong<1247594672 1837310825 
ping>478016018 1861977274 
pong<478016018 1861977274 
ping>1022490459 935101133 
pong<1022490459 935101133 
... 

セマフォは、2つのプロセス間で共有されているので、pong sがにもかかわらず、ping sからインターリーブされたデータを得ることはありませんsleep s。

1

これは、POSIX共有メモリのミューテックスを使用して行うことができます。

pthread_mutexattr_t attr; 
int pshared = PTHREAD_PROCESS_SHARED; 
pthread_mutexattr_init(&attr); 
pthread_mutexattr_setpshared(&attr, &pshared); 

pthread_mutex_init(&some_shared_mmap_structure.mutex, &attr); 
pthread_mutexattr_destroy(&attr); 

今、あなたは普通のpthread_mutex_lockのを使用して& some_shared_mmap_structure.mutexのロックを解除してロックできます()それがマッピングされてい複数のプロセスからなどのコールは、。 (未テスト)

struct msemaphore { 
    pthread_mutex_t mut; 
}; 

#define MSEM_LOCKED 1 
#define MSEM_UNLOCKED 0 
#define MSEM_IF_NOWAIT 1 

msemaphore *msem_init(msemaphore *msem_p, int initialvalue) { 
    pthread_mutex_attr_t attr; 
    int pshared = PTHREAD_PROCESS_SHARED; 

    assert((unsigned long)msem_p & 7 == 0); // check alignment 

    pthread_mutexattr_init(&attr); 
    pthread_mutexattr_setpshared(&attr, &pshared); // might fail, you should probably check 
    pthread_mutex_init(&msem_p->mut, &attr); // never fails 
    pthread_mutexattr_destroy(&attr); 

    if (initialvalue) 
     pthread_mutex_lock(&attr); 

    return msem_p; 
} 

int msem_remove(msemaphore *msem) { 
    return pthread_mutex_destroy(&msem->mut) ? -1 : 0; 
} 

int msem_lock(msemaphore *msem, int cond) { 
    int ret; 
    if (cond == MSEM_IF_NOWAIT) 
     ret = pthread_mutex_trylock(&msem->mut); 
    else 
     ret = pthread_mutex_lock(&msem->mut); 

    return ret ? -1 : 0; 
} 

int msem_unlock(msemaphore *msem, int cond) { 
    // pthreads does not allow us to directly ascertain whether there are 
    // waiters. However, a unlock/trylock with no contention is -very- fast 
    // using linux's pthreads implementation, so just do that instead if 
    // you care. 
    // 
    // nb, only fails if the mutex is not initialized 
    return pthread_mutex_unlock(&msem->mut) ? -1 : 0; 
} 
+0

OPがセマフォを必要とすることはほとんどありませんが(ほぼすべての目的でmutexで十分です)、実装したものはセマフォではありません。ヒント:初期値は非負の値をとることができ、ゼロは* locked *を意味します。 – ephemient

+0

しかし、OPにリンクされているのは、少なくともセマフォと呼ばれるミューテックスだけでした。少なくとも、問題のドキュメントを読んでからです。 – bdonlan

+0

もう一度読めば、正しいと思われます。どのような誤解を招く名前! – ephemient