linux上的msemaphore?

linux上的msemaphore?,linux,multithreading,ipc,pthreads,aix,Linux,Multithreading,Ipc,Pthreads,Aix,AIX(和HPUX,如果有人关心的话)有一个很好的小特性,称为msemaphores,它可以轻松地同步多个进程共享的内存映射文件的细粒度片段(例如记录)。有人知道linux中有类似的东西吗 为了清楚起见,msemaphore函数是通过以下相关链接描述的。在Linux下,您可以使用SysV共享内存实现所需功能;快速搜索可能会有所帮助。如果sem_init(3)的第二个参数“pshared”为真,则可以将其放在进程之间共享的内存中。这似乎与msem的功能相同 #include <semapho

AIX(和HPUX,如果有人关心的话)有一个很好的小特性,称为msemaphores,它可以轻松地同步多个进程共享的内存映射文件的细粒度片段(例如记录)。有人知道linux中有类似的东西吗


为了清楚起见,msemaphore函数是通过以下相关链接描述的。

在Linux下,您可以使用SysV共享内存实现所需功能;快速搜索可能会有所帮助。

如果
sem_init(3)
的第二个参数“
pshared
”为真,则可以将其放在进程之间共享的内存中。这似乎与
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);
    }
}
#包括
#包括
#包括
#包括
#包括
#包括
int main(){
无效*共享;
sem_t*sem;
int计数器,*数据;
pid_t pid;
srand(时间(空));
shared=mmap(NULL,sysconf(_SC_PAGE_SIZE),PROT_READ | PROT_WRITE,
MAP|u匿名| MAP|u共享,-1,0);
sem_init(sem=shared,1,1);
数据=共享+大小(sem_t);
计数器=*数据=0;
pid=fork();
而(1){
sem_wait(sem);
如果(pid)
printf(“ping>%d%d\n”,数据[0]=rand(),数据[1]=rand());
else if(计数器!=数据[0]){

printf(“pong这可以使用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()etc调用,从映射了它的多个进程中解锁和锁定&u shared_mmap_structure.mutex

实际上,您甚至可以实现msem API,具体如下:(未经测试)


谢谢。MSemaphore提供了一些便利和简单性,我希望它们已经实现,而不是自己构建。虽然OP不太可能需要信号量(互斥体对于几乎所有目的都足够了),您实现的不是信号量。提示:initialvalue可以接受任何非负值,零表示锁定。但是,OP链接到的是一个互斥体,它只称自己为信号量-至少从我阅读的相关文档来看:)仔细阅读后,你似乎是对的。多么误导人的名字!我的想法是,它被实现为一个信号量,尽管我们把它当作互斥体来看待和使用。我认为这有两个原因。(1)没有限制,只有锁定的进程/线程才能解锁它,从而打破互斥锁的基本原则。(2)MSEM_IF_WAITERS只有在它使用类似于sem_getvalue()[posix]或更可能是带有GETNCNT/GETZCNT选项[sysv]的semop()跟踪时,才对我有意义。我想在IBM或HP打开源代码之前,我们无法确定。由于互斥锁的默认linux pthreads实现不会进行任何检查以确保锁的所有者是解锁它的人,这一部分应该无关紧要:)无论如何,我在文档中没有看到任何关于其他数量的等待者的内容,但您可以扩展它他的方法很容易就能让更多的侍者发出信号——毕竟还有一个可共享的条件变量选项
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);
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;
}