Linux多线程3-4_向线程发送信号

简介: 一、发送信号的函数     int pthread_kill(pthread_t thread, int sig);     1、别被名字吓到,pthread_kill可不是kill,而是向线程发送signal。
一、发送信号的函数
    int pthread_kill(pthread_t thread, int sig);
    1、别被名字吓到,pthread_kill可不是kill,而是向线程发送signal。还记得signal吗,大部分signal的默认动作是终止进程的运行,所以,我们才要用sigaction()去抓信号并加上处理函数。

    2、向指定ID的线程发送sig信号,如果线程代码内不做处理,则按照信号默认的行为影响整个进程,也就是说,如果你给一个线程发送了SIGQUIT,但线程却没有实现signal处理函数,则整个进程退出。如果要获得正确的行为,就需要在线程内实现sigaction了。所以,如果int sig的参数不是0,那一定要清楚到底要干什么,而且一定要实现线程的信号处理函数,否则,就会影响整个进程。如果int sig是0呢,这是一个保留信号,其实并没有发送信号,作用是用来判断线程是不是还活着。

二、信号处理
    1、进程信号处理:
    int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
    给信号signum设置一个处理函数,处理函数在sigaction中指定
        act.sa_mask 信号屏蔽字
        act.sa_handler 信号集处理程序

    2、信号集的处理
    int sigemptyset(sigset_t *set); 清空信号集
    int sigfillset(sigset_t *set);  将所有信号加入信号集
    int sigaddset(sigset_t *set, int signum); 增加一个信号到信号集
    int sigdelset(sigset_t *set, int signum); 删除一个信号到信号集

    3、多线程信号屏蔽处理
    /* int sigprocmask(int how, const sigset_t *set, sigset_t *oldset)*/这是进程的信号屏蔽处理

    int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
         how = SIG_BLOCK:向当前的信号掩码中添加set,其中set表示要阻塞的信号组。
         SIG_UNBLOCK:向当前的信号掩码中删除set,其中set表示要取消阻塞的信号组。
         SIG_SETMASK:将当前的信号掩码替换为set,其中set表示新的信号掩码。
    在多线程中,新线程的当前信号掩码会继承创造它的线程的信号掩码
    一般情况下,被阻塞的信号将不能中断此线程的执行,除非此信号的产生是因为程序运行出错如 SIGSEGV;另外不能被忽略处理的信号 SIGKILL 和 SIGSTOP 也无法被阻塞。

三、手册
PTHREAD_KILL(3)            Linux Programmer’s Manual           PTHREAD_KILL(3)
NAME
       pthread_kill - send a signal to a thread
        // pthread_kill向线程发送一个信号

SYNOPSIS
       #include
        //包含头文件signal.h

       int pthread_kill(pthread_t thread, int sig);

       Compile and link with -pthread.
        //编译连接使用线程库

DESCRIPTION
       The  pthread_kill() function sends the signal sig to thread, another thread in the same process as the caller.  The signal is asynchronously
         directed to thread.
        // pthread_kill向同一进程中的另一个发送信号,这个信号异步的发送到线程

       If sig is 0, then no signal is sent, but error checking is still performed; this can be used to check for the  existence of a thread ID.
        //如果信号是0,实际并没有信号发送,这可以用来测试指定的线程ID是否存在

RETURN VALUE
       On success, pthread_kill() returns 0; on error, it returns an error number, and no signal is sent.
        //如果成功返回0,失败就返回错误码,没有信号发送

ERRORS
       ESRCH  No thread with the ID thread could be found.
        //没有指定的线程ID可以找到

       EINVAL An invalid signal was specified.
        //发送的信号是无效的

CONFORMING TO
       POSIX.1-2001.

NOTES
       Signal  dispositions  are  process-wide:  if  a  signal  handler is installed, the handler will be invoked in the thread
       thread, but if the disposition of the signal is "stop", "continue", or "terminate", this action will  affect  the  whole
       process.
        //进程中所有的线程对用一个信号使用同一个信号处理函数。如果信号处理函数被设置,它将会唤醒指定的线程。但如果信号是“stop”、
         //“continue ”、“terminate ”,将会影响整个进程

