信号的产生
终端按键产生的信号
Ctrl + c -> 2) SIGINT(终止/中断) INT -Interrupt
Ctrl + z -> 20)SIGSTP(暂停/停止) T - Terminal
Ctrl + \ -> 3) SIGQUIT(退出)
硬件异常产生信号
除0操作 -> 8) SIGFPE(浮点数异常)
非法访问内存 -> 11)SIGSEGV(段错误)
总线错误 -> 7) SIGBUS
$cat kill.c
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
int a = 10;
int b = a/0;
return 0;
}
$gcc kill.c -o kill -Wall -g
kill.c: In function ‘main’:
kill.c:17:14: warning: division by zero [-Wdiv-by-zero]
int b = a/0;
^
kill.c:17:9: warning: unused variable ‘b’ [-Wunused-variable]
int b = a/0;
$./kill
Floating point exception (core dumped)
背后的东西是当前进程收到了SIGFPE 的信号
kill函数和kill命令
kill命令产生信号:kill -SIGKILL PID
$cat kill_2.c
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
int a = 10;
while(1);
return 0;
}
$gcc kill_2.c -o kill_2 -Wall -g
kill_2.c: In function ‘main’:
kill_2.c:16:6: warning: unused variable ‘a’ [-Wunused-variable]
int a = 10;
$./kill_2 (然后会挂在那边)
在另外一个窗口中 查看PID
$ps aux |grep -i kill_
ubuntu 7779 100 0.0 4196 352 pts/8 R+ 18:54 1:48 ./kill_2
ubuntu 7804 0.0 0.0 11752 932 pts/17 R+ 18:56 0:00 grep --color=auto -i kill_
$kill -SIGKILL 7779
$./kill_2
Killed
尝试段错误
$./kill_2 (然后会挂在那边)
另外一个终端:
$ps aux |grep -i kill_
ubuntu 7828 100 0.0 4196 352 pts/8 R+ 18:57 0:22 ./kill_2
ubuntu 7834 0.0 0.0 11752 932 pts/17 R+ 18:58 0:00 grep --color=auto -i kill_
$^C
$kill -SIGSEGV 7828
然后运行kill_2进程的终端显示的信息如下:
$./kill_2
Segmentation fault (core dumped)
尝试总线错误
$./kill_2 (然后会挂在那边)
在另外一个终端中输入:
$pkill -SIGBUS kill_2
然后运行kill_2进程的终端显示的信息如下:
$./kill_2
Bus error (core dumped)
关于manpage的使用的一些说明:
num 含义
1 在shell环境中可以直接操作的命令或者可运行文件
2 系统核心可以呼叫的函数或者工具
3 一些常见的函数与函数库,大部分为C的函数库
4 装置文件的说明,通常在/dev下的文件
5 配置文件或者是某些文件的格式
6 游戏
7 惯例与协议,Linux文件系统、网络协议、ASCII Code
8 系统管理员可用的管理命令
9 与Kernel相关的文件
kill函数
KILL(2) Linux Programmer's Manual KILL(2)
NAME
kill - send signal to a process
SYNOPSIS
#include <sys/types.h>
#include <signal.h>
int kill(pid_t pid, int sig);
第一个参数:进程ID
第二个参数:信号
返回值:成功是0 失败的时候 -1
说明:
PID> 0: 发送给指定的进程
PID =0: 发送信号给 与调用kill函数进程属于同一进程组的所有进程
PID<0 : 取|pid|发给对应的进程组
pid = -1: 发送给进程有权限发送的系统中的所有进程
进程组:每一个进程都属于一个进程组,进程组是一个或多个进程集合,他们相互关联,共同完成一个实体任务,
每一个进程组都有一个进程组长,默认进程组ID 和 进程组长ID 相同
权限保护:super用户
重点:
要记住,可以通过ps ajx 查看进程组ID.
$ps ajx
PPID PID PGID SID TTY TPGID STAT UID TIME COMMAND
0 1 1 1 ? -1 Ss 0 0:02 /sbin/init
ps: process status 的缩写。ps命令列出系统中当前运行的哪些进程状态。
参数说明:
-A 显示所有进程(等价于-e)(utility)
-a 显示一个终端的所有进程,除了会话引线
-N 忽略选择。
-d 显示所有进程,但省略所有的会话引线(utility)
-x 显示没有控制终端的进程,同时显示各个命令的具体路径。dx不可合用。(utility)
-p pid 进程使用cpu的时间
-u uid or username 选择有效的用户id或者是用户名
-g gid or groupname 显示组的所有进程。
U username 显示该用户下的所有进程,且显示各个命令的详细路径。如:ps U zhang;(utility)
-f 全部列出,通常和其他选项联用。如:ps -fa or ps -fx and so on.
-l 长格式(有F,wchan,C 等字段)
-j 作业格式
-o 用户自定义格式。
v 以虚拟存储器格式显示
s 以信号格式显示
-m 显示所有的线程
-H 显示进程的层次(和其它的命令合用,如:ps -Ha)(utility)
e 命令之后显示环境(如:ps -d e; ps -a e)(utility)
h 不显示第一行
signal 不推荐使用数字,应使用宏,因为不同操作系统信号信号编号可能不一样。
但其名称是一样的。
通过这个函数给指定的函数发送信号
小提示:
在程序中,如何查看函数的说明
将光标移动到函数;然后2+K
$cat 101_kill.c
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
#include<signal.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
pid_t pid = fork();//fork yi ge zijincheng
if(pid > 0)
{
while(1)
{
printf("It's my parent process!,pid = %d\n",getpid());
sleep(6);
}
}
else if(pid == 0)
{
printf ("child process, pid = %d,ppid = %d\n",getpid(),getppid());
sleep(6);
kill(getppid(),SIGSEGV);
// while(1);
}
else
{
}
return 0;
}
$gcc 101_kill.c -o 101_kill -Wall -g
$./101_kill
It's my parent process!,pid = 13175
child process, pid = 13176,ppid = 13175
Segmentation fault (core dumped)
修改程序
$cat 101_kill.c
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
#include<signal.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
pid_t pid = fork();//fork yi ge zijincheng
if(pid > 0)
{
while(1)
{
printf("It's my parent process!,pid = %d\n",getpid());
sleep(6);
}
}
else if(pid == 0)
{
printf ("child process, pid = %d,ppid = %d\n",getpid(),getppid());
sleep(6);
// kill(getppid(),SIGSEGV);
while(1);
}
else
{
}
return 0;
}
$./101_kill
It's my parent process!,pid = 13293
child process, pid = 13294,ppid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
It's my parent process!,pid = 13293
在另外一个终端输入ps |ajx
13275 13293 13293 13275 pts/1 13293 S+ 1000 0:00 ./101_kill
13293 13294 13293 13275 pts/1 13293 R+ 1000 0:03 ./101_kill
修改程序,子进程向父进程发送SIGCHILD信号
$cat 101_kill.c
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
#include<signal.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
pid_t pid = fork();//fork yi ge zijincheng
if(pid > 0)
{
while(1)
{
printf("It's parent process!,pid = %d\n",getpid());
sleep(6);
}
}
else if(pid == 0)
{
printf ("child process, pid = %d,ppid = %d\n",getpid(),getppid());
sleep(6);
kill(getppid(),SIGCHLD);
// while(1);
}
else
{
}
return 0;
}$cat 101_kill.c
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
#include<signal.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
pid_t pid = fork();//fork yi ge zijincheng
if(pid > 0)
{
while(1)
{
printf("It's parent process!,pid = %d\n",getpid());
sleep(6);
}
}
else if(pid == 0)
{
printf ("child process, pid = %d,ppid = %d\n",getpid(),getppid());
sleep(6);
kill(getppid(),SIGCHLD);
// while(1);
}
else
{
}
return 0;
}
$./101_kill
It's parent process!,pid = 14754
child process, pid = 14755,ppid = 14754
It's parent process!,pid = 14754
It's parent process!,pid = 14754
It's parent process!,pid = 14754
It's parent process!,pid = 14754
It's parent process!,pid = 14754
It's parent process!,pid = 14754
子进程向父进程发送SIGCHLD信号之后,
默认动作是忽略。父进程没有被终止。
kill 杀死进程组
修改程序:
$vi 101_kill.c
$cat 101_kill.c
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
#include<signal.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
pid_t pid = fork();//fork yi ge zijincheng
if(pid > 0)
{
while(1)
{
printf("It's parent process!,pid = %d\n",getpid());
sleep(6);
}
}
else if(pid == 0)
{
while(1)
{
printf ("child process, pid = %d,ppid = %d\n",getpid(),getppid());
sleep(6);
kill(getppid(),SIGCHLD);
// while(1);
}
}
else
{
}
return 0;
}
$./101_kill
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
It's parent process!,pid = 15230
child process, pid = 15231,ppid = 15230
child process, pid = 15231,ppid = 15230
It's parent process!,pid = 15230
在另外一个窗口中
通过PID<0 : 取|pid|发给对应的进程组
$ps ajx |grep -i 101_kill
14774 15435 15435 14774 pts/1 15435 S+ 1000 0:00 ./101_kill
15435 15436 15435 14774 pts/1 15435 S+ 1000 0:00 ./101_kill
15306 15440 15439 15306 pts/110 15439 S+ 1000 0:00 grep --color=auto -i 101_kill
$kill -SIGKILL -15435
$ps ajx |grep -i 101_kill
15306 15459 15458 15306 pts/110 15458 S+ 1000 0:00 grep --color=auto -i 101_kill
PID =0: 发送信号给 与调用kill函数进程属于同一进程组的所有进程
这个只能在函数里面去做了。
修改程序:
$cat 101_kill.c
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include<unistd.h>
#include<error.h>
#include<pthread.h>
#include<signal.h>
void sys_err(const char *str)
{
perror(str);
exit(1);
}
int main(int argc,char *argv[])
{
pid_t pid = fork();//fork yi ge zijincheng
if(pid > 0)
{
while(1)
{
printf("It's parent process!,pid = %d\n",getpid());
sleep(1);
}
}
else if(pid == 0)
{
while(1)
{
printf ("child process, pid = %d,ppid = %d\n",getpid(),getppid());
sleep(6);
kill(0,SIGKILL);
// while(1);
}
}
else
{
}
return 0;
}
$gcc 101_kill.c -o 101_kill -Wall -g
$./101_kill
It's parent process!,pid = 15588
child process, pid = 15589,ppid = 15588
It's parent process!,pid = 15588
It's parent process!,pid = 15588
It's parent process!,pid = 15588
It's parent process!,pid = 15588
It's parent process!,pid = 15588
Killed
$ps ajx |grep -i 101_kill
15242 15627 15626 15242 pts/108 15626 S+ 1000 0:00 grep --color=auto -i 101_kill
pid = -1: 发送给进程有权限发送的系统中的所有进程
kill -SIGKILL -1
直接退到锁屏界面。 然后拷贝功能(从乌班图拷贝到windows)之类的都无效。
重启一下就回复正常了
sudo init 6
权限保护: super用户root可以发送个任意用户,普通用户是不能先系统用户发送信号。
kill -9(root用户的pid)是不可以的。同样,普通用户也不能先其他普通用户发送信号,
终止其进程。只能向自己创建的进程发送信号。普通用户的基本规则:
发送者实际或有效用户ID == 接收者实际或者有效用户ID
sudo :super user do
$ps aux |more
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 4.6 0.0 34144 3388 ? Ss 13:49 0:02 /sbin/init
进程ID 1是init 进程,这个进程是linux系统中所有的进程的祖宗。
$kill -9 1
bash: kill: (1) - Operation not permitted