37-使用 kill 函数发送信号

来源:互联网 发布:如何引出大数据 编辑:程序博客网 时间:2024/06/05 17:43

一直以来,我们给程序发送信号都是通过快捷键(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 函数
0 0
原创粉丝点击