Linux信号发送命令之kill命令

kill

作用:向进程发送信号。

注意: kill命令只是用来向进程发送信号的,而不是直接杀死进程。

kill命令的一般使用格式:

kill [参数] 进程号

进程号可用ps命令查看

kill的参数:

-l 列出全部的信号名称
-a 当处理当前进程时,不限制命令名和进程号的对应关系
-p 指定kill 命令只打印相关进程的进程号,而不发送任何信号
-s 指定发送信号
-u 指定用户

kill命令可直接向进程发送特定的信号,使用格式为:

kill [信号编号] 进程号

注意:

如果不指定信号编号,则默认发送15号SIGTERM 信号。该信号是程序结束(terminate)信号,将终止所有不能捕获该信号的进程,通常用来要求程序自己正常退出。如果进程仍然终止不了,可尝试发送9号SIGKILL信号,强制杀死进程。

发送9号信号来强制杀死进程示例:

kill -9 进程号

查看这些信号编号:

kill -l   # l 即 list 的意思
slot@slot-ubt:~$ kill -l
1) SIGHUP    2) SIGINT   3) SIGQUIT  4) SIGILL   5) SIGTRAP
 6) SIGABRT  7) SIGBUS   8) SIGFPE   9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT   17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG  24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF 28) SIGWINCH    29) SIGIO   30) SIGPWR
31) SIGSYS  34) SIGRTMIN    35) SIGRTMIN+1  36) SIGRTMIN+2  37) SIGRTMIN+3
38) SIGRTMIN+4  39) SIGRTMIN+5  40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8
43) SIGRTMIN+9  44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9  56) SIGRTMAX-8  57) SIGRTMAX-7
58) SIGRTMAX-6  59) SIGRTMAX-5  60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2
63) SIGRTMAX-1  64) SIGRTMAX    
slot@slot-ubt:~$ 
    

可以看到,一共有64个信号。其中,前32个信号属于Unix经典信号(即所有类Unix操作系统都提供的信号);后32个信号属于实时信号(用户实时自定义信号),即与特定的硬件驱动相匹配的信号。常用的是前32个信号,而后32个信号做底层驱动开发时能用到。

其中,最常用的信号有:

2号 SIGINT:中断信号
9号 SIGKILL:杀死信号
11号 SIGSEGV:段错误信号
19号 SIGSTOP:暂停信号(如使用control + z操作)
18号 SIGCONT:继续信号(对应19号暂停信号)

实例1: 一个有关段错误(Segmentation fault)的例子

demo:seg_fault.c

#include <stdio.h>

int main()
{
    char *str = "hello";
    *str = 'a'; 
    printf("%s\n", str);
    return 0;
}

编译

slot@slot-ubt:~/test$ gcc seg_fault.c -o app
slot@slot-ubt:~/test$ 
slot@slot-ubt:~/test$ ls
aa  app  bb  cc  haha.ha  hello.txt  seg_fault.c
slot@slot-ubt:~/test$ 

可以看到,编译通过。

运行

slot@slot-ubt:~/test$ 
slot@slot-ubt:~/test$ ./app
Segmentation fault (core dumped)
slot@slot-ubt:~/test$ 

可以看到,运行程序时出现段错误Segmentation fault

调试

slot@slot-ubt:~/test$ gcc seg_fault.c -g -o app
slot@slot-ubt:~/test$
slot@slot-ubt:~/test$ gdb app
GNU gdb (Ubuntu 7.11-0ubuntu1) 7.11
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from app...done.
(gdb) r
Starting program: /home/slot/test/app 

Program received signal SIGSEGV, Segmentation fault.
0x000000000040053a in main () at seg_fault.c:6
6       *str = 'a';
(gdb) 

可以看到,程序退出的原因是接收到了段错误的信息:

Program received signal SIGSEGV, Segmentation fault.

具体出错位置是在源文件的第6行:

6       *str = 'a';

原因分析

我们知道,字符串是不可改变的量,被分配在内存区域的数据段。当尝试向该只读(RO: read-only)数据区域进行写操作时,操作系统内核(kernel)会通过kill命令向当前进程发送编号为11的信号,即SIGSEGV(段错误)信号,导致程序终止。

