信号集

信号集是指信号的集合

主程序可以选择阻塞某些信号,被阻塞的信号集体成为阻塞信号集(信号屏蔽字bolck)

当进程阻塞了某个信号,如果在运行期间接受到阻塞的信号时,这个信号的处理程序不会被执行,这个信号会放在被挂起的信号集里(信号未决集)

pcntl_siggromask 用来设置进程的信号屏蔽字

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
echo getmypid();
pcntl_signal(SIGINT,function ($signal){
    fprintf(STDOUT,"%d 接受到信号 %d\n",getmypid(),$signal);
});
// 设置信号屏蔽字,阻塞
$sigset = [SIGINT,SIGUSR1];
pcntl_sigprocmask(SIG_BLOCK,$sigset);
$i = 10;
while ($i--){
    pcntl_signal_dispatch();
    sleep(1);
    if($i == 5){
        fprintf(STDOUT,"开始接触屏蔽\n");
        // 接触信号屏蔽
        // 返回之前阻塞的信号集
        pcntl_sigprocmask(SIG_UNBLOCK,$sigset,$oldset);
    }
}


发送信号

  1. linux中可以使用kill命令发送信号
  2. 在程序中使用 posix_kill 给一个指定的进程或进程组发送信号
  3. pcntl_alarm SIGALRM
  4. 终端按下特殊按键 ctrl+c, ctrl+\ ctrl+z
  5. 网络通信中SIGURG,SIGPIPE,SIGCHLD
 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
<?php

pcntl_signal(SIGINT,function ($signal){
    fprintf(STDOUT,"pid %d 接收到信号 %d\n",posix_getpid(),$signal);
});
pcntl_signal(SIGALRM,function ($signal){
    fprintf(STDOUT,"pid %d 接收到信号 %d\n",posix_getpid(),$signal);
});
$mapPid = [];
$pid = pcntl_fork();
if($pid > 0){
    $mapPid[] = $pid;
    $pid = pcntl_fork();
    if($pid > 0){
        $mapPid[] = $pid;
        while(1){
            pcntl_signal_dispatch();
//            posix_kill($mapPid[0],SIGINT);
            // 如果参数为0,会向进程组中的所有进程发送信号
//            posix_kill(0,SIGINT);
            // 如果参数为 -1,测试会把虚拟机关闭,断开连接
//            posix_kill(-1,SIGINT);
            // 如果参数为 1,测试会把虚拟机关系统重新启动,1 为系统进程
            posix_kill(1,SIGINT);
            pcntl_alarm(2);
            sleep(2);
        }
    }
    exit(0);
}
while(1){
    pcntl_signal_dispatch();
    fprintf(STDOUT,"pid %d, ppid %d, gid %d \n",posix_getpid(),posix_getppid(),posix_getpgrp());
    sleep(1);
}