目录
一、验证环境
二、知识点回顾
三、简介
四、自定义函数
1、MyAbort
(1)描述
(2)定义
(3)参数
(4)返回值
(5)其他
2、MySystem
(1)描述
(2)定义
(3)参数
(4)返回值
(5)其他
五、信号函数
1、pthread_sigmask
(1)描述
(2)声明
(3)参数
(4)返回值
(5)其他
2、sigwait
(1)描述
(2)声明
(3)参数
(4)返回值
(5)其他
3、pthread_kill
(1)描述
(2)声明
(3)参数
(4)返回值
(5)其他
六、DEMO
1、system
(1)测试代码
(3)运行效果
2、sigwait
(1)测试代码
(3)运行效果
3、sigwait2
(1)测试代码
一、验证环境
名称 | 值 |
CPU | Intel(R) Core(TM) i5-1035G1 CPU @ 1.00GHz |
操作系统 | CentOS Linux release 7.9.2009 (Core) |
内存 | 5G |
逻辑核数 | 6 |
二、知识点回顾
大家可以参考之前的博客《Unix环境高级编程-学习-11-信号之初识》
三、简介
基于进程的信号处理是比较复杂的,再把线程加入,信号处理变得更加复杂。
每个线程都有自己的信号屏蔽字,但信号处理是进程中所有线程共享的。也就是线程可以阻止某些信号,但某个线程修改了特定信号的处理行为后,所有的线程都共享这个处理行为的改变。如果一个线程选择忽略某个特定信号,那么另外的线程就可以通过以下两种方式撤销线程的信号选择:
1、恢复信号的默认处理行为。
2、为信号设置一个新的信号处理程序。
进程中的信号是递送到单个线程的。如果一个信号与硬件故障相关,那么该信号一般会被发送到引起该事件的线程中去,其他的信号责备发送到任意一个线程。
四、自定义函数
1、MyAbort
(1)描述
使程序异常终止。
(2)定义
void MyAbort(void)
{sigset_t NewMask;struct sigaction OldAct;/*调用者不可以忽略信号 SIGABRT ,如果是话,重置为默认行为,默认行为是终止(abort)进程。。*/if (SigAction(SIGABRT,NULL,&OldAct) != SUCCESS_FLAG){goto ERR_PHASE;}if (OldAct.sa_handler == SIG_IGN){OldAct.sa_handler = SIG_DFL;if (SigAction(SIGABRT,&OldAct,NULL) != SUCCESS_FLAG){goto ERR_PHASE;}}/*默认信号行为的情况下,将所有标准输出缓冲区进行刷新。*/if (OldAct.sa_handler == SIG_DFL){fflush(NULL);}/*调用者不可以屏蔽信号 SIGABRT ,确保此信号是不屏蔽的。*/if (SigSetFill(&NewMask) != SUCCESS_FLAG){goto ERR_PHASE;}if (SigSetDel(&NewMask,SIGABRT) != SUCCESS_FLAG){goto ERR_PHASE;}if (SIG_PROC_MASK_SET(&NewMask,NULL) != SUCCESS_FLAG){goto ERR_PHASE;}/*发送信号 SIGABRT*/if (SigSend(getpid(),SIGABRT) != SUCCESS_FLAG){goto ERR_PHASE;}/*信号 SIGABRT 默认行为是终止(abort)进程,从信号处理程序返回到此,说明SIGABRT的信号处理程序是开发者自定义的。*//*进程可能产生了更多的输出,所以再次刷新*/fflush(NULL);/*处理动作置为默认,确保进程退出。*/OldAct.sa_handler = SIG_DFL;if (SigAction(SIGABRT,&OldAct,NULL) != SUCCESS_FLAG){goto ERR_PHASE;}/*除信号 SIGABRT 外,全部屏蔽。*/if (SIG_PROC_MASK_SET(&NewMask,NULL) != SUCCESS_FLAG){goto ERR_PHASE;}/*发送信号 SIGABRT*/if (SigSend(getpid(),SIGABRT) != SUCCESS_FLAG){goto ERR_PHASE;}/*这一块代码应该不会被执行*/exit(FAIL_FLAG);
ERR_PHASE:LOG_FORMAT(Error,"Fail.\n");return;
}
(3)参数
无
(4)返回值
无
(5)其他
无
2、MySystem
(1)描述
执行一个操作系统命令。
(2)定义
Status MySystem(const char *Cmd)
{JUDGE_NULL_PTR(Cmd);pid_t Pid;Status MyStatus = SUCCESS_FLAG;struct sigaction Ignore;struct sigaction SaveIntr;struct sigaction SaveQuit;sigset_t ChildMask;sigset_t SaveMask;/*忽略信号: SIGINT SIGQUIT*/Ignore.sa_handler = SIG_IGN;Ignore.sa_flags = 0;/*在信号处理函数运行期间,不阻塞任何信号。*/if(SigSetEmpty(&(Ignore.sa_mask)) != SUCCESS_FLAG){MyStatus = FAIL_FLAG;goto JUDGE_STATUS_PHASE;}if (SigAction(SIGINT,&Ignore,&SaveIntr) != SUCCESS_FLAG){MyStatus = FAIL_FLAG;goto JUDGE_STATUS_PHASE;}if (SigAction(SIGQUIT,&Ignore,&SaveQuit) != SUCCESS_FLAG){MyStatus = FAIL_FLAG;goto JUDGE_STATUS_PHASE;}/*阻塞信号: SIGCHLD*/if(SigSetEmpty(&ChildMask) != SUCCESS_FLAG){MyStatus = FAIL_FLAG;goto JUDGE_STATUS_PHASE;}if (SigSetAdd(&ChildMask,SIGCHLD) != SUCCESS_FLAG){MyStatus = FAIL_FLAG;goto JUDGE_STATUS_PHASE;}if (SIG_PROC_MASK_ADD(&ChildMask,&SaveMask) != SUCCESS_FLAG){MyStatus = FAIL_FLAG;goto JUDGE_STATUS_PHASE;}/*派生子进程*/Pid = fork();if (Pid < 0){MyStatus = FAIL_FLAG;goto END_PHASE;}else if(Pid == 0)/*子进程*/{/*恢复之前的信号动作和信号屏蔽字。*/if (SigAction(SIGINT,&SaveIntr,NULL) != SUCCESS_FLAG){MyStatus = FAIL_FLAG;goto END_PHASE;}if (SigAction(SIGQUIT,&SaveQuit,NULL) != SUCCESS_FLAG){MyStatus = FAIL_FLAG;goto END_PHASE;}if (SIG_PROC_MASK_SET(&SaveMask,NULL) != SUCCESS_FLAG){MyStatus = FAIL_FLAG;goto END_PHASE;}execl("/bin/sh","sh","-c",Cmd,(char *)0);/*执行错误*/_exit(FAIL_FLAG);}else /*父进程*/{while (waitpid(Pid,&MyStatus,0) < 0){/*信号打断以外的错误*/if (errno != EINTR){MyStatus = FAIL_FLAG;break;}}}END_PHASE:/*恢复之前的信号动作和信号屏蔽字。*/if (SigAction(SIGINT,&SaveIntr,NULL) != SUCCESS_FLAG){MyStatus = FAIL_FLAG;goto JUDGE_STATUS_PHASE;}if (SigAction(SIGQUIT,&SaveQuit,NULL) != SUCCESS_FLAG){MyStatus = FAIL_FLAG;goto JUDGE_STATUS_PHASE;}if (SIG_PROC_MASK_SET(&SaveMask,NULL) != SUCCESS_FLAG){MyStatus = FAIL_FLAG;goto JUDGE_STATUS_PHASE;}JUDGE_STATUS_PHASE:switch (MyStatus){case SUCCESS_FLAG:LOG_FORMAT(Debug,"OK, Cmd : '%s'.\n",Cmd);break;case FAIL_FLAG:LOG_FORMAT(Error,"Fail, Cmd : '%s'.\n",Cmd);break; default:break;}return MyStatus;
}
(3)参数
参数名 | 描述 |
Cmd | 操作系统命令。 |
(4)返回值
SUCCESS_FLAG | 成功 |
FAIL_FLAG | 失败 |
(5)其他
在命令执行期间,SIGCHLD信号阻塞,SIGINT和SIGQUIT将被忽略。
五、信号函数
1、pthread_sigmask
(1)描述
线程设置或检测信号屏蔽字。
(2)声明
int pthread_sigmask(int __how, const sigset_t *__restrict__ __newmask, sigset_t *__restrict__ __oldmask)
(3)参数
参数 | 描述 |
__how | __newmask行为。 |
__newmask | 信号屏蔽字。 |
__oldmask | 原始信号屏蔽字。 |
(4)返回值
参数 | 描述 |
0 | 成功 |
其他 | 错误编码 |
(5)其他
__how支持如下参数宏:
参数宏 | 描述 |
SIG_BLOCK | 线程添加信号屏蔽字。 |
SIG_UNBLOCK | 线程删除信号屏蔽字。 |
SIG_SETMASK | 线程设置信号屏蔽字。 |
2、sigwait
(1)描述
等待一个信号或多个信号的出现。
(2)声明
int sigwait(const sigset_t *__restrict__ __set, int *__restrict__ __sig)
(3)参数
参数 | 描述 |
__set | 等待的信号集。 |
__sig | 实际接收到的信号。 |
(4)返回值
参数 | 描述 |
0 | 成功 |
其他 | 错误编码 |
(5)其他
如果信号集中某个信号在sigwait调用的时候处于挂起状态,那么sigwait将无阻塞的返回。在返回之前,sigwait会从进程中移除那些处理挂起等待的信号。如果具体实现支持排队信号,并且多个信号被挂起,那么sigwait将会移除该信号的其中一个,其他继续排队。
为了避免错误行为发生,线程在调用sigwait之前,必须阻塞那些它需要等待的信号。
sigwait会原子的取消信号集的状态,知道有新的信号被递送。在返回之前,sigwait将恢复线程的信号屏蔽字。如果信号在sigwait被调用的时候没有被阻塞,那么在线程完成对sigwait的调用之前会出现一个时间窗口期,在这个时间窗口中,信号就可以被发生给线程。
使用sigwait的好处在于它可以简化处理信号,允许把异步产生的信号用同步方式处理。为了防止信号中断线程,可以把信号加到每个线程的信号屏蔽字中。然后安排专用线程处理信号。这样信号线程可以进程函数调用,不需要担心在信号处理程序中调用哪些函数是安全的,因为这些函数调用来自支持的线程上下文,而非会中断线程正常执行的传统信号处理程序。
如果多个线程在sigwait的调用中因等待同一个信号而阻塞,那么在信号递送的时候,就只有一个线程可以从sigwait中返回。如果一个信号被捕获,而一个现在在用sigwait等待此信号,那么这是将由操作系统实现来觉得以何种方式递送信号。操作系统实现可以让sigwait返回,也可以激活信号处理程序,但这两种方式不会同时发生。
3、pthread_kill
(1)描述
发送信号给线程。
(2)声明
int pthread_kill(pthread_t __threadid, int __signo)
(3)参数
参数 | 描述 |
__threadid | 线程号 |
__signo | 发送的信号。 |
(4)返回值
参数 | 描述 |
0 | 成功 |
其他 | 错误编码 |
(5)其他
六、DEMO
1、system
(1)测试代码
#include "MySignal.h"Status main()
{LOG_LEVEL = Debug;MySystem("/bin/python /home/gbase/test.py");MyAbort();return SUCCESS_FLAG;
}
(3)运行效果
[gbase@czg2 Exec]$ ./TestSystem
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-SigSetEmpty : OK.
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-SigAction : OK.
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-SigAction : OK.
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-SigSetEmpty : OK.
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-SigSetAdd : OK, SigNo : 17.
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-SigProcMask : OK, How : 0
2024-12-24 15:23:18-P[10487]-T[10487]-[Debug]-SigAction : OK.
2024-12-24 15:23:18-P[10487]-T[10487]-[Debug]-SigAction : OK.
2024-12-24 15:23:18-P[10487]-T[10487]-[Debug]-SigProcMask : OK, How : 2
insert into xxx1 select * from xxx2 where substr(xxx3,1,3)='1';
insert into xxx1 select * from xxx2 where substr(xxx3,1,3)='1';
insert into xxx1 select * from xxx2 where substr(xxx3,1,3)='1';
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-SigAction : OK.
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-SigAction : OK.
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-SigProcMask : OK, How : 2
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-MySystem : OK, Cmd : '/bin/python /home/gbase/test.py'.
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-SigAction : OK.
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-SigSetFill : OK.
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-SigSetDel : OK, SigNo : 6.
2024-12-24 15:23:18-P[10486]-T[10486]-[Debug]-SigProcMask : OK, How : 2
已放弃(吐核)
[gbase@czg2 Exec]$ ll
总用量 488
-rw------- 1 gbase gbase 442368 12月 24 15:23 core.10486
-rwxr-xr-x 1 root root 15256 12月 24 15:23 TestSigPending
-rwxr-xr-x 1 root root 11080 12月 24 15:23 TestSigSuspend
-rwxr-xr-x 1 root root 15560 12月 24 15:23 TestSigSuspend2
-rwxr-xr-x 1 root root 10112 12月 24 15:23 TestSystem
生成core文件是正常的,这是信号SIGABRT的默认动作。
[gbase@czg2 Exec]$ gdb TestSystem core.10486
GNU gdb (GDB) Red Hat Enterprise Linux 7.6.1-120.el7
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/PublicFunction/MySignal/Exec/TestSystem...done.
[New LWP 10486]
Core was generated by `./TestSystem'.
Program terminated with signal 6, Aborted.
#0 0x00002b8a93e45657 in kill () from /lib64/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.17-326.el7_9.x86_64
(gdb) bt
#0 0x00002b8a93e45657 in kill () from /lib64/libc.so.6
#1 0x00002b8a93c0a583 in SigSend (Pid=10486, Signal=6)at /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/PublicFunction/MySignal/Src/MySignal.c:193
#2 0x00002b8a93c0c6bd in MyAbort ()at /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/PublicFunction/MySignal/Src/MySignal.c:660
#3 0x000000000040081a in main ()at /opt/Developer/ComputerLanguageStudy/C/DataStructureTestSrc/PublicFunction/MySignal/TestSrc/TestSystem.c:9
(gdb) quit
2、sigwait
(1)测试代码
启动一个专用线程处理信号,主进程等待,当出现指定信号时,进行信号处理,而不用走之前的思路使用信号处理程序。
#include "MySignal.h"
#include "MyThread.h"static int QuitFlag;
static sigset_t SigMask;
static OneThrdMutexSt Lock;
static OneThrdCondSt Cond;static void* SigHandleThrd(void *Arg)
{if (Arg == NULL){/* 没什么用,防止编译错误。 */}int SigNo;while (1){if (SigWait(&SigMask,&SigNo) != SUCCESS_FLAG){THRD_EXIT(FAIL_FLAG);}switch (SigNo){case SIGINT:LOG_FORMAT(Debug,"OK, SigNo : %s.\n",strsignal(SigNo));break;case SIGQUIT:THRD_MUTEX_LOCK_F(&Lock);QuitFlag = 1;THRD_MUTEX_UNLOCK_F(&Lock);THRD_COND_BROADCAST_F(&Cond);LOG_FORMAT(Debug,"OK, SigNo : %s.\n",strsignal(SigNo));THRD_EXIT(SUCCESS_FLAG);default:LOG_FORMAT(Error,"Fail, SigNo : %s.\n",strsignal(SigNo));THRD_EXIT(EXCEPTION_EXIT_FLAG);}}
}Status main()
{LOG_LEVEL = Debug;sigset_t OldSigMask;OneThrdSt *Thrd = NULL;/*初始化互斥锁和条件变量*/if (ThrdMutexCreate(&Lock,PTHREAD_PROCESS_PRIVATE,PTHREAD_MUTEX_ERRORCHECK,PTHREAD_MUTEX_STALLED,0,0) != SUCCESS_FLAG){goto END_PHASE;}if (ThrdCondCreate(&Cond,PTHREAD_PROCESS_PRIVATE,0,0,CLOCK_REALTIME) != SUCCESS_FLAG){goto END_PHASE;}/*清空信号屏蔽字变量*/if (SigSetEmpty(&SigMask) != SUCCESS_FLAG){goto END_PHASE;}/*添加信号屏蔽字*/if (SigSetAdd(&SigMask,SIGINT) != SUCCESS_FLAG){goto END_PHASE;}if (SigSetAdd(&SigMask,SIGQUIT) != SUCCESS_FLAG){goto END_PHASE;}/*设置线程屏蔽字,所有线程共享,所以只用设置一次。*/if (SIG_THRD_MASK_ADD(&SigMask,&OldSigMask) != SUCCESS_FLAG){goto END_PHASE;} /*打印当前信号屏蔽字*/CurSigMaskPrint(Debug);/*创建子线程*/if(OneThrdCreate(&Thrd, PTHREAD_CREATE_JOINABLE,PTHREAD_STACK_MIN, 0,SigHandleThrd, NULL) != SUCCESS_FLAG){goto END_PHASE;}/*等待信号处理线程修改 QuitFlag*/THRD_MUTEX_LOCK_F(&Lock);while (QuitFlag == 0){THRD_COND_WAIT_F(&Cond,&Lock);} THRD_MUTEX_UNLOCK_F(&Lock);/*SIGQUIT 信号被捕获,并且被阻塞,这里可以做些什么,在实际应用中。*/QuitFlag = 0;/*打印当前信号屏蔽字*/CurSigMaskPrint(Debug);/*恢复原有信号屏蔽字*/if (SIG_PROC_MASK_SET(&OldSigMask,NULL) != SUCCESS_FLAG){goto END_PHASE;}/*打印当前信号屏蔽字*/CurSigMaskPrint(Debug);END_PHASE:ThrdMutexFree(&Lock);ThrdCondFree(&Cond);OneThrdFree(&Thrd);return SUCCESS_FLAG;
}
(3)运行效果
[gbase@czg2 Exec]$ ./TestSigThrdWait
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-ThrdMutexAttrInit : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-MutexAttrSetShrd : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-MutexAttrSetType : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-MutexAttrSetRobust : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-ThrdMutexInit : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-MutexAttrGetShrd : OK, SharedVal : PTHREAD_PROCESS_PRIVATE.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-MutexAttrGetType : OK, Type : PTHREAD_MUTEX_ERRORCHECK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-MutexAttrGetRobust : OK, Robust : PTHREAD_MUTEX_STALLED.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-ThrdMutexAttrDstry : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-ThrdMutexCreate : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-ThrdCondAttrInit : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-ThrdCondAttrSetShrd: OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-CondAttrSetClock : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-ThrdCondInit : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-ThrdCondAttrGetShrd: OK, SharedVal : PTHREAD_PROCESS_PRIVATE.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-CondAttrGetClock : OK, ClockId : CLOCK_REALTIME.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-ThrdCondAttrDstry : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-OneThrdCondCreate : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-SigSetEmpty : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-SigSetAdd : OK, Signal : Interrupt.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-SigSetAdd : OK, Signal : Quit.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-SigThrdMask : OK, How : 0
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-SigProcMask : OK, How : 0
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-SigPrint :
[ SIGINT,SIGQUIT ]
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-ThrdAttrInit : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-SetDetachState : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-SetStackSize : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-SetGuardSize : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-ThrdCreate : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-GetDetachState : OK, DetachState : PTHREAD_CREATE_JOINABLE.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-GetStackSize : OK, StackSize : 16384.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-GetGuardSize : OK, GuardSize : 0.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-ThrdAttrDestroy : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-OneThrdCreate : OK.
2024-12-30 13:52:20-P[26181]-T[26181]-[Debug]-ThrdMutexLock : OK.
我们在sigwait之前先屏蔽信号SIGINT,SIGQUIT。
[root@czg2 ~]# kill -SIGINT `pidof TestSigThrdWait`
2024-12-30 13:57:07-P[26181]-T[26182]-[Debug]-SigWait : OK, SigNo : Interrupt
2024-12-30 13:57:07-P[26181]-T[26182]-[Debug]-SigHandleThrd : OK, SigNo : Interrupt.
发送信号SIGINT,主线程26181是阻塞了这个信号,所以不会进行处理,子线程26182打印信息,然后继续等待。
[root@czg2 ~]# kill -SIGQUIT `pidof TestSigThrdWait`
2024-12-30 14:05:37-P[26181]-T[26182]-[Debug]-SigWait : OK, SigNo : Quit
2024-12-30 14:05:37-P[26181]-T[26182]-[Debug]-ThrdMutexLock : OK.
2024-12-30 14:05:37-P[26181]-T[26182]-[Debug]-ThrdMutexUnLock : OK.
2024-12-30 14:05:37-P[26181]-T[26182]-[Debug]-ThrdCondBroadcast : OK.
2024-12-30 14:05:37-P[26181]-T[26182]-[Debug]-SigHandleThrd : OK, SigNo : Quit.
2024-12-30 14:05:37-P[26181]-T[26181]-[Debug]-ThrdCondWait : OK.
2024-12-30 14:05:37-P[26181]-T[26181]-[Debug]-ThrdMutexUnLock : OK.
2024-12-30 14:05:37-P[26181]-T[26181]-[Debug]-SigProcMask : OK, How : 0
2024-12-30 14:05:37-P[26181]-T[26181]-[Debug]-SigPrint :
[ SIGINT,SIGQUIT ]
2024-12-30 14:05:37-P[26181]-T[26181]-[Debug]-SigProcMask : OK, How : 2
2024-12-30 14:05:37-P[26181]-T[26181]-[Debug]-SigProcMask : OK, How : 0
2024-12-30 14:05:37-P[26181]-T[26181]-[Debug]-SigPrint :
[ ]
2024-12-30 14:05:37-P[26181]-T[26181]-[Debug]-ThrdMutexDestroy : OK.
2024-12-30 14:05:37-P[26181]-T[26181]-[Debug]-ThrdMutexFree : OK.
2024-12-30 14:05:37-P[26181]-T[26181]-[Debug]-ThrdCondDstry : OK.
2024-12-30 14:05:37-P[26181]-T[26181]-[Debug]-ThrdCondFree : OK.
2024-12-30 14:05:37-P[26181]-T[26181]-[Debug]-OneThrdFree : OK.
发送信号SIGQUIT,主线程26181是阻塞了这个信号,所以不会进行处理。子线程26182获取互持锁修改全局推出标记,唤醒主线程,打印信息。主线程被唤醒后,将信号屏蔽字还原,释放内存。
3、sigwait2
(1)测试代码
和上面的sigwait DEMO差不太多,只是不用全局退出标记来决定主线程是否退出,使用pthread_join(THRD_WAIT)等一个线程结束,并释放线程占用的资源。运行效果就不贴出来。
#include "MySignal.h"
#include "MyThread.h"// static int QuitFlag;
static sigset_t SigMask;
// static OneThrdMutexSt Lock;
// static OneThrdCondSt Cond;static void* SigHandleThrd(void *Arg)
{if (Arg == NULL){/* 没什么用,防止编译错误。 */}int SigNo;while (1){if (SigWait(&SigMask,&SigNo) != SUCCESS_FLAG){THRD_EXIT(FAIL_FLAG);}switch (SigNo){case SIGINT:LOG_FORMAT(Debug,"OK, SigNo : %s.\n",strsignal(SigNo));break;case SIGQUIT:// THRD_MUTEX_LOCK_F(&Lock);// QuitFlag = 1;// THRD_MUTEX_UNLOCK_F(&Lock);// THRD_COND_BROADCAST_F(&Cond);LOG_FORMAT(Debug,"OK, SigNo : %s.\n",strsignal(SigNo));THRD_EXIT(SUCCESS_FLAG);default:LOG_FORMAT(Error,"Fail, SigNo : %s.\n",strsignal(SigNo));THRD_EXIT(EXCEPTION_EXIT_FLAG);}}
}Status main()
{LOG_LEVEL = Debug;sigset_t OldSigMask;OneThrdSt *Thrd = NULL;void *ThrdExitState = NULL;/*初始化互斥锁和条件变量*/// if (ThrdMutexCreate(&Lock,// PTHREAD_PROCESS_PRIVATE,// PTHREAD_MUTEX_ERRORCHECK,// PTHREAD_MUTEX_STALLED,// 0,// 0) != SUCCESS_FLAG)// {// goto END_PHASE;// }// if (ThrdCondCreate(&Cond,// PTHREAD_PROCESS_PRIVATE,// 0,// 0,// CLOCK_REALTIME) != SUCCESS_FLAG)// {// goto END_PHASE;// }/*清空信号屏蔽字变量*/if (SigSetEmpty(&SigMask) != SUCCESS_FLAG){goto END_PHASE;}/*添加信号屏蔽字*/if (SigSetAdd(&SigMask,SIGINT) != SUCCESS_FLAG){goto END_PHASE;}if (SigSetAdd(&SigMask,SIGQUIT) != SUCCESS_FLAG){goto END_PHASE;}/*设置线程屏蔽字,所有线程共享,所以只用设置一次。*/if (SIG_THRD_MASK_ADD(&SigMask,&OldSigMask) != SUCCESS_FLAG){goto END_PHASE;} /*打印当前信号屏蔽字*/CurSigMaskPrint(Debug);/*创建子线程*/if(OneThrdCreate(&Thrd, PTHREAD_CREATE_JOINABLE,PTHREAD_STACK_MIN, 0,SigHandleThrd, NULL) != SUCCESS_FLAG){goto END_PHASE;}/*等待线程*/THRD_WAIT(Thrd, ThrdExitState);LOG_FORMAT(Debug,"OK, ThrdExitState : %ld.\n",(long)ThrdExitState);/*等待信号处理线程修改 QuitFlag*/// THRD_MUTEX_LOCK_F(&Lock);// while (QuitFlag == 0)// {// THRD_COND_WAIT_F(&Cond,&Lock);// } // THRD_MUTEX_UNLOCK_F(&Lock);/*SIGQUIT 信号被捕获,并且被阻塞,这里可以做些什么,在实际应用中。*/// QuitFlag = 0;/*打印当前信号屏蔽字*/CurSigMaskPrint(Debug);/*恢复原有信号屏蔽字*/if (SIG_PROC_MASK_SET(&OldSigMask,NULL) != SUCCESS_FLAG){goto END_PHASE;}/*打印当前信号屏蔽字*/CurSigMaskPrint(Debug);END_PHASE:// ThrdMutexFree(&Lock);// ThrdCondFree(&Cond);OneThrdFree(&Thrd);return SUCCESS_FLAG;
}