中断处理过程
信号 指软件终端信号,软中断
- 中断处理程序注册。进程注册中断处理程序。不能覆盖信号:sigkill,sigstop
- 中断源产生中断。按键、kill、定时器等
- 进程中断响应,忽略sig_ign,执行中断处理程序,执行系统默认处理程序sig_def
- 中断返回
中断处理程序实验:
function sigHandler($signo)
{
printf("pid=%d, 接收到一个信号:%d\n", getmypid(), $signo);
}
// SIGKILL SIGSTOP 无法被捕捉,报错
// 设置信号捕捉
pcntl_signal(SIGINT,'sigHandler');
pcntl_signal(SIGUSR1,'sigHandler');
// 子进程继承父进程的中断程序,并且可以覆盖
$pid = pcntl_fork();
if ($pid == 0){
pcntl_signal(SIGUSR1, function ($signo){
printf("pid=%d, 覆盖的中断操作:%d\n", getmypid(), $signo);
});
}
while (1){
sleep(2);
pcntl_signal_dispatch();
printf(" %d work running.\n", getmypid());
}
// kill -s SIGINT 16912
// kill -s SIGUSR1 16912
// kill 16912
信号集 pcntl_sigprocmask 设置或截取信号屏蔽字
pcntl_signal(SIGINT, function ($sigNo){
printf("pid=%d, 接收到了信号:%d\n", getmypid(), $sigNo);
});
// 信号屏蔽字
$sigSet = [SIGINT, SIGUSR1];
pcntl_sigprocmask(SIG_BLOCK, $sigSet);
$i = 1;
while (1){
sleep(2);
pcntl_signal_dispatch();
printf("pid=%d, work run\n", getmypid());
if ($i == 5){
printf("time come");
pcntl_sigprocmask(SIG_UNBLOCK, $sigSet, $oldSet);
print_r($oldSet);
}
$i++;
}
发送信号
- kill 命令 -s 信号编号 | 信号名称 进程PID
- 程序中的 posix_kill 给指定的进程组发送信号
- pcntl_alarm sigalrm
- 终端下特殊的按键
- 网络 SIGURG,SIGPIPE。子进程结束 SIGCHLD
// posix_kill
pcntl_signal(SIGINT, function ($sigNo){
printf("pid %d 收到 %d 信号\n", posix_getpid(), $sigNo);
});
// 创建的子进程都是兄弟进程,父进程ID,组ID都一样
$midPid = [getmypid()];
$pid = pcntl_fork();
if ($pid > 0){
$midPid[] = $pid;
$pid = pcntl_fork();
if ($pid > 0){
$midPid[] = $pid;
while (1){
// foreach ($midPid as $i){
// posix_kill($i, SIGINT);
// }
// 就会向进程组中的每个进程发送信号
posix_kill(0, SIGINT);
sleep(2);
}
}
}
while (1){
pcntl_signal_dispatch();
fprintf(STDOUT,"pid %d ppid=%d,pgid=%d doing...\n",posix_getpid(),
posix_getppid(),posix_getpgrp());
sleep(1);
}
// pcntl_alarm
pcntl_signal(SIGALRM, function ($sigNo){
printf("pid %d 收到 %d 信号\n", posix_getpid(), $sigNo);
});
pcntl_alarm(2);
while (1){
pcntl_signal_dispatch();
sleep(2);
}
// SIGCHLD
pcntl_signal(SIGCHLD, function ($sigNo){
fprintf(STDOUT,"pid %d 接收到 %d 信号\n",posix_getpid(),$sigNo);
$pid = pcntl_waitpid(-1,$status,WNOHANG);
if ($pid>0){
fprintf(STDOUT,"pid %d 退出了\n",$pid);
}
});
$pid = pcntl_fork();
if ($pid>0){
while (1){
pcntl_signal_dispatch();
sleep(2);
}
}else{
fprintf(STDOUT,"child pid %d 退出了\n",getmypid());
exit(10);
}