【问题标题】:Some problems with using semaphores使用信号量的一些问题
【发布时间】:2012-05-02 02:09:47
【问题描述】:

现在我正在处理我的项目,我有一个关于信号量初始化的问题。实际上我在 Mac OS X 上编程,但我试图在 Linux 上编译我的项目,但它没有编译。在 OS X 上,它可以编译,但每次都在初始化时崩溃。

sem_t *mutex_1, *mutex_2, *mutex_3, *reader, *writer;

int initialization_semaphores (void) 
{
    int ERROR = EOK;
    if ((mutex_1 = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, 0, 0)) == MAP_FAILED)
        ERROR = ESEM;
    if ((mutex_2 = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, 0, 0)) == MAP_FAILED)
        ERROR = ESEM;
    if ((mutex_3 = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, 0, 0)) == MAP_FAILED)
        ERROR = ESEM;
    if ((reader = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, 0, 0)) == MAP_FAILED)
        ERROR = ESEM;
    if ((writer = mmap(NULL, sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, 0, 0)) == MAP_FAILED)
        ERROR = ESEM;

    if (ERROR == EOK) {
        if (sem_init(mutex_1, 1, 1) == -1)
            ERROR = ESEM;
        if (sem_init(mutex_2, 1, 1) == -1)
            ERROR = ESEM;
        if (sem_init(mutex_3, 1, 1) == -1)
            ERROR = ESEM;
        if (sem_init(reader, 1, 1) == -1)
            ERROR = ESEM;
        if (sem_init(writer, 1, 1) == -1)
            ERROR = ESEM;
    }
}

当我尝试在 linux 上编译它时,我看到了这个:

/tmp/ccmkN9G7.o: In function `initialization_semaphores':
readerWriter.c:(.text+0x1a2): undefined reference to `sem_init'
readerWriter.c:(.text+0x1cb): undefined reference to `sem_init'
readerWriter.c:(.text+0x1f4): undefined reference to `sem_init'
readerWriter.c:(.text+0x21d): undefined reference to `sem_init'
readerWriter.c:(.text+0x246): undefined reference to `sem_init'
readerWriter.c:(.text+0x275): undefined reference to `shm_open'

对吗? :

int ERROR = EOK;
mutex_1 = sem_open("mutex1", O_CREAT, S_IRUSR | S_IWUSR, 1);   
mutex_2 = sem_open("mutex2", O_CREAT, S_IRUSR | S_IWUSR, 1);  
mutex_3 = sem_open("mutex3", O_CREAT, S_IRUSR | S_IWUSR, 1); 
reader = sem_open("reader", O_CREAT, S_IRUSR | S_IWUSR, 1); 
writer = sem_open("writer", O_CREAT, S_IRUSR | S_IWUSR, 1);   

【问题讨论】:

  • 我注意到你没有从你的函数中返回一个值,即使它被声明为返回一个int。这应该引发警告——它是否引发了任何其他可能有用的警告? (尽管 R.. 总是正确的,但错误或警告中可能仍有一些启发性的东西。)
  • 我从函数中返回了值,实际上我并没有将我的所有函数都粘贴到这里。
  • 顺便说一句,在 cmets 中几乎不可能读取错误和警告; edit发帖可能会更好。 :)
  • 在 Linux 上,您可能需要 -lpthread 和/或 -lrt
  • 是的,我知道,但它不起作用,我无法初始化信号量。每次我收到 ERROR = ESEM

标签: c synchronization semaphore


【解决方案1】:

Mac OSX 不符合标准,不支持sem_init。该函数存在,但它默默地失败或更糟,留下一个不工作的信号量。

我建议您向 Apple 提交错误,因为这是一个长期存在的真实问题,严重影响了应用程序的可移植性。抱怨的人越多,解决问题的希望就越大。

至于解决它,您可以尝试查找/编写所有 POSIX 信号量函数的替代实现并将您的程序链接到该实现,或者您可以切换到使用 sem_open 而不是 mmapsem_init .

(只要您已经为每个信号量映射了整个页面的开销,sem_open 并不会真正花费您更多的钱。当您想要将您的信号量包含在现有的 struct 中。)

【讨论】:

    【解决方案2】:

    在 Mac OSX 上有一个解决方法。

    #include <dispatch/dispatch.h>
    
    typedef dispatch_semaphore_t sem_t;
    
    void sem_init(sem_t* sem, bool is_pshared, unsigned value)
    {
        *sem = dispatch_semaphore_create(value);
    }
    
    static void sem_destroy(sem_t* sem)
    {
        dispatch_release(*sem);
    }
    
    static void sem_post(sem_t* sem)
    {
        dispatch_semaphore_signal(*sem);
    }
    
    static void sem_wait(sem_t* sem)
    {
        dispatch_semaphore_wait(*sem, DISPATCH_TIME_FOREVER);
    }
    

    但是,我不知道该怎么做sem_getvalue() -- 如果有人知道,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-30
      • 2011-10-11
      • 1970-01-01
      • 2013-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多