对linux的kill命令不太了解的一些朋友一直会有这样一个错觉: kill命令就是用来杀死一个进程啊! 我要说, 这种理解是比较初级的。 其实, kill这个命令的命名本来就误导了一大批人, 我不知道是谁取了kill这个名字, 我要是知道, 首先要为大家打他的屁股。
kill命令的真正作用是:将某信号发送给某进程或者进程组。
下面, 我们先来看程序:
#include <stdio.h>
#include <signal.h>
void sig_callback1()
{
printf("signal: SIGUSR1\n");
}
void sig_callback2()
{
printf("signal: SIGUSR2\n");
}
int main()
{
// 用户定义信号
if(SIG_ERR == signal(SIGUSR1, sig_callback1))
{
printf("error1\n");
return 1;
}
// 用户定义信号
if(SIG_ERR == signal(SIGUSR2, sig_callback2))
{
printf("error2\n");
return 1;
}
while(1)
{
NULL;
}
return 0;
}
执行结果为:
[taoge@localhost learn_c]$ signal: SIGUSR1
[taoge@localhost learn_c]$ kill -SIGUSR2 4652
[taoge@localhost learn_c]$ signal: SIGUSR2
[taoge@localhost learn_c]$ kill 4652
[taoge@localhost learn_c]$ kill -SIGUSR1 4652
bash: kill: (4652) - No such process
[1]+ Terminated ./a.out
[taoge@localhost learn_c]$
我们看到, kill命名实际上是向进程发送信号的。 那个kill 4652也是向进程发送信号, 发送的是SIGTERM信号, SIGTERM信号的默认操作是杀死进程, 哦, 原来是这么个逻辑。
好, 我们改一下上面的程序, 在感知到SIGTERM信号后, 不执行默认的杀死进程的操作, 如下:
#include <stdio.h>
#include <signal.h>
void sig_callback1()
{
printf("signal: SIGUSR1\n");
}
void sig_callback2()
{
printf("signal: SIGUSR2\n");
}
void sig_haha()
{
printf("heng, i do not terminate the process, so what?\n");
}
int main()
{
// 用户定义信号
if(SIG_ERR == signal(SIGUSR1, sig_callback1))
{
printf("error1\n");
return 1;
}
// 用户定义信号
if(SIG_ERR == signal(SIGUSR2, sig_callback2))
{
printf("error2\n");
return 1;
}
// SIGTERM信号的默认操作是杀死进程, 但程序员完全可以改变这个默认操作, 说白了, 就是改变信号到函数的映射关系
if(SIG_ERR == signal(SIGTERM, sig_haha))
{
printf("error3\n");
return 1;
}
while(1)
{
NULL;
}
return 0;
}
执行结果为:
^C
[taoge@localhost learn_c]$ ^C
[taoge@localhost learn_c]$ ./a.out &
[1] 4787
[taoge@localhost learn_c]$ kill -SIGUSR1 4787
[taoge@localhost learn_c]$ signal: SIGUSR1
[taoge@localhost learn_c]$ kill -SIGUSR2 4787
[taoge@localhost learn_c]$ signal: SIGUSR2
[taoge@localhost learn_c]$ kill 4787
[taoge@localhost learn_c]$ heng, i do not terminate the process, so what?
[taoge@localhost learn_c]$ kill -SIGUSR1 4787
[taoge@localhost learn_c]$ signal: SIGUSR1
[taoge@localhost learn_c]$ kill -SIGUSR2 4787
[taoge@localhost learn_c]$ signal: SIGUSR2
可以看到, 执行kill 4787, ./a.out对应的进程并没有被杀死, 为啥呢? 因为我覆盖了系统默认的杀死操作, 看看signal(SIGTERM, sig_haha)你就明白了。 我重写了信号到函数的映射, 让SIGTERM映射为我自己写的sig_haha函数。
后来, 我又想了一下, 为什么要将kill命令命名为kill? 其实, 也许是有一点道理的, 对于小白来说, kill 4787的默认操作就是杀死这个进程。 好吧, 在不需要深入理解细节的时候, 把kill叫kill(杀死), 其实也无伤大雅。比如,对一些非程序猿来说(比如运维人员等), 不需要知道kill是发送什么鸟信号, 只要知道kill 4787是杀死4787这个进程即可。
算了, 打屁股的事情就此作罢。