网站首页 > 基础教程 正文
开发的过程中,偶尔会碰到将大量的数据进行同步,PHP作为单线程,不能使用多线程的思路来发挥多核的优势。
虽然不能创建线程,但是我们可以创建进程,一样可以达到利用多核CPU的目的。
涉及到资源的并发使用问题,多线程、多进程都需要并发安全地使用资源。
简单例子
实验代码
ceshi.php
<?php
// 开启多个进程,同时执行一个任务
function task($startID) {
$pid = posix_getpid(); // 获取进程号
printf("进程号:%d,执行任务: %d - %d\n", $startID, $startID + 1000);
}
for ($i = 0; $i < 5; $i++) {
$id = pcntl_fork();
if ($id == -1) {
die("pcntl fork failed");
} elseif($id) {
// parent process
continue;
} else {
// child process
task($i * 1000);
exit;
}
}
printf("父进程结束\n");
运行结果
php ceshi.php
上图中我们开启了五个进程,每个进程执行一段任务,隔离了任务,防止不同进程执行相同的任务。
不知道大家有没有注意到,上图中父进程退出了,为什么还能打印出进程号为 594 号的输出呢。这是因为子进程继承了父进程打开的文件描述符,如:标准输出(stdout)、标准输入(stdin)、标准错误(stderr)。这三个描述符都是对应终端的,所以会输出到终端,就是我们执行命令的窗口。
守护进程实现
上面脚本如果是一个无限循环,日志将会一直打印,当用户Session终端退出,任务也会随着退出。这时候我们就需要使用守护进程去实现这个任务进程,守护进程一旦执行,终端关闭与否,任务进程都会运行。关闭守护进程可以使用kill命令,或者在任务执行完成之后直接退出就可以。
实验代码
ceshi.php
<?php
// 开启多个进程,同时执行一个任务
function task($startID) {
$pid = posix_getpid();
while (true) {
file_put_contents($pid."log.txt", "任务{$startID}-". ($startID+1000) ."执行完毕\n", FILE_APPEND);
sleep(5);
}
}
$pid = pcntl_fork();
if ($pid == -1){
die("pcntl fork failed: first time");
} elseif ($pid > 0) {
//父进程退出,子进程不是进程组长,以便接下来顺利创建新会话
exit;
}
posix_setsid(); // 脱离终端,设置新的session会话
posix_setuid(33); // 设置进程用户
posix_setgid(33); // 设置进程组
fclose(STDOUT); // 关闭标准输出
fclose(STDIN); // 关闭标准输入
fclose(STDERR); // 关闭标准错误
cli_set_process_title("ceshi"); // 设置进程名字
// 循环创建子进程处理任务
for ($i = 0; $i < 5; $i++) {
$id = pcntl_fork();
if ($id == -1) {
die("pcntl fork failed");
} elseif($id) {
// parent process
continue;
} else {
// child process
task($i * 1000);
exit;
}
}
运行结果
php ceshi.php
守护进程的代码里面已经注释了实现逻辑,截图也已经将关键的命令以及结果做了注释,大家可以结合着看,我这里就不多做介绍。
实现守护进程的过程中我自己踩到一个坑,这里分享下,避免踩坑:
在关闭标准输入、标准输出、标准错误的文件描述符之后,就不要再使用 printf 函数,这个函数会将结果打印到标准输出,如果强行打印会致使程序退出,ps 也查不到相关运行的进程。
- 上一篇: 介绍一个早期phpMyAdmin软件的漏洞
- 下一篇: 「真实案例」php文件锁产生的问题和解决方案
猜你喜欢
- 2024-11-23 西邮冯景瑜团队挖掘到CVE漏洞,被国家信息安全漏洞库收录公布
- 2024-11-23 PHP操作SQL数据库增删改查的代码
- 2024-11-23 简单轻量级的php的web防火墙,拦截SQL注入和XSS攻击
- 2024-11-23 PHP操作FTP类实现(上传、下载、移动、创建)的方法
- 2024-11-23 PHP7开发API离不开签名验证,你是如何设计?
- 2024-11-23 PHP连接msSQL数据库方法
- 2024-11-23 「PHP」如何使用imap协议接收邮件
- 2024-11-23 php 多进程是如何实现的?
- 2024-11-23 PHP自动加载学习记录
- 2024-11-23 PHP安全编码规范不可忽略
- 最近发表
- 标签列表
-
- gitpush (61)
- pythonif (68)
- location.href (57)
- tail-f (57)
- pythonifelse (59)
- deletesql (62)
- c++模板 (62)
- css3动画 (57)
- c#event (59)
- linuxgzip (68)
- 字符串连接 (73)
- nginx配置文件详解 (61)
- html标签 (69)
- c++初始化列表 (64)
- exec命令 (59)
- canvasfilltext (58)
- mysqlinnodbmyisam区别 (63)
- arraylistadd (66)
- node教程 (59)
- console.table (62)
- c++time_t (58)
- phpcookie (58)
- mysqldatesub函数 (63)
- window10java环境变量设置 (66)
- c++虚函数和纯虚函数的区别 (66)