美文网首页
进程 多进程-进程间通讯---共享内存与信号量

进程 多进程-进程间通讯---共享内存与信号量

作者: 明天你好_ee9a | 来源:发表于2020-07-17 13:56 被阅读0次

上文说到可以通过消息队列去创建任务,消费任务。本文利用共享内存(传说中最快的进程通讯方法) 与 信号量(与锁概念有差异,锁是锁定资源,信号量是被捕捉到的时候执行相应的代码)

  • 共享内存 :顾名思义,就是多个进程一起读取/写入同一个内存块
  • 信号量:信号量是一种变量或抽象数据类型,用于控制并发系统中多个进程对公共资源的访问

说一些日常生活中的例子
以一个停车场的运作为例。简单起见,假设停车场只有三个车位(共享内存),一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆直接进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入外面的一辆进去,如果又离开两辆,则又可以放入两辆,如此往复。 在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。

上代码

<?php
$ppid = posix_getpid();
echo "父进程的进程号:{$ppid}".PHP_EOL;
$childList = array();

// 创建共享内存,创建信号量,定义共享key
$shm_id = ftok(__FILE__,'m');
$sem_id = ftok(__FILE__,'s');
//共享内存
$shareMemory = shm_attach($shm_id);
//信号量
$signal = sem_get($sem_id);

const SHARE_KEY = 1;

// 生产者
function producer(){
    global $shareMemory;
    global $signal;
    $pid = posix_getpid();
    $repeatNum = 5;
    for ( $i = 1; $i <= $repeatNum; $i++) {
        // 获得信号量
        sem_acquire($signal);
        
        if (shm_has_var($shareMemory,SHARE_KEY)){
            // 有值,加一
            $count = shm_get_var($shareMemory,SHARE_KEY);
            $count ++;
            shm_put_var($shareMemory,SHARE_KEY,$count);
            echo "({$pid}) count: {$count}".PHP_EOL;
        }else{
            // 无值,初始化
            shm_put_var($shareMemory,SHARE_KEY,0);
            echo "({$pid}) count: 0".PHP_EOL;
        }
        // 用完释放,释放后让其他进程进行捕获,执行然后执行
        sem_release($signal);
        sleep(2);
    }
}

//创建进程
function createProgress($callback){
    $pid = pcntl_fork();
    if ( $pid == -1) {
        // 创建失败
        exit("进程创建失败".PHP_EOL);
    } else if ($pid == 0) {
        // 子进程执行程序
        $pid = posix_getpid();
        $callback();
        exit("({$pid}) 子进程执行完毕并退出".PHP_EOL);
    }else{
        // 父进程执行程序
        return $pid;
    }
}

// 3个写进程
for ($i = 0; $i < 3; $i ++ ) {
    $pid = createProgress('producer');
    $childList[$pid] = 1;
    echo "创建子进程。进程号为: {$pid}".PHP_EOL;
}

// 等待所有子进程结束
while(!empty($childList)){
    $childPid = pcntl_wait($status);
    if ($childPid > 0){
        unset($childList[$childPid]);
    }
}
// 释放共享内存与信号量
shm_remove($shareMemory);
sem_remove($signal);
echo "({$ppid}) 主进程执行完毕".PHP_EOL;

执行结果


image.png

这样子虽然是多个进程同时对共享内存进行操作,但是也有有序的,获得信号量的子进程就对共享内存进行io操作,操作完成后释放,让其他进程捕获。未捕获信号量的进程则等待

相关文章

  • 进程/线程/协程

    进程 FastCGI多进程 线程 多线程 , 线程安全 协程 跨进程通讯 进程间通信(IPC) (1)共享内存,独...

  • 进程间通讯

    一、进程间通讯的方式进程间通讯的方式有很多,常用的有共享内存(内存映射文件、共享内存DLL、剪切板等)、命名管道和...

  • 【充电】《Nginx核心知识100讲》nginx 共享内存

    所有worker进程协同工作的关键:共享内存 1.nginx 进程间的通讯方式 nginx进程间通讯有两种,信号跟...

  • unity面试题1(进程,线程和协程的区别)

    进程 进程之间不共享任何状态,进程的调度由操作系统完成,每个进程都有自己的独立的内存空间,进程间的通讯主要是通过信...

  • 并发编程

    1.进程间的通讯方式 1.1 共享内存1.2 消息队列1.3 管道1.4 信号量(相当于锁机制) 2. 线程...

  • Android

    ContentProvider 作用 进程间数据共享 即跨进程通信 原理 Binder进程间通信结合匿名共享内存(...

  • Linux

    操作系统 Linux进程间通信方式:Socket、共享内存、消息队列、信号量 epoll、select、poll ...

  • Nginx 进程管理,你需要了解哪些?

    Nginx 是一个多进程的程序,多进程之间进行通讯可以使用共享内存、信号等。当做进程间管理的时候,通常只使用信号。...

  • PHP进程通信-信号量和共享内存

    信号量与共享内存。共享内存是最快是进程间通信方式,因为n个进程之间并不需要数据复制,而是直接操控同一份数据。实际上...

  • 共享内存

    Linux进程间通信 - 共享内存

网友评论

      本文标题:进程 多进程-进程间通讯---共享内存与信号量

      本文链接:https://www.haomeiwen.com/subject/pdoxkktx.html