加入收藏 | 设为首页 | 会员中心 | 我要投稿 晋中站长网 (https://www.0354zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 服务器 > 搭建环境 > Windows > 正文

Linux下的进程间通信:套接字和信号

发布时间:2019-06-05 10:26:11 所属栏目:Windows 来源:Marty Kalin
导读:学习在 Linux 中进程是如何与其他进程进行同步的。 本篇是 Linux 下进程间通信(IPC)系列的第三篇同时也是最后一篇文章。第一篇文章聚焦在通过共享存储(文件和共享内存段)来进行 IPC,第二篇文章则通过管道(无名的或者命名的)及消息队列来达到相同的

信号会中断一个正在执行的程序,在这种意义下,就是用信号与这个程序进行通信。大多数的信号要么可以被忽略(阻塞)或者被处理(通过特别设计的代码)。SIGSTOP (暂停)和 SIGKILL(立即停止)是最应该提及的两种信号。这种符号常量有整数类型的值,例如 SIGKILL 对应的值为 9

信号可以在与用户交互的情况下发生。例如,一个用户从命令行中敲了 Ctrl+C 来终止一个从命令行中启动的程序;Ctrl+C 将产生一个 SIGTERM 信号。SIGTERM 意即终止,它可以被阻塞或者被处理,而不像 SIGKILL 信号那样。一个进程也可以通过信号和另一个进程通信,这样使得信号也可以作为一种 IPC 机制。

考虑一下一个多进程应用,例如 Nginx 网络服务器是如何被另一个进程优雅地关闭的。kill 函数:

  1. int kill(pid_t pid, int signum); /* declaration */

可以被一个进程用来终止另一个进程或者一组进程。假如 kill 函数的第一个参数是大于 0 的,那么这个参数将会被认为是目标进程的 pid(进程 ID),假如这个参数是 0,则这个参数将会被视作信号发送者所属的那组进程。

kill 的第二个参数要么是一个标准的信号数字(例如 SIGTERMSIGKILL),要么是 0 ,这将会对信号做一次询问,确认第一个参数中的 pid 是否是有效的。这样优雅地关闭一个多进程应用就可以通过向组成该应用的一组进程发送一个终止信号来完成,具体来说就是调用一个 kill 函数,使得这个调用的第二个参数是 SIGTERM 。(Nginx 主进程可以通过调用 kill 函数来终止其他工人进程,然后再停止自己。)就像许多库函数一样,kill 函数通过一个简单的可变语法拥有更多的能力和灵活性。

示例 3. 一个多进程系统的优雅停止

  1. #include <stdio.h>
  2. #include <signal.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <sys/wait.h>
  6.  
  7. void graceful(int signum) {
  8.   printf("tChild confirming received signal: %in", signum);
  9.   puts("tChild about to terminate gracefully...");
  10.   sleep(1);
  11.   puts("tChild terminating now...");
  12.   _exit(0); /* fast-track notification of parent */
  13. }
  14.  
  15. void set_handler() {
  16.   struct sigaction current;
  17.   sigemptyset(&current.sa_mask);         /* clear the signal set */
  18.   current.sa_flags = 0;                  /* enables setting sa_handler, not sa_action */
  19.   current.sa_handler = graceful;         /* specify a handler */
  20.   sigaction(SIGTERM, &current, NULL);    /* register the handler */
  21. }
  22.  
  23. void child_code() {
  24.   set_handler();
  25.  
  26.   while (1) {   /` loop until interrupted `/
  27.     sleep(1);
  28.     puts("tChild just woke up, but going back to sleep.");
  29.   }
  30. }
  31.  
  32. void parent_code(pid_t cpid) {
  33.   puts("Parent sleeping for a time...");
  34.   sleep(5);
  35.  
  36.   /* Try to terminate child. */
  37.   if (-1 == kill(cpid, SIGTERM)) {
  38.     perror("kill");
  39.     exit(-1);
  40.   }
  41.   wait(NULL); /` wait for child to terminate `/
  42.   puts("My child terminated, about to exit myself...");
  43. }
  44.  
  45. int main() {
  46.   pid_t pid = fork();
  47.   if (pid < 0) {
  48.     perror("fork");
  49.     return -1; /* error */
  50.   }
  51.   if (0 == pid)
  52.     child_code();
  53.   else
  54.     parent_code(pid);
  55.   return 0;  /* normal */
  56. }

(编辑:晋中站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读