Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/234.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在RAII-like php类中使用共享内存和信号量删除的正确策略_Php_Linux_Semaphore_Shared Memory_Pcntl - Fatal编程技术网

在RAII-like php类中使用共享内存和信号量删除的正确策略

在RAII-like php类中使用共享内存和信号量删除的正确策略,php,linux,semaphore,shared-memory,pcntl,Php,Linux,Semaphore,Shared Memory,Pcntl,这种情况何时发生? 如果您使用共享内存和信号量进行interprocess锁定(with),那么您应该关注信号量和共享内存段的生命周期。例如,您正在编写BackgroundWorker应用程序,并使用主进程和某些子进程(分叉)进行作业处理。在它们之间使用共享内存和信号量是IPC的好主意。而且RAII类似于围绕shm_xxx和sem_xxx php函数的类包装器看起来也是个好主意 示例 class Semaphore { private $file; private $sem

这种情况何时发生?

如果您使用共享内存和信号量进行interprocess锁定(with),那么您应该关注信号量和共享内存段的生命周期。例如,您正在编写BackgroundWorker应用程序,并使用主进程和某些子进程(分叉)进行作业处理。在它们之间使用共享内存和信号量是IPC的好主意。而且
RAII
类似于围绕shm_xxx和sem_xxx php函数的类包装器看起来也是个好主意

示例

class Semaphore
{
     private $file;

     private $sem;

     public function __construct()
     {
        $this->file = tempnam(sys_get_temp_dir(), 's');
        $semKey = ftok($this->file, 'a');

        $this->sem = sem_get($semKey, 1); //auto_release = 1 by default
     }

     public function __destruct()
     {
         if (is_resource($this->sem) {
            sem_remove($this->sem);
         }
     }

     ....
}
不是好的选择-在fork之后,我们在父进程中有一个实例,在子进程中有一个实例。其中任何一个的析构函数都会破坏信号量

为什么重要

大多数linux系统对共享内存计数的信号量都有限制。如果您有一个应用程序,它应该创建和删除信号量的许多共享内存段,那么在进程关闭时自动释放它时,您就不能等待了

问题

使用
c
可以与
IPC\u RMID
一起使用-它标记要删除的段。当当前连接到该段的最后一个进程正确地将其分离时,实际的移除本身就会发生。当然,如果当前没有进程附加到该段,则删除似乎是立即的。它的工作原理类似于简单的参考计数器。但是php没有实现
shmctl

另一种策略-仅在主进程的析构函数中销毁信号量:

class Semaphore
{
     ... 
     private $pid;

     public function __construct()
     {
        $this->pid = getmypid();
        ...
     }

     public function __destruct()
     {
         if (is_resource($this->sem) && $this->pid === getmypid()) {
            sem_remove($this->sem);
         }
     }
     ....
}
所以,问题是

  • 如果有在php中使用IPC\u RMID的方法
  • 在这种情况下应该采用什么策略?仅在主进程中销毁?其他案件
  • 我检查了当前和
    IPC\u RMID
    未使用。但是,PHP使用
    semop()
    ,并使用它设置
    SEM\u UNDO
    标志,以防设置了
    auto\u release
    (请参阅)。但请注意,这在每个流程级别上都有效。所以,如果您使用PHP作为Apache模块,或FCGI或FPM,它可能无法按预期工作。不过,对于CLI来说,它应该可以很好地工作

    对于清理,这取决于“主”是否最后终止

    如果您不知道,您可以自己实现引用计数

    class Semaphore
    {
        static private $m_referenceCount = 0;
    
        public function __construct()
        {
            ++self::$m_referenceCount;
            // aquire semaphore
        }
    
        public function __destruct()
        {
            if (--self::$m_referenceCount <= 0) {
                // clean up
            }
        }
    }
    
    类信号量
    {
    静态私有$m_referenceCount=0;
    公共函数构造()
    {
    ++self::$m_referenceCount;
    //阿奎尔信号灯
    }
    公共函数_udestruct()
    {
    
    如果(--self::$m_referenceCount Yes,我的问题比其他实际的for CLI情况更重要。自制引用计数有一个关键问题-您应该确保引用递增/递减是原子操作。因此您应该有一些进程间锁来实现这一点。Yes?递增或递减整数(在本机大小下)当然是原子的!可能不是原子的是递减和比较操作。但即使不是原子的,它在某些情况下仍然可以可靠地工作:如果您先创建所有实例,然后在任何时候逐个删除它们,而不创建新实例,您将进行清理。可能两次或多次,但至少一次。Shi,我的意思是,原子联锁应该在一些单独的CLI进程中实现——简单情况下是主进程和一个从进程。PHP共享内存实现没有任何原子操作。因此,您应该自行进行锁定。这种锁定的基本实现是共享内存+信号量。但如何了解锁定对象的生命周期E