本文为小伙伴们带来了关于PHP平滑关闭/重启的实现代码, 前言 写过 CLI 常驻进程的老司机肯定遇到过这么一个问题:在需要更新程序的时候,我要怎样才能安全关闭老进程?...原理 要实现平滑关闭/重启不难,这里先讲解两个知识点: 阻塞信号 当我们的程序正在处理一个任务的时候,你肯定不希望它中途被终止,比如说你在执行一个数据库事务,肯定不希望事务还没被提交进程就被终止了。...pcntl_sigprocmask(SIG_UNBLOCK, $sig_set); } 我们是可以保证一个事务不会被打断,但是我们的程序还不知道是不是已经接收到信号了,并且把阻塞信号移除之后进程立刻就退出了...PHP_EOL; }; pcntl_signal(SIGINT, $sig_handler); // 给 SIGINT 信号注册一个处理器 // 模拟耗时操作 echo "开始执行事务" ....拼起来 到这里你已经了解平滑关闭/重启的原理了,我们把上面的半成品代码(因为在收到信号后可能还会进入下一层循环)整理一下:
优雅关机就是服务端关机命令发出后不是立即关机,而是等待当前还在处理的请求全部处理完毕后再退出程序,是一种对客户端友好的关机方式。...在终端迅速执行Ctrl+C命令给程序发送syscall.SIGINT信号 此时程序并不立即退出而是等我们第2步的响应返回之后再退出,从而实现优雅关机。...在终端迅速执行kill -1 43682命令给程序发送syscall.SIGHUP信号 等第3步浏览器收到响应信息hello gin!...后再次访问127.0.0.1:8080/会收到hello q1mi!的响应。 在不影响当前未处理完请求的同时完成了程序代码的替换,实现了优雅重启。...但是需要注意的是,此时程序的PID变化了,因为endless 是通过fork子进程处理新请求,待原进程处理完当前请求后再退出的方式实现优雅重启的。
)defer cancel()// 5 秒内优雅关闭服务(将未处理完的请求处理完再关闭服务),超过 5 秒就超时退出if err := srv.Shutdown(ctx); err !...服务器在一个单独的 goroutine 中运行,这样主程序可以继续执行,而不必等待服务器启动完成。3....Shutdown 方法接受一个 context 参数,这个 context 设置了一个超时时间。在这里,我们设置了一个 5 秒的超时时间,意味着服务器将在 5 秒内等待未完成的请求处理完毕,然后关闭。...如果超过了设定的超时时间,服务器将退出,程序也会正常结束。如何验证优雅关机的效果?...syscall.SIGINT 信号此时程序并不会立即退出,而是会等上面的第 2 步的响应返回之后再退出,从而实现优雅关机的效果总结优雅关机是构建健壮 Web 服务的一个重要技术点,它确保了在服务关闭时所有正在处理的请求都能被妥善完成
在函数内部可以进行一些程序退出前的清理工作,如释放资源、输出日志等。 二、注册信号处理函数 将信号处理函数注册到SIGINT信号上,可以对该信号进行捕捉和处理。...当程序接收到SIGINT信号时,就会自动调用该函数进行处理。...return 0; } 在程序中使用std::atomic类型变量声明一个标志位quit,表示是否接收到SIGINT信号。在主循环中不断地检查该标志位是否为true,如果是则退出程序。...在信号处理函数中,将该标志位设置为true,表示接收到了SIGINT信号。 四、防止重复信号 在信号处理函数中,可能会产生一些耗时的操作,如释放资源或写入日志等。...在进入信号处理函数时,先检查该标志位是否为true,若为true则退出函数。在函数内部完成了所有的信号处理工作后,再将该标志位设置为false,表示处理完毕。
所以用signal函数注册的信号处理函数只会被调用一次,之后收到这个信号将按默认方式处理,如果想一直处理这个信号的话就得在信号处理函数中再次用signal注册一次,一般都在信号处理函数开始处调用signal...注册一次这个信号,虽然这样可以一直能处理这个信号,但是可以看出,在sa_handler指针恢复到再次调用signal注册信号期间如果收到这个信号,那么这个信号就按默认方式处理,如果是INT之类信号的话,...信号处理函数——sigint_handler,这个函数在处理信号时用sleep阻塞10s才返回,主进程fork出一个子进程,这个子进程向主进程发送5次SIGINT信号后退出,编译运行结果如下:...再来看看加了-std=c99编译参数之后的结果: 实验六: 加上-std=c99参数效果就跟实验五不一样了,信号处理函数sigint_handler在收到信号时就直接执行,并没有等上一个信号处理完了再处理下一个信号...最后,至于在应用程序中调用signal为什么到内核就变成了rt_sigaction了呢,也大概说一下吧: 反汇编一下实验一和实验二的二进制程序(dis是我写的一个反汇编程序指定函数的shell命令,可以在我之前博客中找到
信号是操作系统中的一种通知机制,用于通知进程发生了某些事件,比如接收到了外部中断、收到了某个进程发送的信号等等。当系统接收到信号时,会中断进程的正常执行流程,转而执行信号处理程序。...signal()函数用于注册信号处理程序。当进程收到指定的信号时,就会执行注册的信号处理程序。handler可以是一个函数指针,也可以是SIG_IGN或SIG_DFL。...当该信号接收到后,进程会恢复执行。 4)sigqueue函数:用于向指定进程发送一个指定信号,并附带一个整型值作为附加数据。...当进程接收到SIGQUIT信号时,它会强制退出,并在退出之前生成一个内核映像(core dump)。在C语言中,可以使用signal函数来注册SIGQUIT信号的处理程序。...例如: signal(SIGINT, SIG_IGN); 表示在收到 SIGINT(即中断信号,一般是由用户按下 Ctrl-C 触发)时,将其忽略,即不对其进行任何处理。
一旦进程接收到 SIGINT 信号,内核会将其递送到进程,并触发信号处理函数 signal_handler 1.3 信号未决状态 当信号发送给进程时,如果该信号被进程的信号屏蔽字阻塞,那么该信号就会进入未决状态...10 秒后,信号屏蔽被解除,SIGINT 信号会被递送并触发相应的处理。...\n"); while (1) { sleep(1); // 程序将一直运行,直到接收到信号 } return 0; } 在这个示例中,signal_handler...\n"); while (1) { sleep(1); // 程序将一直运行,直到接收到信号 } return 0; } 通过 sigaction()...,程序能够灵活地处理信号,并控制信号捕捉的行为,甚至允许在处理信号时阻塞其他信号。
引言 在现代操作系统中,信号处理是一种重要的机制,它允许操作系统通知应用程序发生了特定的事件,如终止请求(SIGTERM)或中断信号(SIGINT)。...本文通过一个具体的 Go 示例,详细讲解了如何使用 Go 的 signal 包来处理系统信号,进而实现程序的优雅退出或其他自定义行为。...每种信号类型都对应一个特定的事件,例如: SIGINT:通常由 Ctrl+C 发出,用于中断程序。 SIGTERM:表示终止信号,通常用于请求程序正常退出。...等待与退出: 主函数通过 处理完信号。一旦接收到协程的结束信号,输出 "exiting" 并结束程序。...应用场景与挑战 应用场景 优雅地处理程序退出:在需要清理资源或保存状态之前,优雅地关闭程序。 外部事件响应:使程序能够响应外部命令,如停止、重新启动等。
在Linux中,要发送一个信号相当容易。程序员需要知道两个信息:要发送哪个信号,将这个信号发送给哪个进程。可以用 man 7 signal 找到一个可以利用的信号的列表。...ID号 printf("程序已经开始运行,5秒钟后将接收到时钟信号。.../n"); } void when_sigint() { printf("已经接收到了SIGINT信号,程序将退出!.../signal_test 程序已经开始运行,5秒钟后将接收到时钟信号。 距离SIGALRM信号到来还有5秒。 系统接收到了SIGIO信号。 距离SIGALRM信号到来还有4秒。...------此时程序会停下来等待,请按下ctrl+c送出SIGINT信号------- 已经接收到了SIGINT信号,程序将退出!
当进程收到一个信号时,该进程会中断其执行,并执行收到信号对应的处理程序。 信号机制作为 Linux 进程间通信的一种方法。Linux 进程间通信常用的方法还有管道、消息、共享内存等。...信号的产生有多种来源: 硬件来源,例如 CPU 内存访问出错,当前进程会收到信号 SIGSEGV;按下 Ctrl+C 键,当前运行的进程会收到信号 SIGINT 而退出; 软件来源,例如用户通过命令 kill...当外部设备出现一个必须由 CPU 处理的事件,如键盘敲击、数据到达网卡等,内核会收到中断通知,暂时打断当前程序的执行,跳转到该中断类型对应的中断处理程序。...signal(int signum, sighandler_t handler); 例如下面的例子,程序捕获了信号 SIGINT ,并且只是输出不做其他处理,这样在键盘上按 Ctrl+C 并不能让程序退出...由于 SIGKILL 是特权信号,进程无法捕获和忽略,因此进程在收到该信号后无法进行清理,立刻退出。
(不可用于 SIGKILL、SIGSTOP 信号),即确定收到信号后处理函数的入口地址。...SA_NOCLDWAIT:使父进程在它的子进程退出时不会收到 SIGCHLD 信号,这时子进程如果退出也不会成为僵尸进程。...SIGINT 程序终止(interrupt)信号, 在用户键入INTR字符(通常是Ctrl-C)时发出,用于通知前台进程组终止进程。...SIGQUIT 和SIGINT类似, 但由QUIT字符(通常是Ctrl-/)来控制. 进程在因收到SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信号。...SIGTERM 程序结束(terminate)信号, 与SIGKILL不同的是该信号可以被阻塞和处理。通常用来要求程序自己正常退出,shell命令kill缺省产生这个信号。
一、引言 在 Linux 操作系统中,信号(Signal)是一种进程间通信(IPC,Inter - Process Communication)的机制,它用于通知进程发生了某种异步事件。...进程接收到信号后,会根据信号的类型以及自身的处理方式做出相应的反应。理解信号对于编写健壮的 Linux 程序以及深入理解 Linux 操作系统的运行机制至关重要。...例如,当用户在终端中按下 Ctrl + C 组合键时,系统会向当前前台进程发送 SIGINT 信号,通常进程会接收到这个信号后停止当前正在执行的任务并退出。...比如,我们在终端中运行一个长时间运行的命令while true; do echo "Hello"; sleep 1; done,按下 Ctrl + C 后,该命令对应的进程会接收到 SIGINT 信号并终止...生成核心转储文件并终止进程:例如 SIGQUIT 信号,在终止进程的同时会生成核心转储文件,该文件包含了进程在收到信号时的内存状态等信息,可用于调试程序。
=0); return 0;}执行: 信号集 在实际应用中,一个用户进程常常需要对多个信号进行处理,在LInux中引入信号集(signal set)概念,用于表示由多个信号所组成集合的数据类型,其定义为...在for循环运行了5次,即大约5秒后,产生了SIGALRM信号,此时由signal注册信号的处理函数handler,输出字符串。信号处理完毕后又返回先前程序的中断点,继续执行for循环。...setitimer函数 setitimer函数与alarm函数一样,也可以用于使系统在某一时刻发出信号,但它可以更加精确地控制程序。...信号的阻塞 在Linux的信号控制中,有时不希望进程在接收到信号时立刻中断进行的执行,也不希望该信号被完全忽略,而是延时一段时间再去调用相关的信号处理函数。...在输出第一句"Before pause()."后,等待约3秒钟,采输出第二句。
2.2 优雅关机 2.2.1 什么是优雅关机 优雅关机就是服务端关机命令发出后不是立即关机,而是等待当前还在处理的请求全部处理完毕后再退出程序,是一种对客户端友好的关机方式。...在终端迅速执行Ctrl+C命令给程序发送syscall.SIGINT信号 此时程序并不立即退出而是等我们第2步的响应返回之后再退出,从而实现优雅关机。...在终端迅速执行kill -1 43682命令给程序发送syscall.SIGHUP信号 等第3步浏览器收到响应信息hello gin!...后再次访问127.0.0.1:8080/会收到hello q1mi!的响应。 在不影响当前未处理完请求的同时完成了程序代码的替换,实现了优雅重启。...但是需要注意的是,此时程序的PID变化了,因为endless 是通过fork子进程处理新请求,待原进程处理完当前请求后再退出的方式实现优雅重启的。
(重启被中断的系统调用) SA_RESETHAND 信号处理函数接收到信号后,会先将对信号处理的方式设为预设方式,而且当函数处理该信号时,后来发生的信号将不会被阻塞。...信号来了,进入信号处理函数,默认情况下,在信号处理函数未完成之前,如果又来了一个SIGINT信号,其将被阻塞,只有信号处理函数处理完毕,才会对后来的SIGINT再进行处理,同时后续无论来多少个SIGINT...在对比SIGTERM和SIGINT,这个信号不能被捕获或忽略,并且在接收过程中不能执行任何清理在接收到该信号。...进程在因收到 SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信 号. 4) SIGILL 执行了非法指令....通常用来要求程序自己正常退出. shell命令kill缺省产生这 个信号. 17) SIGCHLD 子进程结束时, 父进程会收到这个信号. 18) SIGCONT 让一个停止(stopped
注意事项: 当使用signal()函数注册信号处理函数时,处理函数并不会立即执行,而是在未来收到对应的信号时才会执行 如果注册了一个处理SIGINT信号的处理函数,但是进程从未收到SIGINT信号,那么注册的处理函数也就永远不会被调用...目标进程收到SIGINT信号后,会执行与之关联的信号处理函数。通常情况下,SIGINT信号会导致进程终止执行,类似于用户主动输入exit或者点击关闭窗口。...目标进程收到SIGQUIT信号后,会执行与之关联的信号处理函数。...SIGPIPE信号是一个用于处理管道写端在写操作时无读端接收的情况的信号。...,CPU一直在进行进程的调度,那么就涉及到进程上下文的保存和恢复,因为我们没有进行退出操作,所以每次恢复后,异常还是存在。
信号是给程序提供一种可以处理异步事件的方法,它利用软件中断来实现。 我们无法自定义信号,所有信号都是系统预定义的。 ---- 信号由谁产生?...捕捉信号,指定信号处理函数进行处理。详见信号的安装 执行系统默认动作,大多数都是终止进程。 ---- 信号的捕获 信号的捕获是指,在接收到某种信号后,去执行指定的函数。..., &act, 0);//处理SIGINT停止信号 //收到SIGINT信号,如果此时再收到SIGUSR1,则会执行完后在进行SIGUSR1信号处理。...SIGUSR1信号 while (1) { } return 0; } 以上详解: 先收到SIGINT信号,如果此时再收到SIGUSR1,则会执行完SIGINT的信号处理函数后再进行...结果如下图所示: 先收到SIGUSR1信号,如果此时再收到SIGINT,则会先执行SIGINT的信号处理函数后再回来继续进行SIGUSR1信号处理函数的执行。
在一个程序收到某些信号后,程序都会自动去执行默认的操作,但大多的操作都会导致程序异常退出,除了前文我们介绍的阻塞信号以外,我们还可以对信号进行捕获(拦截)处理,让被捕获的信号去执行我们已经编写好的函数中...handler 该函数的第一个参数是我们要发送的信号,第二个参数是让我们提供一个函数指针,这个函数指针的原型就是上面 typedef 的原型,我们根据原型定义一个函数,然后将函数名传递到第二个参数,就可以成功调用这个函数了...当函数执行成功,会将第一个参数中的信号捕获并让其指向我们自己编写的处理函数。...信号捕获,让程序接受到该信号后转到 mySigAction 函数 signal(SIGINT, mySigAction); while (1) { printf(“mian printf…\n”);...sa_handler 方式 act.sa_flags = 0; // 捕获信号,并传递捕获后执行的操作结构体 sigaction(SIGINT, &act, &oldact); while (1) {
当你编写程序,想要屏蔽某个或多个信号的时候,那么我们就会用到PHP扩展中的pcntl_sigprocmask函数,这个函数就是用于设置信号屏蔽字的函数,第一个参数就是可以是否设置屏蔽信号字,SIG_BLOCK...是设置,SIG_UNBLOCK是移除不设置 第二个参数就是你要设置屏蔽的信号集合数组,第三个参数是返回之前设置屏蔽的信号集数组 ?...demo1测试代码 如果不知道怎么用PHP编写信号处理程序的同学,可以查看我上面的一篇文章教程 如何用PHP编写一个信号中断处理程序(https://www.umdzz.cn/article/56/php...echo "我捕捉到一个信号,信号编号是:"....经过测试后发现,在i>5的时候,程序是接收不到我们发送的信号的,当i=5,我们解除信号屏蔽字后,我们的程序是可以正常接收到我们的信号屏蔽字的,并且也打印出了,我之前之前测试的信号屏蔽字,SIGINT和SIGUSR1
领取专属 10元无门槛券
手把手带您无忧上云