0%

PHP开发SPL总结

PHP标准库 (SPL)

PHP标准库(SPL)提供一些数据结构,迭代器,接口和函数等。

数据结构

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
/**
* 栈(先进后出)
*/
$stack = new SplStack();
$stack->push('data1');//入栈(先进后出)
$stack->push('data2');//入栈
$stack->push('data3');//入栈

echo $stack->pop(), PHP_EOL;//出栈
echo $stack->pop(), PHP_EOL;//出栈
echo $stack->pop(), PHP_EOL;//出栈


/**
*队列(先进先出)
*/
$queue = new SplQueue();
$queue->enqueue('data4');//入队列
$queue->enqueue('data5');//入队列
$queue->enqueue('data6');//入队列

echo $queue->dequeue(), PHP_EOL;//出队列
echo $queue->dequeue(), PHP_EOL;//出队列
echo $queue->dequeue(), PHP_EOL;//出队列



/**
* 堆
*/
$heap = new SplMinHeap();
$heap->insert('data8');//入堆
$heap->insert('data9');//入堆
$heap->insert('data10');//入堆


echo $heap->extract(), PHP_EOL;//从堆中提取数据
echo $heap->extract(), PHP_EOL;//从堆中提取数据
echo $heap->extract(), PHP_EOL;//从堆中提取数据



/**
* 固定数组(不论使不使用,都会分配相应的内存空间)
*/
$array = new SplFixedArray(15);
$array['0'] = 54;
$array['6'] = 69;
$array['10'] = 32;
var_dump($array);

异常

  • RuntimeException 运行时异常

函数

  • spl_autoload_register() 注册自动装载函数

进程控制(pcntl)

pcntl_fork()

在当前进程当前位置产生分支, fork是创建了一个子进程,父进程和子进程 都从fork的位置开始向下继续执行,不同的是父进程执行过程中,得到的fork返回值为子进程号,而子进程得到的是0。

语法:pcntl_fork ( ) : int

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

$pid = pcntl_fork();
//父进程和子进程都会执行下面代码
if ($pid == -1) {
//错误处理:创建子进程失败时返回-1.
die('could not fork');
} else if ($pid) {
//父进程会得到子进程号,所以这里是父进程执行的逻辑
pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。
} else {
//子进程得到的$pid为0, 所以这里是子进程执行的逻辑。
}

?>

pcntl_wait()

等待或返回 fork 的子进程状态. wait函数挂起当前进程的执行直到一个子进程退出或接收到一个信号要求中断当前进程或调用一个信号处理函数。如果一个子进程在调用此函数时已经退出(俗称僵尸进程),此函数立刻返回,子进程使用的所有系统资源将被释放。

语法:pcntl_wait ( int &$status , int $options = 0 , array &$rusage = ? ) : int

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

DEFINE(MAXPROCESS,25);

for ($i=0;$i<100;$i++){
$pid = pcntl_fork();

if ($pid == -1) {
die("could not fork");
} elseif ($pid) {
echo "I'm the Parent $i\n";
$execute++;
if ($execute>=MAXPROCESS){
pcntl_wait($status);
$execute--;
}
} else {
echo "I am the child, $i pid = $pid \n";
sleep(rand(1,3));
echo "Bye Bye from $i\n";
exit;
}
}
?>

pcntl_async_signals()

作用:开启/关闭异步信号处理或返回当前的设定

语法:bool pcntl_async_signals ([ bool $on = NULL ] )

pcntl_alarm

为进程设置一个alarm闹钟信号, 创建一个计时器,在指定的秒数后向进程发送一个SIGALRM信号。每次对 pcntl_alarm()的调用都会取消之前设置的alarm信号

语法:pcntl_alarm ( int $seconds ) : int

seconds:等待的秒数,如果seconds设置为0,将不会创建alarm信号

示例:

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
/**
* Register the worker timeout handler.
*
* @param \Illuminate\Contracts\Queue\Job|null $job
* @param \Illuminate\Queue\WorkerOptions $options
* @return void
*/
protected function registerTimeoutHandler($job, WorkerOptions $options)
{
// We will register a signal handler for the alarm signal so that we can kill this
// process if it is running too long because it has frozen. This uses the async
// signals supported in recent versions of PHP to accomplish it conveniently.
pcntl_signal(SIGALRM, function () use ($job, $options) {
if ($job) {
$this->markJobAsFailedIfWillExceedMaxAttempts(
$job->getConnectionName(), $job, (int) $options->maxTries, $this->maxAttemptsExceededException($job)
);
}

$this->kill(1);
});

pcntl_alarm(
max($this->timeoutForJob($job, $options), 0)
);
}

pcntl_signal

安装一个信号处理器, pcntl_signal()为signo指定的信号安装一个新的信号处理器

语法:pcntl_signal ( int $signo , callback $handler , bool $restart_syscalls = true ) : bool

1
2
3
4
5
6
7
8
9
10
11
12
13
pcntl_async_signals(true);

pcntl_signal(SIGTERM, function () {
$this->shouldQuit = true;
});

pcntl_signal(SIGUSR2, function () {
$this->paused = true;
});

pcntl_signal(SIGCONT, function () {
$this->paused = false;
});

操作系统接口(posix)

getmypid()

作用:获取当前进程id

语法:int getmypid ( void )

posix_kill

发送一个信号给进程

语法:bool posix_kill ( int $pid , int $sig )

1
2
3
if (extension_loaded('posix')) {
posix_kill(getmypid(), SIGKILL);
}