phper 請了解進程調度策略,CPU 時間片,進程控制【創建,銷毀,回收,進程信號】與及進程運行流程和基本的進程組,信號中斷原理,以及進程之間的關系。
關于進程的更多內容可參考本人前面擼過的文章或是百度了解。
進程的通信:
匿名管道,命名管道,消息隊列,內存共享,socketpair 請自行擼代碼測試哦
進程的調度算法:
輪詢,隨機分發,計分板等策略或是搞個優先極或是隊列,或是堆棧等基本的算法【自己去發揮哦】
進程池:
擼過 tcp 的話應該知道要能處理多個客戶端,就得用 IO 復用技術【事件多路分發器】或是多進程以及多線程,每來一個客戶端就 fork 一個進程或是線程,那樣的話上下文切換成本特別高,所以咱們先創建好一組進程【進程池】,等客戶端連接上來的時候,通過某種算法【我們用的輪詢】來選擇某個進程投遞任務來干活,這樣的話就不用創建又銷毀來回折騰了,提升它的效率。下面是 PHP 代碼版本的實現
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: [email protected] * 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 "信號中斷處理" .PHP_EOL; } function processPool(instance & $instance , $num ) { if (! $instance || $num ==0){ fprintf (STDERR, "%s" , "參數錯誤" ); 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 ( "進程創建失敗" ); } else if ( $instance ->proc[ $i ]->pid>0){ //nothing continue ; } else { worker( $instance ); } } master( $instance ); $exitProcess = []; while (1){ for ( $i =1; $i <= $num ; $i ++){ //非阻塞方式回收子進程 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); } } //簡單的輪詢算法 自己可以用隊列,隨機,鏈表,棧鏈,二叉樹啥的折騰 function roundRobin(& $instance , $roll ) { /** @var instance $instance */ return $instance ->proc[ $roll % $instance ->processNum+1]; } function master(& $instance ) { /** @var instance $instance */ fprintf (STDOUT, "master 進程 %d\n" , $instance ->processIdx); global $flag ; $roll = 0; while ( $flag ){ pcntl_signal_dispatch(); /** @var process $process */ $process = roundRobin( $instance , $roll ++); echo "輪詢的進程:" . $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讀取的內容:%s file=%d\n" ,posix_getpid(), $content , $file ); } exit (0); } $instance = new instance(); processPool( $instance ,5); |
效果
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://learnku.com/articles/36316