曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 4139|回复: 0
打印 上一主题 下一主题

[信号] kill() -- 给进程发送信号

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2012-7-29 19:09:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
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            #试图杀死一个并不存在的进程

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-6-7 05:51 , Processed in 0.086559 second(s), 25 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表