php多进程ipc

 

php多进程ipc

由于php没有多线程机制,在一些cpu密集型任务时,只能起多进程操作,于是要考虑进程间通信等场景。
php已有方式包括:管道、消息队列、共享内存、socket,如下重点探究文件与共享内存


<?php
const SHM_VAR = 1;
const M = 20000;
const N = 100000;
const NUM = 10;

/**
 * 1 文件
 */
function pipe()
{
    // 申请锁资源
    $sem_key = ftok( __FILE__, 'b' );
    $sem_id = sem_get( $sem_key );
    // 创建文件
    $pipePath = "pipe1";
    $file = fopen( $pipePath, 'w+');
    fwrite( $file, 0);
    for( $i = 0; $i < NUM; $i++ ){
        $pid = pcntl_fork();
        if( $pid < 0 ){
            exit(-1);
        }
        if( $pid ==0  ) {
            for ($j = M+$i; $j<=N; $j+=NUM) {
                $mark =1;
                for($n=2; $n<$j/2;$n++) {
                    if ($j % $n == 0) {
                        $mark = 0;
                        break;
                    }
                }
                if ($mark) {
                    sem_acquire($sem_id );
                    $file = fopen( $pipePath, 'r+');
                    $count= (int)fread( $file, 5);
                    $count++;
                    $file = fopen( $pipePath, 'w+');
                    fwrite($file, $count);
                    sem_release( $sem_id );
                }
            }
            exit(-1);
        }
    }
    for($n=0;$n<NUM;$n++)
    {
        pcntl_wait($status);
    }
    $file = fopen( $pipePath, 'r+');
    echo (int)fread($file, 5) . PHP_EOL;
}

/**
 * 2 共享内存
 */
function shareMemory()
{
    // 申请锁资源
    $sem_key = ftok( __FILE__, 'b' );
    $sem_id = sem_get( $sem_key );
// 申请共享内存
    $shm_key = ftok( __FILE__, 'm' );
    $shm_id = shm_attach( $shm_key, 1024, 0666 );

//共享内存初始化
    shm_put_var( $shm_id, SHM_VAR, 0 );
    for( $i = 0; $i < NUM; $i++ ){
        $pid = pcntl_fork();
        if( $pid < 0 ){
            exit(-1);
        }
        if( $pid ==0  ) {
            for ($j = M+$i; $j<=N; $j+=NUM) {
                $mark =1;
                for($n=2; $n<$j/2;$n++) {
                    if ($j % $n == 0) {
                        $mark = 0;
                        break;
                    }
                }
                if ($mark) {
                    // 获取锁
                    sem_acquire($sem_id );
                    if( shm_has_var( $shm_id, SHM_VAR ) ){
                        $counter = shm_get_var( $shm_id, SHM_VAR );
                        $counter += 1;
                        shm_put_var( $shm_id, SHM_VAR, $counter );
                    }
                    sem_release( $sem_id );
                }
            }exit(-1);
        }
    }
    for($n=0;$n<NUM;$n++)
    {
        pcntl_wait($status);
    }

    echo '最终结果'.shm_get_var( $shm_id, SHM_VAR ).PHP_EOL;
// 记得删除共享内存数据,删除共享内存是有顺序的,先remove后detach,顺序反过来php可能会报错
    shm_remove( $shm_id );
    shm_detach( $shm_id );
}

/**
 * 3 消息队列
 */
function consumeQueue()
{
    $filePath = __DIR__."/A.php";
    echo $filePath.PHP_EOL;
    $id = ftok($filePath,'m');
    $msgQueue = msg_get_queue($id);
    global $msgType;
    $msgType = 1;
    while (true) {
        msg_receive($msgQueue,$msgType,$msgType,1024,$message);
        echo $message;
    }

}
function produceQueue()
{
    $filePath = __DIR__."/A.php";
    echo $filePath.PHP_EOL;
    $id = ftok($filePath,'m');
    $msgQueue = msg_get_queue($id);
    while (!feof(STDIN)) {
        $line = fread(STDIN, 1024);
        //System V IPC key
        msg_send($msgQueue, MSG_TYPE, $line);
    }
}

/**
 * 4 管道
 */
// 定义管道路径,与创建管道
function myPipe()
{
    $pipe_path = 'test.pipe';
    if(!file_exists($pipe_path)){
        if(!posix_mkfifo($pipe_path,0664)){
            exit("create pipe error!");
        }
    }
    $pid = pcntl_fork();
    if($pid == 0){
        // 子进程,向管道写数据
        $file = fopen($pipe_path,'w');
        while (true){
            fwrite($file,'hello world');
            $rand = rand(1,3);
            sleep($rand);
        }
        exit('child end!');
    }else{
        // 父进程,从管道读数据
        $file = fopen($pipe_path,'r');
        while (true){
            $rel = fread($file,20);
            echo "{$rel}\n";
            $rand = rand(1,2);
            sleep($rand);
        }
    }
}

/**
 * 5 socket
 */
function udp()
{

}

function server1()
{
    set_time_limit( 0 );

    ob_implicit_flush();

    $socket = socket_create( AF_INET, SOCK_DGRAM, SOL_UDP );

    if ( $socket === false ) {

        echo "socket_create() failed:reason:" . socket_strerror( socket_last_error() ) . "\n";

    }

    $ok = socket_bind( $socket, '10.33.150.172', 84 );

    if ( $ok === false ) {

        echo "socket_bind() failed:reason:" . socket_strerror( socket_last_error( $socket ) );

    }

    while ( true ) {

        $from = "";

        $port = 0;

        socket_recvfrom( $socket, $buf,1024, 0, $from, $port );

        echo $buf;

        usleep( 1000 );

    }
}

function client1()
{
    $sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
    while (!feof(STDIN)) {
        $msg = fread(STDIN, 1024);
        $len = strlen($msg);
        socket_sendto($sock, $msg, $len, 0, '10.33.150.172', 84);
    }
    socket_close($sock);
}

/**
 * tcp
 */
function server2()
{
    set_time_limit( 0 );

    ob_implicit_flush();

    $socket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );

    socket_bind( $socket, '10.33.150.172', 84 );

    socket_listen($socket);

    $acpt=socket_accept($socket);

    echo "Acpt!\n";

    while ( $acpt ) {

        $words=fgets(STDIN);

        socket_write($acpt,$words);

        $hear=socket_read($acpt,1024);

        echo $hear;

        if("bye\r\n"==$hear){

            socket_shutdown($acpt);

            break;

        }

        usleep( 1000 );

    }

    socket_close($socket);
}

function client2()
{
    set_time_limit( 0 );

    ob_implicit_flush();

    $socket = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );

    socket_bind( $socket, '10.33.150.172', 84 );

    socket_listen($socket);

    $acpt=socket_accept($socket);

    echo "Acpt!\n";

    while ( $acpt ) {

        $words=fgets(STDIN);

        socket_write($acpt,$words);

        $hear=socket_read($acpt,1024);

        echo $hear;

        if("bye\r\n"==$hear){

            socket_shutdown($acpt);

            break;

        }

        usleep( 1000 );

    }

    socket_close($socket);
}
server2();

文件需要上锁保证进程同步性,同时会存在大量系统调用,读文件、写文件速度不如共享内存快;
共享内存,外加锁机制可是实现多个进程对同一块内存进行操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值