实例2:向正常程序发送11号段错误信号

demo: loop_forever.c

#include <stdio.h>
#include <unistd.h>

int main()
{
    while (1) {
        printf("hello world\n");
        sleep(2);
    }
    return 0;
}

编译并运行程序

slot@slot-ubt:~/test$ gcc loop_forever.c -o loopapp
slot@slot-ubt:~/test$ 
slot@slot-ubt:~/test$ ./loopapp 
hello world
hello world
...

在另一个终端中向程序loopapp发送11号信号:

slot@slot-ubt:~$ ps -ef | grep loopapp
slot      6242  2123  0 09:54 pts/17   00:00:00 ./loopapp
slot      6247  4844  0 09:54 pts/1    00:00:00 grep --color=auto loopapp
slot@slot-ubt:~$ 
slot@slot-ubt:~$ kill -11 6242
slot@slot-ubt:~$ 

发送11号信号后:

slot@slot-ubt:~/test$ ./loopapp 
hello world
hello world
hello world
hello world
hello world
hello world
hello world
Segmentation fault (core dumped)

可以看到,正常程序在接收到11号信号后同样会出现段错误。

一个小结

一般,当我们遇到Segmentation fault这种错误时,很可能是我们对内存进行了一些非法操作,如 向不存在的内存地址进行写操作、对内核空间(注:在32位Linux操作系统中,地址空间的划分为:0~3G为用户空间,3~4G为内核空间)进行写操作、对只读数据区进行写操作(如实例1所示)等。

ps:gdb的使用可参考如下文章:
GDB: The GNU Project Debugger
陈皓:用GDB调试程序
Linux gdb调试器用法全面解析

扩展:kill函数

作用

kill()函数将信号发送给进程或进程组。

声明

 #include <sys/types.h>
 #include <signal.h>

 int kill(pid_t pid, int sig);

kill函数声明所在位置为

glibc-2.24/signal/signal.h:127:extern int kill (__pid_t __pid, int __sig) __THROW;

关于参数的说明

参数pid 有如下四种情况:

  • pid > 0:将信号发送给进程ID为pid的进程;
  • pid == 0:将信号传发送给与发送进程属于同一进程组的所有进程(这些进程的进程组ID等于发送进程的进程组ID);
  • pid < 0:将该信号发送给其进程组ID等于pid绝对值的所有进程;
  • pid == -1:将该信号发送给系统内所有的进程。
    注意:
    这里所说的“所有进程”不包括实现定义的系统进程集。对于大多数Unix系统而言,系统进程集包括内核进程init进程(pid为1) 。

实现源码

源码位置为glibc-2.24/signal//kill.c:26:__kill (int pid, int sig)

/* Send signal SIG to process number PID.  If PID is zero,
   send SIG to all processes in the current process's process group.
   If PID is < -1, send SIG to all processes in process group - PID.  */
int
__kill (int pid, int sig)
{
      __set_errno (ENOSYS);
      return -1;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容

  • 又来到了一个老生常谈的问题,应用层软件开发的程序员要不要了解和深入学习操作系统呢? 今天就这个问题开始,来谈谈操...
    tangsl阅读 4,121评论 0 23
  • 程序调试的基本思想是“分析现象->假设错误原因->产生新的现象去验证假设”这样一个循环过程,根据现象如何假设错误原...
    Manfred_Zone阅读 16,532评论 0 26
  • 对于 Linux来说,实际信号是软中断,许多重要的程序都需要处理信号。信号,为 Linux 提供了一种处理异步事件...
    故事狗阅读 84,895评论 2 62
  • 1 刚刚下课拿起手机,我收到木子的微信:亲爱的,我要结婚了。 木子是我大学室友,她和男友华子堪称是“患难”情侣,之...
    梦雅吖吖阅读 822评论 10 22
  • 没有喧嚣的花炮,也没有扰人的汽车警报,这个年算是过完了。 记得这是在上海过的第二个春节,也是第二次有幸在上海看到下...
    Vicar伟光阅读 329评论 4 4