php sem_get(),关于php中sem_get failed for key no space left on device问题的解决方案...

有时我们在处理并发操作时会使用信号量做进程同步,如下一个php应用的例子

1

2

3

4

$sem_id =

sem_get($id,1,0666,true);

sem_acquire($sem_id);

...

我们release了资源,但是系统没有真正的释放资源

通过

[root@localhost ~]# ipcs -s

------ Semaphore Arrays --------

key semid owner perms nsems

0x0002152f 32769 www 666 3

0x00019fff 65538 www 666 3

0x00019ff1 98307 www 666 3

....

我们知道 ,Semaphores 会很快达到上限

#ipcs -l

...

max semaphores per array = 250

...

系统默认是250个,于是当我们再次通过sem_get()获取资源句柄时就会得到以下错误:

Warning: sem_get() [function.sem-get]: failed for key 0x(n): No

space left on device in ...

最后修改程序,加入

sem_remove($sem_id);

新的问题出现了

sem_release() [function.sem-release]:

failed to release key 0xxxxxxx: Invalid argument in...

这是由于出现竞争,假设a进程等待b进程,b完成时执行了sem_remove,所以a进程执行sem_release就会出错,因为信号里已经被释放了,故提示信号量无效.

所以php下的信号量不适用于需要创建大量不同锁的环境.

折衷的方法就是将锁hash到一个范围:

如:

$sem_id = sem_get($id % 100,1,0666,true);

...

另外记得信号量上限的配置,这里是调整到2048

sysctl -w kernel.sem="1024 32000 100 2048"

echo "kernel.sem=1024 32000 100 2048"

>> /etc/sysctl.conf

最后想提一个非常重要的问题,当sem_get第4个参数auto_release为true时,php的信号里的作用范围只限当前区间,如:

function lock()

{ $sem_id = sem_get($id,1,0666,true);

sem_acquire($sem_id);

...

} lock ();

//函数中调用了信号量,作用域只在函数内

lock();

//

再次调用不会死锁,因为第一个信号量锁定作用已消失

------------------------------------------------------

文章来源:http://lajabs.net/2011/02/15/信号量使用时的一些问题/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值