37-使用 kill 函数发送信号

一直以来,我们给程序发送信号都是通过快捷键(Ctrl+C, Ctrl+Z, Ctrl+\) 或者使用系统命令kill来向进程发送信号(还有一种是系统给你发送的信号,比如 SIGCHLD、SIGSEGV 等等)。除此之外,也可以通过函数 int kill(pid_t pid, int sig) 来向进程发送信号。kill 函数是 POSIX 定义的。

实际上还有一个函数名为 raise,它是 ANSI C 定义的函数(在 ANSI C中就没有多进程的概念,所以该函数是给本进程发信号)。对于单线程的程序来说,raise 函数就是给本进程发信号,相当于kill(getpid(), sig);对于多线程的程序来说,它是给本线程发送信号,相当于pthread_kill(pthread_self(), sig)(有点扯远了,大家忽略)。

所以,学会了 kill 函数,自然也就会了 raise

1. kill 函数原型

int kill(pid_t pid, int sig);
  • 参数 pid

    • pid > 0,表示向进程号为 pid 的进程发信号
    • pid = 0,表示向同组进程发信号(有权限才行)
    • pid < -1,向进程组 |pid| 发信号(有权限才行)
    • pid = -1,向所有进程发信号(有权限才行,早期的 POSIX 并未定义此种情况)

所以,最常用的就是 pid > 0 的情况了,其它情况暂时还不会,因为你还不懂什么是进程组,就此略过,等讲到进程组的概念的时候,自然就懂了。

  • 参数 sig

表示向进程发送什么信号。如果 sig 为 0 ,通常用来测试是否有权限向进程发信号。

2. 实例

这个例子很简单,父进程 fork 出一个子进程,然后该子进程向父进程发送 10 次信号。父进程 fork 完后每 10 称向屏幕打点。

  • 代码
// mykill.c
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <wait.h>
#include <stdio.h>
#include <stdlib.h>


void handler(int sig) {
  if (sig == SIGUSR1) {
    printf("Hello my child\n");
  }
  else if (sig == SIGCHLD) {
    wait(NULL);
  }
}


void child() {
  int n = 10; 
  while(n--) {
    if (kill(getppid(), SIGUSR1) == -1) {
      perror("kill");
    }   
    sleep(1);
  }

  exit(0);
}

int main() {
  if (SIG_ERR == signal(SIGUSR1, handler)) {
    perror("signal SIGUSR1");
  }
  if (SIG_ERR== signal(SIGCHLD, handler)) {
    perror("signal SIGUSR2");
  }

  pid_t pid = fork();

  if (pid == 0) child();
  else if (pid == -1) {
    perror("fork");
  }

  while(1) {
    write(STDOUT_FILENO, ".", 1); 
    sleep(10);
  }

  return 0;
}
  • 编译并运行
$ gcc mykill.c -o mykill
$ ./mykill
  • 结果
.Hello my child
.Hello my child
.Hello my child
.Hello my child
.Hello my child
.Hello my child
.Hello my child
.Hello my child
.Hello my child
.Hello my child
.......
  • 结果分析

如果父进程收到子进程发来的信号,父进程在信号处理函数里打印 Hello my child。值得注意的是,每次父进程打印完Hello my child 后就会立即打印一个点,原因后面的文章会讲。

3. 总结

  • 掌握 kill 函数
  • 掌握 raise 函数(请自己练习)
  • 信号会中断父进程的 sleep 函数
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值