热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

100多线程与信号

不知道你是否还记得之前在进程中的信号处理时,提到过阻塞信号集与未决信号集的概念,如果你已经忘记了,请参考《阻塞信号与未决信号》一文回忆一下

不知道你是否还记得之前在进程中的信号处理时,提到过阻塞信号集未决信号集的概念,如果你已经忘记了,请参考《阻塞信号与未决信号》一文回忆一下。


1. 多线程程序中的信号

在多线程中,每一个线程都有属于自己的阻塞信号集与未决信号集。当一个线程派生另一个线程的时候,会继承父线程的阻塞信号集,但是不会继承未决信号集,并且新线程会清空未决信号集。


2. 相关函数


2.1 设置阻塞信号集的函数

在多线程程序中,如果要设置线程的阻塞信号集,不能再使用 sigprocmask 函数,而应该使用 pthread_sigmask,其定义如下:

int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);

这个函数的用法和 sigprocmask 是一样的。


  • how 参数

    • SIG_BLOCK 该选项表示将 set 参数指示的信号集中的信号添加到进程阻塞集中
    • SIG_UNBLOCK 该选项与功能 SIG_BLOCK 相反,表示将线程阻塞信号集中指定的信号删除
    • SIG_SETMASK 该选项表示将线程阻塞信号集直接设定为你指定的 set
  • set 参数

表示你指定的信号集合


  • oldset

返回旧的阻塞信号集


  • 返回值 int

0 表示成功,-1 失败。


2.2 获取未决信号的函数

该函数仍然是 sigpending,没有变化。它的原型如下:

int sigpending(sigset_t *set);

2.3 信号发送函数

kill 函数只能给指定的进程发送函数,而是使用 pthread_kill 可以给指定的线程发送函数。它的原型如下:

int pthread_kill(pthread_t thread, int sig);

3. 实验

程序 th_sig 做了下面几个工作:


  • 在主线程阻塞了 SIGQUIT 信号
  • 在 fun1 线程中阻塞了 SIGINT 信号
  • 在 fun2 线程中什么也没阻塞

3.1 代码

