专栏首页云端漫步使用信号进制实现进程通信

使用信号进制实现进程通信

进程间通信方式

学习操作系统的原理,我们知道,进程间通信有以下几种方式:

  • 管道(pipe)
  • 信号(signal)
  • 消息队列
  • 共享内存
  • 信号量
  • 套接字(socket)

而在应用系统开发中,我们常用的方式就是消息队列和套接字两种方式。在程序中写了一个死循环,运行时,常使用 ctrl+c来中断进程。突然软件卡死了,我们无法关闭,这时,你知道使用kill -9 pip来结束进程。这些基本的操作常识性操作,背后就使用的“信号量"和应用程序发生通信。

信号

信号(Signal)是Linux, 类Unix和其它POSIX兼容的操作系统中用来进程间通讯的一种方式。一个信号就是一个异步的通知,发送给某个进程,或者同进程的某个线程,告诉它们某个事件发生了。当信号发送到某个进程中时,操作系统会中断该进程的正常流程,并进入相应的信号处理函数执行操作,完成后再回到中断的地方继续执行。如果目标进程先前注册了某个信号的处理程序(signal handler),则此处理程序会被调用,否则缺省的处理程序被调用。这种方式只有事件类型,不能实现进程间数据传递。

发送信号

  • kill系统调用
  • kill命令用户发送信号
  • raise库函数发送信号给当前进程 也可以通过键盘发送特定命令实现发送信号,如 ctrl+c SIGINT ctrl+z SIGTSTP ctrl+\ SIGQUIT ctrl+T SIGINFO

信号处理

程序中可以设置接受信号,编写处理函数对信号进行拦截处理,信号有以下处理动作。其中SIGKILL和SIGSTOP不能被程序所捕捉做拦截处理 在mac电脑下,在命令终端输入 kill-l会列出所有的signal信息

HUP INT QUIT ILL TRAP ABRT EMT FPE KILL BUS SEGV SYS PIPE ALRM TERM URG STOP TSTP CONT CHLD TTIN TTOU IO XCPU XFSZ VTALRM PROF WINCH INFO USR1 USR2

通过信号实现守护进程退出提示

我们要终止一个服务进程,在终止前,让取它打印让其做个倒计时的功能。那么怎么实现这个小功能呢?这就需要用到信号,通过kill发送终止信号,在程序中编写捕捉函数,在信号被触发时,执行捕捉函数。

package main

import (
    "fmt"
    "os"
    "os/signal"
    "syscall"
    "time"
)

func main() {
    c := make(chan os.Signal)
    signal.Notify(c, syscall.SIGINT)
    fmt.Println("启动服务")
    sig := <-c
    fmt.Println("收到信号", sig)
    TipMsg()

    sum := 0
    for {
        sum += 1
        time.Sleep(1 * time.Second)
    }
}

func TipMsg() {
    fmt.Printf("5秒后退出程序。。。")
    for i := 5; i > 0; i-- {
        time.Sleep(1 * time.Second)
    }
    fmt.Println("退出程序")
    os.Exit(0)
}

go run server.go启动服务,按下 ctrl+c既可完成测试,也可以使用kill发送信号进行测试。方法

$go build
$./server
//另开一个终端tab
$ps -ef | grep server
$kill 2 pid(服务的进程id)

使用信号量实现配置文件热加载

我们在写程序时,常常将一些可控的参数通过配置文件的方式进行加载。这些参数也经常需要动态的调整,那么修改了配置文件后,就需要重新的加载配置文件,就需要重启服务。借助信号量是不就可以达到配置文件重新加载的目的。基于上边的例子,我们将TipMsg的操作改为配置文件重加载的操作,然后将信号修改为SIGUSR1, 完成修改后,使用kill -USER1 pid即可完成配置的重新加载。具体的实现可以参考这篇文章https://segmentfault.com/a/1190000019436438

参考:https://colobu.com/2015/10/09/Linux-Signals/ https://www.jianshu.com/p/f445bfeea40a

本文分享自微信公众号 - 云端漫记(BB_gzhsh),作者:暮雨

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-08-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 使用信号进制实现进程通信

    而在应用系统开发中,我们常用的方式就是消息队列和套接字两种方式。在程序中写了一个死循环,运行时,常使用<code>ctrl+c</code>来中断进程。突然软件...

    暮雨
  • HashMap 如何解决冲突?扩容机制?

    HashMap默认的容量是DEFAULT_INITIAL_CAPACITY,16。

    暮雨
  • 使用数组实现数据去重

    在上一篇数据去重文中,介绍了使用hashtable这种数据结构实现对一组数据的去重操作,那么这种方式是否存在优化的空间?先来看一道题,给定一组整数无序数组,获取...

    暮雨
  • Shell 信号发送与捕捉

    信号(Signal):信号是在软件层次上对中断机制的一种模拟,通过给一个进程发送信号,执行相应的处理函数。

    范蠡
  • Linux——Linux系统编程之进程间的通信-信号的使用总结(信号的基本概念、类型、常用函数、使用实践测试)

    软中断信号(signal,又简称为信号)用来通知进程发生了异步事件,用于处理异步事件。信号既可以在一个进程内通信,也可以用于不同进程间的通信,信号在驱动中应用的...

    Winter_world
  • matlab中使用VMD(变分模态分解)

    创建一个以4 kHz采样的信号,类似于拨打数字电话的所有键。将信号另存为MATLAB®时间数据。

    拓端
  • 10-3 信号

    见贤思齊
  • 时钟数据恢复CDR简介

    上周调研了光模块中的跨阻放大器TIA,今天主要调研下光模块中另一个重要的电芯片---CDR。

    光学小豆芽
  • Linux信号处理机制

    信号是一种进程间通信机制,信号都有一个对应的默认处理行为,信号触发时,信号处理函数和进程正常的执行流程同时存在,这会给编程带来隐患,如果信号处理函数中调用了不可...

    luoxn28
  • Unix系统服务监控 Monit

    Monit 是Unix系统中用于管理和监控进程、程序、文件、目录和文件系统的工具。使用 Monit 可以检测进程是否正常运行,如果异常可以自动重启服务以及报警,...

    用户2131907

扫码关注云+社区

领取腾讯云代金券