PHP sem_get函数失败

时间:2016-11-03 11:21:19

标签: php semaphore sysv-ipc

我已经实现了一个访问控制,用于插入到用于预订服务的数据库表中。它工作正常一段时间,然后sem_get()函数失败,尽管我在sem_release()之后调用了sem_get()

case 'room':
    $key = "room";
    $semaphore = sem_get($key, 1, 0666, 1);
    if ($semaphore) {
        sem_acquire($semaphore);
        //do some stuff
        if ($already_reserved_rooms < $max_rooms) {
            $return="ok";
            sem_release($semaphore);
            return $return;
        }
          sem_release($semaphore);
    }
    else {
      //send me mail that semaphore failed 
    }

    return 'no rooms';
    break;

我也应该拨打sem_remove()吗?

我按照this网站上的步骤进行了操作。

3 个答案:

答案 0 :(得分:0)

删除信号量

是的,完成信号量集后,应该调用sem_remove()。否则,信号量集将保留在系统中,直到您将其删除。但是,信号量集持续存在的事实导致没问题,而信号量的数量小于SEMMNS限制:

  

SEMMNS全系统限制信号量的数量:取决于策略(在Linux上,可以通过/proc/sys/kernel/sem的第二个字段读取和修改此限制)。

sem_remove()会立即删除信号量集,唤醒使用此信号量阻止的所有进程。

顺便说一下,您可以使用ipcrm命令从命令行中删除信号量,使用ipcs命令显示有关IPC设施(包括信号量)的信息。

发布信号量

当自动释放标志(sem_release()的第4个参数)打开时,您无需致电sem_get。但只要你不需要获得的“锁定”,释放信号量是个好主意。

sem_release()仅增加内部信号量的值。将其视为解锁操作,与sem_acquire()相反。

sem_get()失败

sem_get()函数在以下情况下返回FALSE

  • PHP参数解析失败(E_ERROR);
  • 信号量存在,但调用进程无权访问该集(E_WARNING);
  • 内存分配错误(E_WARNING);
  • 信号量集的最大数量,或系统范围的最大信号量数量超过(E_WARNING

在每种情况下sem_get都会记录错误或警告。所以你必须检查日志以找出问题的根源。

由于您的代码工作了一段时间,因此不是参数解析问题,而是权限。内存分配问题很少见。因此很可能您的信号量限制已经用完了。查看semget的手册页以供参考。手册页介绍了如何通过/proc/sys/kernel/sem读取和修改限制。

有关sysvsem扩展程序内部的更多信息,请参阅this答案。

答案 1 :(得分:0)

sem_get()的$ key参数是整数,而您将其作为字符串传递。请考虑通过ftok()调用获取整数键。

所以请考虑更换

$key = "room";

到以下代码:

$project = "r"; // Project identifier. This must be a one character string.
$key = ftok(__FILE__, $project);

答案 2 :(得分:0)

sem_get函数在您的情况下返回false,因为您输入的是字符串而不是整数。

替换

$semaphore = sem_get($key, 1, 0666, 1);

作者

$semaphore = sem_get(crc32($key), 1, 0666, 1);

它将起作用