SEE ALSO
       kill(2) sigaction(2), sigpending(2), pthread_self(3), pthread_sigmask(3), raise(3), pthreads(7), signal(7)

COLOPHON
       This  page  is part of release 3.22 of the Linux man-pages project.  A description of the project, and information about
       reporting bugs, can be found at http://www.kernel.org/doc/man-pages/


PTHREAD_SIGMASK(3)         Linux Programmer’s Manual        PTHREAD_SIGMASK(3)
NAME
       pthread_sigmask - examine and change mask of blocked signals
        //检测或者改变信号的掩码   

SYNOPSIS
       #include
          //包含头文件

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

       Compile and link with -pthread.
          //编译连接线程库

DESCRIPTION
       The  pthread_sigmask()  function is just like sigprocmask(2), with the difference that its use in multithreaded programs
       is explicitly specified by POSIX.1-2001.  Other differences are noted in this page.
          // pthread_sigmask() 像 sigprocmask(2)一样,不同的地方是这个函数使用在多吸纳成环境中

       For a description of the arguments and operation of this function, see sigprocmask(2).
          //想看更详细的资料,去看手册 sigprocmask(2)

RETURN VALUE
       On success, pthread_sigmask() returns 0; on error, it returns an error number.
          //成功返回0,失败返回错误码

ERRORS
       See sigprocmask(2).
             //错误码参照 sigprocmask(2)

CONFORMING TO
       POSIX.1-2001.

NOTES
       A new thread inherits a copy of its creator’s signal mask.
        //一个新线程继承创造它的那个线程的掩码

四、实例

点击(此处)折叠或打开

  1. /*DATE:            2015-3-31
  2.  *AUTHOR:        WJ
  3.  *DECRIPTION:    正确到处理信号

  4.  *    int pthread_kill(pthread_t thread, int sig);
  5.  *        向线程thread发送sig信号,成功返回0,失败返回错误码
  6.  *
  7.  *    int sigaction(int signum, const struct sigaction *act, struct sigaction *oldact);
  8.  *        为信号signum设置处理函数,处理函数在sigaction中指定
  9.  *        act.sa_mask 信号屏蔽字
  10.  *        act.sa_handler 信号集处理程序
  11.  *
  12.  * int pthread_sigmask(int how, const sigset_t *set, sigset_t *oldset);
  13.  *        多线程信号屏蔽函数
  14.  *        how = SIG_BLOCK:向当前的信号掩码中添加set,其中set表示要阻塞的信号组。
  15.  *        SIG_UNBLOCK:向当前的信号掩码中删除set,其中set表示要取消阻塞的信号组。
  16.  * SIG_SETMASK:将当前的信号掩码替换为set,其中set表示新的信号掩码。
  17.  * 在多线程中,新线程的当前信号掩码会继承创造它的线程的信号掩码
  18.  */
  19. #include "apue.h"

  20. void sig_handler1(int arg)
  21. {
  22.     printf("thread1 get signal\n");
  23.     return;
  24. }
  25. void sig_handler2(int arg)
  26. {
  27.     printf("thread2 get signal\n");
  28.     return;
  29. }

  30. void *thread_fun1(void *arg)
  31. {
  32.     printf("new thread 1\n");

  33.     struct sigaction act;
  34.     memset(&act, 0, sizeof(act));
  35.     sigaddset(&act.sa_mask, SIGQUIT);
  36.     act.sa_handler = sig_handler1;
  37.     sigaction(SIGQUIT, &act, NULL);

  38.     pthread_sigmask(SIG_BLOCK, &act.sa_mask, NULL);
  39.     sleep(2);
  40. }


  41. void *thread_fun2(void *arg)
  42. {
  43.     printf("new thread 2\n");

  44.     struct sigaction act;
  45.     memset(&act, 0, sizeof(act));
  46.     sigaddset(&act.sa_mask, SIGQUIT);
  47.     act.sa_handler = sig_handler2;
  48.     sigaction(SIGQUIT, &act, NULL);

  49. //    pthread_sigmask(SIG_BLOCK, &act.sa_mask, NULL);
  50.     sleep(2);
  51. }

  52. int main()
  53. {
  54.     pthread_t tid1, tid2;
  55.     int err;
  56.     int s;

  57.     err = pthread_create(&tid1, NULL, thread_fun1, NULL);
  58.     if(err != 0)
  59.     {
  60.         printf("create new thread 1 failed\n");
  61.         return;
  62.     }
  63.     err = pthread_create(&tid2, NULL, thread_fun2, NULL);
  64.     if(err != 0)
  65.     {
  66.         printf("create new thread 2 failed\n");
  67.         return;
  68.     }

  69.     sleep(1);

  70.     s = pthread_kill(tid1, SIGQUIT);
  71.     if(s != 0)
  72.     {
  73.         printf("send signal to thread1 failed\n");
  74.     }
  75.     s = pthread_kill(tid2, SIGQUIT);
  76.     if(s != 0)
  77.     {
  78.         printf("send signal to thread2 failed\n");
  79.     }

  80.     pthread_join(tid1, NULL);
  81.     pthread_join(tid2, NULL);

  82.     return 0;
  83. } 






