博客
关于我
【Linux】进程间通信---信号
阅读量:498 次
发布时间:2019-03-07

本文共 2030 字,大约阅读时间需要 6 分钟。

信号在운算中的应用

1. 信号定义

信号是一个中断软件,它用于通知进程某种事件发生。在典型的 Embedded Unix 系统中,信号有两种形式:可靠非可靠

信号分类

  • 非可靠信号 (1~31, 33~63): 不保证按时发送,默认处理方式(SIG_DFL)。
  • 可靠信号 (34~64): 定时发送,拥有进程 ID,允许发送进程等待确认。

2. 信号的产生方式

信号可以通过 硬件软件 生成,并影响目标进程。

硬件产生的信号

  • Ctrl+C: 2号信号(SIGINT),默认终止前台进程。
  • Ctrl+Z: 20号信号(SIGTSTP),暂停前台进程。
  • Ctrl+|: 3号信号(SIGQUIT),退出当前程序。

软件产生的信号

  • kill命令: 可以发送任意信号,例如 kill -9 PID
  • abort函数: 生成 6号信号(SIGABRT),常用于抛出错误。
  • 越界或解引用: 生成 11号信号(SIGSEGV)。

3. 信号注册

信号注册是将信号映射到特定处理函数的过程。Linux 使用 sigarrays 来处理信号。

sigarray 操作流程

  • 非可靠信号:

  • 将对应位图位置设置为 1。
  • 创建 sigqueue 节点,添加至 sigqueue 队列。
  • 若队列已有节点,忽略重复操作。
  • 可靠信号:

  • 设置 sigarray 中对应位图为 1。
  • 创建 sigqueue 节点,强制添加至 sigqueue 队列(重复也会拉取)。

4. 信号注销

信号注销仅适用于非可靠信号,因为可靠信号无法回滞。

非可靠信号注销

  • 从 sigqueue 队列中移除对应 sigqueue 节点。
  • 重置 sigarray 中对应位图设置为 0。

  • 5. 信号处理

    信号处理可以是默认或者自定义处理。

    自定义处理方式

    • 使用 signal 函数定义处理函数:
      typedef void (*sighandler_t)(int);
      int signal(int signum, sighandler_t handler);

      例如:

      signal(2, sigback); // 处理 2号信号

    6. sigaction 函数

    sigaction 函数允许更复杂的处理逻辑。

    sigaction 结构

    struct sigaction {
    void (*sa_handler)(int); // 处理函数指针
    void (*sa_sigaction)(int, siginfo_t *, void*); // 复杂处理
    sigset_t sa_mask; // collector mask
    int sa_flags; // SA_* 标记
    void (*sa_restorer)(void); // 恢复函数
    };

    使用示例

    void sigback(int signo) { printf("signo: %d\n", signo); }
    int main() {
    struct sigaction act;
    act.sa_flags = SA_SIGINFO; // 设置处理方式为 sigaction 函数
    act.sa_handler = sigback;
    sigaction(2, &act, NULL);
    while (1) {
    printf("linux so easy!\n");
    sleep(1);
    }
    return 0;
    }

    7. 信号捕捉流程

    信号捕捉发生在:

  • 进程进入内核空间。
  • 调用 do_signal 函数处理信号。
  • 具体步骤

  • 进入内核空间: 调用系统调用函数或库函数。
  • 处理信号: 调用 do_signal
  • 执行信号处理函数:
    • 使用 sa_handlersa_sigaction 根据 sa_flags 调用相应函数。

  • 8. 信号阻塞

    信号阻塞允许进程暂时不响应特定信号。

    使用方法

  • 调用 sigprocmask 函数设置 sig_setsig_unblock 操作模式。
  • 示例:
  • #include 
    #include
    int main() {
    sigset_t mask;
    sigset_t old_mask;
    sigempty(mask); // 初始化阻塞位图
    sigprocmask(SIG_BLOCK, &mask, &old_mask);
    // 之后可以根据需求调用 sig_unblock 或 sig_setmask
    sleep(1);
    return 0;
    }

    通过以上方法,可以更好地管理和处理信号,在嵌入式开发中实现高效 middlewares。

    转载地址:http://lnacz.baihongyu.com/

    你可能感兴趣的文章
    解决微信小程序项目导入的问题:app.json 未找到、 __wxConfig is not defined
    查看>>
    非迅捷|PDF、Word、PPT、Excel、图片等互相在线转换:免费、简单、快速、零错误、无套路
    查看>>
    Java面试题整理,闭关在家37天“吃透”这份345页PDF,纯干货
    查看>>
    word文档手写字母总会大写问题
    查看>>
    laravel server error 服务器内部错误
    查看>>
    iJ配置Maven环境详解
    查看>>
    面试题 08.01. 三步问题
    查看>>
    剑指 Offer 11. 旋转数组的最小数字
    查看>>
    作为我的第一篇csdn博客吧
    查看>>
    一道简单的访问越界、栈溢出pwn解题记录
    查看>>
    响应的HTTP协议格式+常见的响应码
    查看>>
    将windows里的内容直接复制粘贴到ubuntu,提高效率
    查看>>
    [PHP] error_reporting(0)可以屏蔽Fatal error错误
    查看>>
    thinkphp 的一些重要知识点
    查看>>
    Java学习第二章——Java基本语句
    查看>>
    遇到问题之-yum update无法连接镜像问题解决
    查看>>
    pycharm如何设置(错误、警告类的标准提醒)
    查看>>
    Python3运行的时候错误:ModuleNotFoundError: No module named 'PIL'
    查看>>
    PHP是世界上最好的语言?Phython第一个不服
    查看>>
    Bugku CTF-web6
    查看>>