我已经实现了一个访问控制,用于插入到用于预订服务的数据库表中。它工作正常一段时间,然后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网站上的步骤进行了操作。
答案 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
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);
它将起作用