目录
打赏
0
0
0
0
53
分享
相关文章
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
在计算机系统的底层架构中,操作系统肩负着资源管理与任务调度的重任。当我们启动各类应用程序时,其背后复杂的运作机制便悄然展开。程序,作为静态的指令集合,如何在系统中实现动态执行?本文带你一探究竟!
【Linux进程概念】—— 操作系统中的“生命体”,计算机里的“多线程”
|
14天前
|
【Linux】阻塞信号|信号原理
本教程从信号的基本概念入手,逐步讲解了阻塞信号的实现方法及其应用场景。通过对这些技术的掌握,您可以更好地控制进程在处理信号时的行为,确保应用程序在复杂的多任务环境中正常运行。
115 84
|
1月前
|
python3多线程中使用线程睡眠
本文详细介绍了Python3多线程编程中使用线程睡眠的基本方法和应用场景。通过 `time.sleep()`函数,可以使线程暂停执行一段指定的时间,从而控制线程的执行节奏。通过实际示例演示了如何在多线程中使用线程睡眠来实现计数器和下载器功能。希望本文能帮助您更好地理解和应用Python多线程编程,提高程序的并发能力和执行效率。
65 20
|
1月前
|
Linux编程: 在业务线程中注册和处理Linux信号
本文详细介绍了如何在Linux中通过在业务线程中注册和处理信号。我们讨论了信号的基本概念,并通过完整的代码示例展示了在业务线程中注册和处理信号的方法。通过正确地使用信号处理机制,可以提高程序的健壮性和响应能力。希望本文能帮助您更好地理解和应用Linux信号处理,提高开发效率和代码质量。
57 17
|
1月前
|
Linux编程: 在业务线程中注册和处理Linux信号
通过本文,您可以了解如何在业务线程中注册和处理Linux信号。正确处理信号可以提高程序的健壮性和稳定性。希望这些内容能帮助您更好地理解和应用Linux信号处理机制。
63 26
Unity多线程使用(线程池)
在C#中使用线程池需引用`System.Threading`。创建单个线程时,务必在Unity程序停止前关闭线程(如使用`Thread.Abort()`),否则可能导致崩溃。示例代码展示了如何创建和管理线程,确保在线程中执行任务并在主线程中处理结果。完整代码包括线程池队列、主线程检查及线程安全的操作队列管理,确保多线程操作的稳定性和安全性。
|
3月前
|
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
96 1
Linux线程(十一)线程互斥锁-条件变量详解
Linux线程(十一)线程互斥锁-条件变量详解
【Linux】线程安全——补充|互斥、锁|同步、条件变量(下)
【Linux】线程安全——补充|互斥、锁|同步、条件变量(下)
81 0