msemaphore在Linux上?

AIX(和HPUX,如果有人关心的话)有一个很好的叫做msemaphores的小function,可以很容易地同步由多个进程共享的内存映射文件的粒度碎片(例如logging)。 有谁知道有什么可比的Linux?

要清楚的是,msemaphore的function是通过下面的相关链接来描述的。

如果sem_init(3)pshared ”的第二个参数为true, POSIX信号量可以放在进程之间共享的内存中。 这似乎与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 ... 

由于信号量在两个进程之间共享,所以pong不会从sleep获得交错的数据。

这可以使用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。

事实上,你甚至可以用这个方式实现msem API:(未经测试)

 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; } 

在Linux下,你可以用SysV共享内存来实现你想要的东西; 快速的谷歌搜索出现了这个(相当老的)指南 ,可能有帮助。