设为首页 加入收藏

TOP

linux fork进程请谨慎多个进程/线程共享一个 socket连接,会出现多个进程响应串联的情况。(二)
2019-08-15 23:30:23 】 浏览:51
Tags:linux fork 进程 谨慎 多个 线程 共享 一个 socket 连接 出现 响应 串联 情况
me'=>$time,'pid'=>$pid); } } } /** * 杀死子进程 * @param int $pid */ public function killChild($pid = 0) { if ($pid > 0) { posix_kill($pid, SIGTERM); if ($this->killCallback !== null) call_user_func($this->killCallback); } } /** * 该进程是否主进程 是返回true 不是返回false * @return bool */ public function parentCheck() { if ($this->myPID() == $this->parentPID) { return true; } else { return false; } } public function pidDead($pid = 0) { if ($pid > 0) { return pcntl_waitpid($pid, $status, WUNTRACED OR WNOHANG); } else { return 0; } } public function setCallback($callback = null) { $this->shutdownCallback = $callback; } public function setKillCallback($callback = null) { $this->killCallback = $callback; } /** * 返回子进程个数 * @return int */ public function childCount() { return count($this->myChildren); } public function runParentCode() { if (!$this->complete) { return $this->parentCheck(); } else { if ($this->shutdownCallback !== null) call_user_func($this->shutdownCallback); return false; } } public function runChildCode() { return !$this->parentCheck(); } /** * 进程池是否已满 * @return bool */ public function spawnReady() { if (count($this->myChildren) < $this->maxChildren) { return true; } else { return false; } } public function shutdown() { while($this->childCount()) { $this->checkChildren(); $this->tick(); } $this->complete = true; } public function tick() { usleep($this->sleepCount); } public function exec($proc, $args = null) { if ($args == null) { pcntl_exec($proc); } else { pcntl_exec($proc, $args); } } } View Code

 

解释一下testFork.php做的事情:子进程从父进程fork出来之后,父子进程各自从redis中取数据,父进程取parent这个key的数据。子进程取child这个key的数据

终端的输出结果是:

parent:parent
parent:parent
parent:children
chlidren:parent  

 

很显然,在偶然的情况下:子进程读到了父进程的结果、父进程读到了子进程该读的结果。

先说结论,再看原因。

linux fork进程请谨慎多个进程/线程共享一个 socket连接,会出现多个进程响应串联的情况。 

 

 有经验的朋友应该会想起unix网络编程中在写并发server代码的时候,fork子进程之后立马关闭了子进程的listenfd,原因也是类似的。

 

昨天,写这份代码的同学,自己闷头查了很长时间,其实还是对于fork没有重分了解,匆忙的写下这份代码。

使用父子进程模式之前,得先问一下自己几个问题:

1.你的代码真的需要父子进程来做吗?(当然这不是今天讨论的话题,对于php业务场景而言、我觉得基本不需要)

2.fork产生的子进程到底与父进程有什么关系?复制的变量相互间的更改是否受影响?

 

《UNIX系统编程》第24章进程的创建 中对上面的两个问题给出了完美的回答、下面我摘抄几个知识点:

1.fork之后父子进程将共享代码文本段,但是各自拥有不同的栈段、数据段及堆段拷贝。子进程的栈、数据从fork一瞬间开始是对于父进程的完全拷贝、每个进程可以更改自己的数据,而不要担心相互影响!

2.fork之后父子进程同时开始从fork点向下执行代码,具体fork之后CPU会调度到谁?不一定!

3.执行fork之后,子进程将拷贝父进程的文件描述符副本,指向同一个文件句柄(包含了当前文件读写的偏移量等信息)。对于socket而言,其实是复用了同一个socket,这也是文章开头提到的问题所在。

 

 

那么再回头看开始提到的问题,当fork之后,父子进程同时共享同一条redis连接。

一条tcp连接唯一标识的办法是那个四元组:clientip + clientport + serverip + serverport

那当两个进程同时指向了一个socket,socket改把响应体给谁呢?我的理解是CPU片分到谁谁会去读取,当然这个理解也可能是错误的,在评论区给出你的理解,谢谢

 

文章的最后谈几点我的想法:

1.php业务场景下需要使用多进程模式的并不多,如果你觉得真的需要使用fork来完成业务,可以先思考一下,真的需要吗?

2.当遇到问题的时候,最先看的还应该是你所使用技术的到底做了啥,主动与身边人沟通

3.《UNIX系统编程》是一本好书,英文名是《The Linux Programming Interface》,简称《TLPI》,我在这本书里找到了很多我想找到的答案。作为一个写php的、读C的程序员来说,简单易懂。

比如进程的创建、IO相关主题、select&poll&信号驱动IO&epoll,特别是事件驱动这块非常推荐阅读,后面我也会在我弄明白网络请求到达网卡之后、linux内核做了啥?然后结合事件驱动再记一篇我的理解。

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇PHP 是如何做垃圾回收的 下一篇PHP在无限分类时注意的一些问题(..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目