phper 請(qǐng)了解進(jìn)程調(diào)度策略,CPU 時(shí)間片,進(jìn)程控制【創(chuàng)建,銷毀,回收,進(jìn)程信號(hào)】與及進(jìn)程運(yùn)行流程和基本的進(jìn)程組,信號(hào)中斷原理,以及進(jìn)程之間的關(guān)系。
關(guān)于進(jìn)程的更多內(nèi)容可參考本人前面擼過(guò)的文章或是百度了解。
進(jìn)程的通信:
匿名管道,命名管道,消息隊(duì)列,內(nèi)存共享,socketpair 請(qǐng)自行擼代碼測(cè)試哦
進(jìn)程的調(diào)度算法:
輪詢,隨機(jī)分發(fā),計(jì)分板等策略或是搞個(gè)優(yōu)先極或是隊(duì)列,或是堆棧等基本的算法【自己去發(fā)揮哦】
進(jìn)程池:
擼過(guò) tcp 的話應(yīng)該知道要能處理多個(gè)客戶端,就得用 IO 復(fù)用技術(shù)【事件多路分發(fā)器】或是多進(jìn)程以及多線程,每來(lái)一個(gè)客戶端就 fork 一個(gè)進(jìn)程或是線程,那樣的話上下文切換成本特別高,所以咱們先創(chuàng)建好一組進(jìn)程【進(jìn)程池】,等客戶端連接上來(lái)的時(shí)候,通過(guò)某種算法【我們用的輪詢】來(lái)選擇某個(gè)進(jìn)程投遞任務(wù)來(lái)干活,這樣的話就不用創(chuàng)建又銷毀來(lái)回折騰了,提升它的效率。下面是 PHP 代碼版本的實(shí)現(xiàn)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
<?php /** * Created by PhpStorm. * User: 1655664358@qq.com * Date: 2019/1/12 * Time: 16:18 */ $flag = 1; class process { public $pid ; public $name ; public $file ; public $num ; } class instance { public $processIdx ; public $proc = []; public $processNum ; } function sigHandler( $sigNo ) { global $flag ; $flag = 0; echo "信號(hào)中斷處理" .PHP_EOL; } function processPool(instance & $instance , $num ) { if (! $instance || $num ==0){ fprintf (STDERR, "%s" , "參數(shù)錯(cuò)誤" ); return 1; } $instance ->processIdx = 0; $instance ->processNum = $num ; pcntl_signal(SIGINT, 'sigHandler' ); pcntl_signal(SIGTERM, 'sigHandler' ); $process = new process(); for ( $i =1; $i <= $num ; $i ++){ $instance ->proc[ $i ] = clone $process ; $instance ->proc[ $i ]->file = $i ; $instance ->proc[ $i ]->pid = pcntl_fork(); $instance ->processIdx = $i ; if ( $instance ->proc[ $i ]->pid<0){ exit ( "進(jìn)程創(chuàng)建失敗" ); } else if ( $instance ->proc[ $i ]->pid>0){ //nothing continue ; } else { worker( $instance ); } } master( $instance ); $exitProcess = []; while (1){ for ( $i =1; $i <= $num ; $i ++){ //非阻塞方式回收子進(jìn)程 pcntl_waitpid( $instance ->proc[ $i ]->pid, $status ,WNOHANG); if ( $status ){ $exitProcess [] = $instance ->proc[ $i ]->pid; fwrite(STDOUT, "worker#" . $instance ->proc[ $i ]->pid. "-" . $status ,30); } } if ( count ( $exitProcess )== $instance ->processNum){ exit (0); } usleep(1000); } } //簡(jiǎn)單的輪詢算法 自己可以用隊(duì)列,隨機(jī),鏈表,棧鏈,二叉樹(shù)啥的折騰 function roundRobin(& $instance , $roll ) { /** @var instance $instance */ return $instance ->proc[ $roll % $instance ->processNum+1]; } function master(& $instance ) { /** @var instance $instance */ fprintf (STDOUT, "master 進(jìn)程 %d\n" , $instance ->processIdx); global $flag ; $roll = 0; while ( $flag ){ pcntl_signal_dispatch(); /** @var process $process */ $process = roundRobin( $instance , $roll ++); echo "輪詢的進(jìn)程:" . $process ->pid.PHP_EOL; $file = $process ->file; posix_mkfifo( $file ,0666); $fd = fopen ( $file , "w" ); fwrite( $fd , "hi" ,2); sleep(1); } for ( $i =1; $i <= $instance ->processNum; $i ++){ posix_kill( $instance ->proc[ $i ]->pid,9); } fprintf (STDOUT, "master shutdown %d\n" , $instance ->processIdx); } function getProcess(& $instance ) { /** @var instance $instance */ return $instance ->proc[ $instance ->processIdx]; } function worker(& $instance ) { /** @var process $process */ $process = getProcess( $instance ); while (1){ $file = $process ->file; posix_mkfifo( $file ,0666); $fd = fopen ( $file , "r" ); $content = fread ( $fd ,10); fprintf (STDOUT, "worker#%d讀取的內(nèi)容:%s file=%d\n" ,posix_getpid(), $content , $file ); } exit (0); } $instance = new instance(); processPool( $instance ,5); |
效果
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://learnku.com/articles/36316