// th_sig.c
#include
#include
#include
#include // 打印信号集
void printsigset(const sigset_t *set) {int i;for (i &#61; 1; i <&#61; 64; i&#43;&#43;) {if (i&#61;&#61;33) putchar(&#39; &#39;);if (sigismember(set, i) &#61;&#61; 1)putchar(&#39;1&#39;);elseputchar(&#39;0&#39;);}puts("");
}// fun1 线程
void* fun1(void* arg) {// 阻塞 SIGINT 信号sigset_t mask, st; sigemptyset(&mask);sigaddset(&mask, SIGINT);pthread_sigmask(SIG_BLOCK, &mask, NULL);while(1) {printf("I&#39;m fun1:\t");sigpending(&st);printsigset(&st);sleep(3);}
}// fun2 线程
void* fun2(void* arg) {sigset_t st; while(1) {printf("I&#39;m fun2:\t");sigpending(&st);printsigset(&st);sleep(3);}
}int main() {// 创建线程前阻塞 SIGQUITsigset_t mask, st; sigemptyset(&mask);sigaddset(&mask, SIGQUIT);pthread_sigmask(SIG_BLOCK, &mask, NULL);pthread_t tid1, tid2;pthread_create(&tid1, NULL, fun1, NULL);pthread_create(&tid2, NULL, fun2, NULL);sleep(2);pthread_kill(tid1, SIGINT);while(1) {printf("I&#39;m main:\t");sigpending(&st);printsigset(&st);sleep(3);}return 0;
}

3.2 编译与运行


  • 编译

$ gcc th_sig.c -o th_sig -lpthread

  • 运行



这里写图片描述
图1 运行结果

关于图 1 的说明&#xff1a;左侧是线程的名字&#xff0c;右侧是打印的未决队列&#xff0c;也就是未被信号处理函数处理的信号。其中第 1 列是 SIGHUP 信号&#xff0c;第 2 列表示 SIGINT 信号&#xff0c;第 3 列表示 SIGQUIT 信号。

当主线程休眠 2 秒后&#xff0c;给线程 fun1 发送了一个 SIGINT 信号&#xff0c;此时 fun1 的未决信号集中第 2 列变成了 1 &#xff08;图 1 上的第 5 行&#xff09;。

在后面某个时候&#xff0c;按下了 CTRL &#43; \&#xff0c;表示发送信号 SIGQUIT 给前台进程组中的进程。接下来&#xff0c;可以发现&#xff0c;所有的线程未决信号集中的第 3 列都变成了 1. 这说明了两件事&#xff1a;


  • 线程继承了父线程阻塞信号集
  • kill 信号会发送给进程中的所有线程

4. 总结


  • 每个线程有自己的阻塞信号集与未决信号集
  • 线程会继承父线程的阻塞信号集&#xff0c;新线程会清空未决信号集
  • pthread_kill 发送信号给指定线程
  • kill 发送信号给所有线程

推荐阅读
  • 本文深入探讨了UNIX/Linux系统中的进程间通信(IPC)机制,包括消息传递、同步和共享内存等。详细介绍了管道(Pipe)、有名管道(FIFO)、Posix和System V消息队列、互斥锁与条件变量、读写锁、信号量以及共享内存的使用方法和应用场景。 ... [详细]
  • RTThread线程间通信
    线程中通信在裸机编程中,经常会使用全局变量进行功能间的通信,如某些功能可能由于一些操作而改变全局变量的值,另一个功能对此全局变量进行读取& ... [详细]
  • 在多线程编程环境中,线程之间共享全局变量可能导致数据竞争和不一致性。为了解决这一问题,Linux提供了线程局部存储(TLS),使每个线程可以拥有独立的变量副本,确保线程间的数据隔离与安全。 ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • Linux设备驱动程序:异步时间操作与调度机制
    本文介绍了Linux内核中的几种异步延迟操作方法,包括内核定时器、tasklet机制和工作队列。这些机制允许在未来的某个时间点执行任务,而无需阻塞当前线程,从而提高系统的响应性和效率。 ... [详细]
  • 作者:守望者1028链接:https:www.nowcoder.comdiscuss55353来源:牛客网面试高频题:校招过程中参考过牛客诸位大佬的面经,但是具体哪一块是参考谁的我 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 本文探讨了一个在Mac Mavericks系统上使用Clang++成功编译但通过R CMD SHLIB构建并在R中加载时遇到‘符号未找到’错误的C++程序问题。文章详细分析了错误原因,并提供了有效的解决方案。 ... [详细]
  • 在一个大型的应用系统中,往往需要多个进程相互协作,进程间通信(IPC,InterProcessCommunication)就显得比较重要了。在Linux系统中,有很多种IPC机制, ... [详细]
  • 在将应用的 Android SDK 更新至 Target 29 后,使用 Facebook SDK 5.8.0 的应用程序在 Android 10 设备上出现崩溃。本文探讨了可能的原因及解决方案。 ... [详细]
  • 本文探讨了Linux环境下线程私有数据(Thread-Specific Data, TSD)的概念及其重要性,介绍了如何通过TSD技术避免多线程间全局变量冲突的问题,并提供了具体的实现方法和示例代码。 ... [详细]
  • 本文总结了Java程序设计第一周的学习内容,涵盖语言基础、编译解释过程及基本数据类型等核心知识点。 ... [详细]
  • 本文将深入探讨 Unreal Engine 4 (UE4) 中的距离场技术,包括其原理、实现细节以及在渲染中的应用。距离场技术在现代游戏引擎中用于提高光照和阴影的效果,尤其是在处理复杂几何形状时。文章将结合具体代码示例,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 本文介绍了如何在Linux系统中获取库源码,并在从源代码编译软件时收集所需的依赖项列表。 ... [详细]
author-avatar
筱庆儿宝贝
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有