kill() 函数原型如下:
[C++] 纯文本查看 复制代码 #include <signal.h>
int kill(pid_t pid, int sig);
kill() 函数的作用是给进程发送信号,可以用它来模拟 kill 命令的这一功能。
kill 有两个参数,第 1 个参数 pid 指示要发送信号到哪个进程上;第 2 个参数 sig 表示要发送那种类型信号,比如 9 表示要杀死该进程。
如果 pid 是一个大于 0 的值,那么就发送到该 pid 所指示的进程上。
如果 pid 的值等于 0 ,那么它发送到和调用进程所在进程组里每一个进程,包括调用进程本身。
如果 pid 等于 -1,那么信号将发送到调用进程所拥有权限发送的所有进程上,除 init (PID 值为 1) 和 它自己。有时称这种发送信号方式为“广播信号”(broadcast signals)。
如果 pid 小于 -1,那么信号将发送往进程组 ID 为 PID 绝对值的进程组中的所有进程。
如果 sig 的值为 0,那么不会发送信号,但可以做错误检查,即可以用来检测某个进程或者进程组是否存在。
如果指定的 PID 实际不存在,那么 kill() 返回错误,错误号为 ESRCH ("No such process") 。
进程发送信号是与权限先关的,相关规则如下:
1. 特权进程(CAP_KILL)可以给任何进程发送信号。
2. init 进程是个例外,它的属主和组都为 root;虽然可以给它发送信号,但前提是必须是它已经安装了对该信号的处理机制(如用 signal() 或 sigaction() 安装信号处理函数)。
3. 对于非特权进程,发送进程的真实用户 ID 或有效用户 ID 必须等于目标进程的真实用户 ID(real user id) 或 保存的设置用户 ID (saved set-user-ID),如下图所示:
4. 对于 SIGCONT 信号有点特殊。一个非特权进程可以发送该信号到与之同一会话的其他进程,而不用进行用户ID检查。该规则允许作业控制 shell 重新启动已经停止的作业(进程组),甚至是该作业中的进程已经改变了他们的用户 ID 。
测试代码:
[C++] 纯文本查看 复制代码 #include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
int main(int argc, char **argv)
{
int s, sig, pid;
if (argc != 3 || strcmp(argv[1], "--help") == 0) {
printf ("usage: %s sig-num pid\n", argv[0]);
exit (EXIT_FAILURE);
}
sig = atoi(argv[1]);
pid = atoi(argv[2]);
s = kill(pid, sig);
if (s != 0) {
if (s == -1) {
perror("kill");
exit(EXIT_FAILURE);
}
} else {
if (s == 0) {
printf ("Process exists and we can send it a signal\n");
} else {
if (errno == EPERM)
printf ("Process exists, but we don't have permission to send it a signal\n");
else if (errno == ESRCH)
printf ("Process does not exist\n");
else
perror ("kill");
}
}
exit (EXIT_SUCCESS);
}
在运行该程序之前,可以运行一个无限循环输出的测试脚本,如:
[Bash shell] 纯文本查看 复制代码 #!/bin/sh
while true
do
echo "hello linux"
sleep 3
done
接着在另一个终端窗口里使用 ps 命令找出该脚本的 PID,然后如下运行上面的程序:[beyes@beyes signal]$ ./killer 9 2385
Process exists and we can send it a signal 回过来看到上面的脚本进程已经被杀死。[beyes@beyes signal]$ ./tmp.sh
hello linux
hello linux
hello linux
hello linux
hello linux
已杀死
又如:[beyes@beyes signal]$ ./killer 9 1153
kill: Operation not permitted #普通用户试图杀死 root 用户的进程
[beyes@beyes signal]$ ./killer 9 3333
kill: No such process #试图杀死一个并不存在的进程 |