更新时间:2023-02-26 18:05:27
fetch_cache
函数中创建和删除信号量.将sem_get()
放入初始化方法(例如__construct
).sem_remove()
删除信号量,但应使用清理方法(例如__destruct
).或者,您可能希望将它们保留更长的时间-取决于应用程序的逻辑.sem_acquire()
获取锁,然后使用sem_release()
释放锁.fetch_cache
function. Put sem_get()
into an initialization method (such as __construct
).sem_remove()
, but in a cleanup method (such as __destruct
). Or, you might want to keep them even longer - depends on the logic of your application.sem_acquire()
to acquire locks, and sem_release()
to release them.
sem_get()
创建一组三信号量.
sem_get()
Creates a set of three semaphores.
底层C函数semget
不是原子的.当两个进程尝试调用semget
时,可能会竞赛条件.因此,应在某些初始化过程中调用semget
. PHP扩展通过三个信号量克服了这个问题:
The underlying C function semget
is not atomic. There is a possibility of race condition when two processes trying to call semget
. Therefore, semget
should be called in some initialization process. The PHP extension overcomes this issue by means of three semaphores:
信号量0又称SYSVSEM_SEM
被初始化为sem_get
的$max_acquire
,并随着进程的获取而递减.
Is initialized to sem_get
's $max_acquire
and decremented as processes acquires it.
第一个调用sem_get
的进程将获取SYSVSEM_USAGE
信号量的值(请参见下文).对于第一个过程,它等于1
,因为扩展名紧随semget
之后,使用原子semop
函数将其设置为1
.而且,如果这确实是第一个过程,则扩展会将SYSVSEM_SEM
信号量值分配给$max_acquire
.
The first process that called sem_get
fetches the value of SYSVSEM_USAGE
semaphore (see below). For the first process, it equals to 1
, because the extension sets it to 1
with atomic semop
function right after semget
. And if this is really the first process, the extension assigns SYSVSEM_SEM
semaphore value to $max_acquire
.
信号量1又称SYSVSEM_USAGE
使用信号量的进程数.
信号量2又称SYSVSEM_SETVAL
充当内部SETVAL
和GETVAL
操作的锁(请参见man 2 semctl
).例如,将其设置为1
,而将扩展名将SYSVSEM_SEM
设置为$max_acquire
,然后将其重置为零.
Plays a role of a lock for internal SETVAL
and GETVAL
operations (see man 2 semctl
). For example, it is set to 1
while the extension sets SYSVSEM_SEM
to $max_acquire
, then is reset back to zero.
最后,sem_get
将一个结构(包含信号量集ID,键和其他信息)包装到PHP资源中并返回它.
Finally, sem_get
wraps a structure (containing the semaphore set ID, key and other information) into a PHP resource and returns it.
因此,当您仅准备使用信号量时,应该在一些初始化过程中调用它.
So you should call it in some initialization process, when you're only preparing to work with semaphores.
这是$max_acquire
转到的地方发挥作用.
SYSVSEM_SEM
的值(我们称其为semval
)最初等于$max_acquire
. semop()
阻塞,直到semval
大于或等于1
.然后从semval
中减去1
.
SYSVSEM_SEM
's value (let's call it semval
) is initially equal to $max_acquire
. semop()
blocks until semval
becomes greater than or equal to 1
. Then 1
is substracted from semval
.
如果为$max_acquire = 1
,则在第一次调用后semval
变为零,并且对sem_acquire()
填充块的下一次调用直到semval
通过sem_release()
调用恢复.
If $max_acquire = 1
, then semval
becomes zero after the first call, and the next calls to sem_acquire()
fill block until semval
is restored by sem_release()
call.
需要从可用组($max_acquire
)中获取下一个锁"时调用它.
Call it when you need to acquire the next "lock" from the available set ($max_acquire
).
与sem_acquire()
几乎相同,不同之处在于它会增加SYSVSEM_SEM
的值.
Does pretty much the same as sem_acquire()
, except it increments SYSVSEM_SEM
's value.
在您不再需要使用sem_acquire()
先前获得的锁"时调用它.
Call it when you need to no longer need the "lock" acquired previously with sem_acquire()
.
立即删除信号量集,唤醒集合中semop
中阻塞的所有进程(来自IPC_RMID
部分, SEMCTL(2)手册页).
Immediately removes the semaphore set, awakening allprocesses blocked in semop
on the set (from IPC_RMID
section, SEMCTL(2) man page).
因此,这实际上与使用ipcrm
命令删除信号量相同.
So this is effectively the same as removing a semaphore with ipcrm
command.