当前位置:   article > 正文

kill,alarm,raise,abort,pause,signal等函数的使用_kill函数原理

kill函数原理

1.1 kill

kill函数是UNIX和类UNIX操作系统中的一个标准库函数,主要用于向指定进程发送信号。

  1. #include <sys/types.h>
  2. #include <signal.h>
  3. int kill(pid_t pid, int signum);

pid_t pid 是进程ID,int signum 是信号的编号。

kill函数的作用是将signum指定的信号发送到pid指定的进程

  • pid > 0:将信号发送给进程ID为pid的进程。
  • pid = 0:将信号发送给当前进程所在的整个进程组中的所有进程。
  • pid < 0:将信号发送给进程组ID等于pid的绝对值的进程组中的所有进程。
  • pid = -1:将信号发送给系统中的所有进程,这个进程组号等于pid的绝对值。

kill函数的成功返回值为0,失败返回值为-1

此外,调用kill函数的进程必须有权限向目标进程发送信号。通常,只有root用户才能向所有进程发送信号,而非root用户只能向与自己用户ID相同的进程发送信号

案例

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <signal.h>
  5. #include <sys/types.h>
  6. int main()
  7. {
  8. pid_t pid;
  9. pid = fork();
  10. if(pid < 0)
  11. {
  12. perror("fail to fork");
  13. exit(1);
  14. }
  15. else if(pid > 0) //父进程的代码区
  16. {
  17. while(1)
  18. {
  19. printf("This is parent peocess\n");
  20. sleep(1);
  21. }
  22. }
  23. else //子进程的代码区
  24. {
  25. printf("This is son process\n");
  26. //子进程在3秒之后,让父进程退出
  27. sleep(3);
  28. //使用kill给父进程发送信号,然后父进程接收到信号后直接退出就可以了
  29. kill(getppid(), SIGINT);
  30. }
  31. return 0
  32. }

执行结果

 1.2 alarm函数

alarm函数是UNIX和类UNIX系统中的一种标准库函数,它的主要作用是为当前进程设置一个定时器。

当设定时间到达后,定时器会向当前进程发送SIGALRM信号。

这个信号的默认行为是终止进程,但如果进程中有一个已注册的信号处理函数来处理SIGALRM信号,那么进程会根据该函数的逻辑来执行相应的操作

  1. #include <sys/time.h>
  2. unsigned int alarm(unsigned int seconds);

seconds参数

指定了定时器的超时时间,单位是秒。

如果seconds的值为0,那么之前设置的定时器会被取消,并且返回之前定时器剩余的时间。

如果seconds的值为-1,那么返回的是0

alarm函数的返回值有以下几种情况

  • 如果seconds的值为0,返回值也是0。
  • 如果seconds的值大于0,并且在seconds秒内再次调用了alarm函数设置了新的定时器,那么返回值是之前定时器剩余的秒数。
  • 如果seconds的值大于0,并且没有在seconds秒内再次调用alarm函数设置新的定时器,那么返回值是0

案例

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #int main()
  4. {
  5. unsigned int sec;
  6. //当执行到alarm之后,代码会接着往下执行,当设定的时间到后,会产生SIGALRM信
  7. //如果alarm之前没有设置其他闹钟,则返回0,如果之前设置了,则返回之前剩余的
  8. //如果一个程序中出现多个alarm闹钟,第一个如果没有到达指定的时间就遇到第二个
  9. //则第一个的闹钟时间清除,按照第二个alarm闹钟的时间继续向下运行
  10. sec = alarm(5);
  11. printf("sec = %d\n", sec);
  12. sleep(3);
  13. sec = alarm(6);
  14. printf("sec = %d\n", sec);
  15. while(1)
  16. {
  17. printf("hello world\n");
  18. sleep(1);
  19. }
  20. return 0;
  21. }

执行结果

  1.3 raise函数

raise函数主要用于向当前进程发送一个信号。这个函数的原型如下:

  1. #include <signal.h>
  2. int raise(int sig);

sig参数是你想要发送的信号的名字

。这个函数的工作原理是,当你调用raise函数并传入一个特定的信号名时,它会向当前进程发送这个信号

返回值:  成功:0  

                失败:非0

raise(sig)  等同于   kill(getpid(), sig)

案例

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <signal.h>
  4. #include <unistd.h>
  5. #include <sys/types.h>
  6. int main(int argc, char const *argv[])
  7. {
  8. int num = 0;
  9. while(1)
  10. {
  11. printf("hello world\n");
  12. sleep(1);
  13. num++;
  14. //当循环执行5秒后,进程退出
  15. if(num == 5)
  16. {
  17. //使用raise给当前进程本身发送信号
  18. raise(SIGALRM);
  19. //等同于kill(getpid(), SIGALRM);
  20. }
  21. }
  22. return 0;
  23. }

执行结果

1.4 abort函数 

abort函数是C语言中的一个标准库函数,其原型定义在<stdlib.h>头文件中

该函数的主要作用是使当前的进程异常终止,即立即停止当前正在执行的程序,而不进行正常的资源回收和清理工作。

  1. #include <stdlib.h>
  2. void abort(void);
  3. 功能:向进程发送一个SIGABRT信号,默认情况下进程会退出。
  4. 参数:无
  5. 返回值:无

 注意即使SIGABRT信号被加入阻塞集,一旦进程调用了abort函数,进程也还是会被终止, 且在终止前会刷新缓冲区,关闭文件描述符。

