前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Linux进程通信之信号量

Linux进程通信之信号量

作者头像
北溟有鱼QAQ
发布2021-09-10 10:24:15
1.8K0
发布2021-09-10 10:24:15
举报
文章被收录于专栏:北溟有鱼QAQ北溟有鱼QAQ

Linux进程通信之信号量

概念(自行百度):

信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。

PV原语:

信号量有两个原子操作:P操作和V操作,具体意义也要分信号量类型的情况 P() : sem减1 V() : sem加1

分类(以了解的)
  • 二进制信号量(0和1)
  • 信号集(集合数组)

为什么要使用信号量

首先,接下来我们写一段代码,可以理解为多进程读写日志的情况

代码语言:javascript
复制
$file = 'demo24.txt';

$num = 0;

//向文件里写数据

file_put_contents($file,$num);

$pid = pcntl_fork();

//子进程
if($pid==0)
{
    //从文件读取数据
    $sum = (int)file_get_contents($file);
    //循环
    for ($i=1;$i<=10000;$i++)
    {
        $sum+=1;
    }
    //写入文件
    file_put_contents($file,$sum);

    exit(0);

}

//父进程读取文件
$sum = (int)file_get_contents($file);

for ($i=1;$i<=10000;$i++)
{
    $sum+=1;
}
//父进程写入
file_put_contents($file,$sum);

//以上代码是子进程 读取文件内容 并累加1000次,写入文件,父进程读取文件内容,并累加1000次 写入文件, 正常来说,最终得到的值是2000

以上结果可以理解为多进程读文件、写文件操作,正常我们使用命令执行是基本看不出什么问题的,接下来我们写一个简单的shell脚本

代码语言:javascript
复制
#!/bin/bash

int=1

while(($int<=500))
do

php demo24.php
cat demo24.txt

echo -e  "-->\c"
let "int++"
done

给以上编写的shell脚本可执行权限。通过命令chomd +x ./test.sh 完成 如果不了解的可以查看上面的文章 如何编写一个PHP解释器文件 执行shell脚本 ./test.sh,查看结果

我们通过以上的执行结果发现,在执行500次的前提下,有多次数据混乱或者不正确的情况,也可以理解为,在我们多进程编程中,读写日志也会出现这样的情况,也就是我们所说的信号集的问题

PHP中的信号集

首先PHP中,只有四个信号集相关的函数 sem_acquire sem_get sem_releasesem_remove 具体参数和用法,请在PHP手册中查看

修改上面PHP代码
代码语言:javascript
复制
$file = 'demo24.txt';

$num = 0;

//向文件里写数据

file_put_contents($file,$num);

$key = ftok('demo24.php','x');

$semId = sem_get($key,1);//这个地方使用的信号集,但设置为1,可以理解为当成二进制信号集使用


$pid = pcntl_fork();

//子进程
if($pid==0)
{
    //获取信号集
    sem_acquire($semId);
    //从文件读取数据
    $sum = (int)file_get_contents($file);
    //循环
    for ($i=1;$i<=10000;$i++)
    {
        $sum+=1;
    }
    //写入文件
    file_put_contents($file,$sum);
    //释放信号集
    sem_release($semId);

    exit(0);

}

//获取信号集
sem_acquire($semId);

//父进程读取文件
$sum = (int)file_get_contents($file);


for ($i=1;$i<=10000;$i++)
{
    $sum+=1;
}

//父进程写入
file_put_contents($file,$sum);
//释放信号集
sem_release($semId);

//回收子进程
$pid = pcntl_wait($status);

//子进程回收成功
if($pid > 0) {
    fprintf(STDOUT, "ok");
}
修改上面shell代码
代码语言:javascript
复制
#!/bin/bash

int=1

while(($int<=500))
do
php demo24.php

ret=`cat demo24.txt`

if [ $ret -ne 20000 ]
then
 echo "$ret有问题"

fi
echo -e  "-->\c"

let "int++"
done

执行shell 查看结果

发现并没有出现没有使用信号量之前数据错乱的情况,使用ipcs 命令查看,信号量已存在

注意
  • 使用完信号量之后,要使用sem_remove函数删掉信号量,否则会造成系统资源浪费
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2021-09-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Linux进程通信之信号量
    • 概念(自行百度):
      • PV原语:
        • 分类(以了解的)
          • 为什么要使用信号量
            • PHP中的信号集
              • 修改上面PHP代码
              • 修改上面shell代码
              • 注意
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档