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. } 






相关文章
|
11天前
|
安全 算法 Linux
【Linux】线程安全——补充|互斥、锁|同步、条件变量(下)
【Linux】线程安全——补充|互斥、锁|同步、条件变量(下)
19 0
|
11天前
|
存储 安全 Linux
【Linux】线程安全——补充|互斥、锁|同步、条件变量(上)
【Linux】线程安全——补充|互斥、锁|同步、条件变量(上)
17 0
|
11天前
|
缓存 Linux 编译器
【Linux】多线程——线程概念|进程VS线程|线程控制(下)
【Linux】多线程——线程概念|进程VS线程|线程控制(下)
25 0
|
11天前
|
存储 Linux 调度
【Linux】多线程——线程概念|进程VS线程|线程控制(上)
【Linux】多线程——线程概念|进程VS线程|线程控制(上)
29 0
|
15天前
|
Java
实现Java多线程中的线程间通信
实现Java多线程中的线程间通信
|
13天前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
28 1
|
13天前
|
设计模式 存储 安全
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:设计一个线程安全的单例类并解释其内存占用情况?使用Java多线程工具类实现一个高效的线程池,并解释其背后的原理。结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
25 1
|
16天前
|
Java
实现Java多线程中的线程间通信
实现Java多线程中的线程间通信
|
13天前
|
设计模式 并行计算 安全
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
Java面试题:如何使用设计模式优化多线程环境下的资源管理?Java内存模型与并发工具类的协同工作,描述ForkJoinPool的工作机制,并解释其在并行计算中的优势。如何根据任务特性调整线程池参数
15 0
|
13天前
|
设计模式 安全 NoSQL
Java面试题:结合单例模式与Java内存管理,设计一个线程安全的单例类?分析Java多线程工具类ExecutorService与Java并发工具包中的工具类,设计一个Java并发框架的分布式锁实现
Java面试题:结合单例模式与Java内存管理,设计一个线程安全的单例类?分析Java多线程工具类ExecutorService与Java并发工具包中的工具类,设计一个Java并发框架的分布式锁实现
18 0