案例

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <signal.h>
  4. #include <unistd.h>
  5. #include <sys/types.h>
  6. int main()
  7. {
  8. int num = 0;
  9. while(1)
  10. {
  11. printf("hello world\n");
  12. sleep(1);
  13. num++;
  14. //当循环执行5秒后,进程退出
  15. if(num == 5)
  16. {
  17. abort();
  18. }
  19. }
  20. return 0;
  21. }

执行结果

1.5 pause函数

pause函数作用是使当前进程进入等待状态,直到接收到一个信号为止。

这个函数通常用于等待某个特定的事件发生,例如等待用户输入或者等待某个条件满足。

  1. #include <sys/wait.h>
  2. int pause(void);

返回值当有信号产生时,函数返回‐1

案例

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <signal.h>
  5. #include <sys/types.h>
  6. int main()
  7. {
  8. pid_t pid;
  9. pid = fork();
  10. if(pid < 0)
  11. {
  12. perror("fail to fork");
  13. exit(1);
  14. }
  15. else if(pid > 0) //父进程的代码区
  16. {
  17. printf("This is parent peocess\n");
  18. //使用pause阻塞等待捕捉信号
  19. pause();
  20. }
  21. else //子进程的代码区
  22. {
  23. printf("This is son process\n");
  24. sleep(3);
  25. kill(getppid(), SIGINT);//睡眠三秒后杀死父进程
  26. }
  27. return 0;
  28. }

执行结果

1.6 signal函数

signal函数是用于设置一个特定的信号处理函数的标准库函数。

当进程接收到一个信号时,signal函数允许你指定一个函数来处理这个信号。

  1. #include <signal.h>
  2. void (*signal(int sig, void (*func)(int)))(int);
  3. ‐‐>
  4. typedef void (*sighandler_t)(int);
  5. sighandler_t signal(int signum, sighandler_t handler);
  6. 功能:当进程中产生某一个信号时,对当前信号进行处理
  7. 参数:
  8. sig:指定要处理的信号
  9. handler:处理方式
  10. SIG_IGN 当信号产生时,以缺省(忽略)的方式处理
  11. SIG_DFL 当信号产生时,以当前信号默认的方式处理

func是你想要设置的信号处理函数。信号处理函数必须具有以下形式

void func(int sig);

当信号产生时,通过信号处理函数自定义方式处理,函数名可以随便写,参数表示当前的信号

 返回值: 成功:返回函数地址,该地址为此信号上一次注册的信号处理函数的地址

                 失败:SIG_ERR

1.6.1  signal函数的使用

  1. #include <stdio.h>
  2. #include <signal.h>
  3. #include <unistd.h>
  4. #include <stdlib.h>
  5. void handler(int sig);
  6. int main(int argc, char const *argv[])
  7. {
  8. //以默认的方式处理信号
  9. #if 0
  10. if(signal(SIGINT, SIG_DFL) == SIG_ERR)
  11. {
  12. perror("fail to signal");
  13. exit(1);
  14. }
  15. if(signal(SIGQUIT, SIG_DFL) == SIG_ERR)
  16. {
  17. perror("fail to signal");
  18. exit(1);
  19. }
  20. if(signal(SIGTSTP, SIG_DFL) == SIG_ERR)
  21. {
  22. perror("fail to signal");
  23. exit(1);
  24. }
  25. #endif
  26. //以忽略的方式来处理信号
  27. #if 0
  28. if(signal(SIGINT, SIG_IGN) == SIG_ERR)
  29. {
  30. perror("fail to signal");
  31. exit(1);
  32. }
  33. if(signal(SIGQUIT, SIG_IGN) == SIG_ERR)
  34. {
  35. perror("fail to signal");
  36. exit(1);
  37. }
  38. if(signal(SIGTSTP, SIG_IGN) == SIG_ERR)
  39. {
  40. perror("fail to signal");
  41. exit(1);
  42. }
  43. //注意:SIGKILL和SIGSTOP这两个信号只能以默认的方式处理,不能忽略或者捕捉
  44. // if(signal(SIGKILL, SIG_IGN) == SIG_ERR)
  45. // {
  46. // perror("fail to signal");
  47. // exit(1);
  48. // }
  49. #endif
  50. //以用户自定义方式处理信号
  51. #if 1
  52. if(signal(SIGINT, handler) == SIG_ERR)
  53. {
  54. perror("fail to signal");
  55. exit(1);
  56. }
  57. if(signal(SIGQUIT, handler) == SIG_ERR)
  58. {
  59. perror("fail to signal");
  60. exit(1);
  61. }
  62. if(signal(SIGTSTP, handler) == SIG_ERR)
  63. {
  64. perror("fail to signal");
  65. exit(1);
  66. }
  67. #endif
  68. while(1)
  69. {
  70. printf("hello world\n");
  71. sleep(1);
  72. }
  73. return 0;
  74. }
  75. void handler(int sig)
  76. {
  77. if(sig == SIGINT)
  78. {
  79. printf("SIGINT正在处理\n");
  80. }
  81. if(sig == SIGQUIT)
  82. {
  83. printf("SIGQUIT正在处理\n");
  84. }
  85. if(sig == SIGTSTP)
  86. {
  87. printf("SIGTSTP正在处理\n");
  88. }
  89. }

在使用signal函数时,还需要考虑信号处理的同步和互斥问题,以确保程序的正确性和稳定性

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/煮酒与君饮/article/detail/788126
推荐阅读
相关标签
  

闽ICP备14008679号