要相信Linux信号处理机制以及程序优雅退出的代码模板

导言

很多人在Linux中用信号让程序退出,总是恨不得直接用kill -9 pid,而实际来看,没有那个必要,也并不优雅,可以用TERM信号!

信号处理的特点

  • 硬件中断,例如,除零、内存缺页、越界等指令级不可继续异常,在下条指令执行前必须被中断的处理
  • 软中断,OS调度级处理,在内核态到用户态切换的时机,具有典型的异步特点

man文档的误导

Execution of signal handlers
Whenever there is a **transition** from kernel-mode to user-mode
execution (e.g., on return from a system call or scheduling of a
thread onto the CPU), the kernel checks whether there is a
pending unblocked signal for which the process has established a
signal handler


每当存在一个内核态到用户态执行的转变,例如,系统调用、重新调度得以在CPU上执行,内核会检查是否存在未处理的异常

注意, 非逐字翻译,但文本描述中转换时机举例涵盖场景不够全面,存在某些误导!

对于那些阻塞的线程,以及在用户态无限循环的线程,是否信号处理就无法进行了么?

经过验证,Linux对于阻塞操作进行了特殊对待,见章节Interruption of system calls and library functions by signal handlers

对于用户空间的无限循环程序,在微观的操作系统视角来看,并不存在一直占用CPU,所以,总会从用户态转换到内核态的就绪,然后再从就绪态获得下一次CPU执行机会,就满足了文档介绍的转换时机。
如果用户态无限循环程序,配合以全局易失的退出标记量,则程序退出问题,更是可以比较优雅地解决!

优雅推出方式模板

   // 以C语言为例
   volatile char g_bExit;
   
   // 信号处理函数,在默认信号处理不能满足要求时使用
   void signal_handler(int signum)
   {
		if (signum == SIGTERM && g_bExit == 0) {
			g_bExit = 1;
			/*向伙伴发送停止信号*/
			for_each_managed_thread()
			{
				pthread_kill(eachThreadId, SIGTERM);
			}
			
			/*主线程用非信号方式退出*/
			wakeupMainThread();
		}
   }
   
   //main thread
   while(unlikely(g_bExit))
   {
     ...
   }
   // 等待伙伴退出
   pthread_join(somePartnerThreadId);

验证信号处理脚本

shell脚本程序,也可以很好地完成对信号处理的验证,而不用写C语言程序,何乐而不为?

echo "Self pid: $$, testing signal process character ..."
# 阻塞的伙伴
/bin/bash -c "sleep 1000" &
# 用户态无限循环的伙伴
/bin/bash -c "x=0;while true; do let x=x+1; done" &

# 打印后台进程列表
jobs -l

# 两段打印分开
sleep 1
echo "Send signal TERM to background jobs ..."
kill %1 %2

echo "Will sleep to see after having send TERM signal ..."
k=0
while true ; do
  sleep 2
  echo "Print jobs loop count: $k; The expected job list should be empty! ..."
  
  jobs -l

  let k=k+1
  if [ $k -eq 10 ]; then
     break
  fi
done

echo "Test is over"

欢迎指正

验证过程,如果不足之处,欢迎指正,谢谢 😃

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值