记忆总是会慢慢褪去,所以让文字记住一切~
分类: LINUX
2015-08-27 09:37:08
这两天Coding结束了,闲了一点,写篇博文吧......刚好这次做的一个模块用到了信号处理机制,所以就写写这个吧~
在Linux的系统上,经常会听到说给某某进程发个信号,让它来做什么什么样的事情。刚好之前项目中用到这个技巧,所以就简单写篇文章记录一下,便于大家学习。
简单的调用可以在shell中调用”kill –X PID”,其实kill有多个参数,可以man一下。这里X即为信号值,其实类似于一个号码(用kill –l可列出来系统支持的所有信号)。可以看到kill –l列出的数据一般都是SIGXXX,当我们在shell脚本中使用时,最好将前面的“SIG”去掉,这样可以减少系统的兼容性问题,或者我们使用相应的编号号码来作为参数。PID是实际运行在系统上的进程号。可以用ps命令来获得。
我们可以让程序来捕获信号,并设定对应的处理程序,这样可以让程序做更多的事情。关于信号对应的处理函数设置可以参照APUE这本书,其核心思想包括两步骤:
a) 定义信号处理函数,其原型为: void sig_handler(int sig);
b) 设置信号对应的处理函数,可以使用signal()来设定,或其他类似方法。
好了说道这里,给进程发送信号究竟可以做什么呢?这里根据我的经验列出了下面4个使用场景:
1) 强行退出进程
使用的是kill -9 pid,9是SIGKILL的编号。这个我想大部分人都会使用。
2) 优雅的退出进程
因为在1)中的SIGKILL这个信号不可以被我们捕捉,所以我们无法给出相应的信号处理函数。那么我们可以通过捕捉其他信号,加上对应的处理函数来完成进程的退出,这样样可以更加优雅的退出。这一般会在有需求的情况下这么做,比如在退出之前我们需要保存或清理一些数据。
3) 重启部分进程
当我们讨论重启时,心中的第一种思路就是杀死一个进程然后再重新执行程序。其实我们也可以不杀死一个进程来进行一些需要的重启。这种情况一般使用在多进程的情况下,一个master下面有多个children进程。在一些情况下我们可能需要去关闭无用的children进程,并通过fork来创建拥有新能力的新进程。这个时候就可以通过这种方法,master来接受信号,并设置一些属性功能。这点有点类似nginx最初的管理模式。
4) 加载配置
我想这个用得应该比较多,当我们对于一个程序的设定改变时,不想重启这个进程(因为重启的花销实在太大了,特别对于关键服务的进程)。那就只能想个法子让进程来读取新的设定。一种方法是:我们可以在进程中启动一个线程来定时的观察设置有没有改变,一旦改变就加载一下。这种方法的缺点是有一个线程的存在,多少会消耗一点系统资源。第二种方法:设定一个信号并对应着加载设定的处理程序(一般称之为reload),这样当程序捕捉到这样的信号即去读取新的设置,触发式的总感觉好一点,不会浪费太多资源。
以上4中场景是在我们项目中经常用到的,供大家参考,希望对你有所帮助~~