VxWorks实时操作系统SIGNAL机制的应用

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
if(code==BUS_PAGE_FAULT)
printf(" PAGE_FAULT\n");
exit(0);
}
}
输出结果为:
SIGUSR ERROR
PAGE_FAULT
实例4:第二方案多参数处理程序
[摘要]介绍VXWORKS实时操作系统的信号机制以及各种处理方法,特别是利用该机制实现异常情况的恢复和处理。
1.
信号可用来在同一任务内部或不同任务之间实现异步通信,从而改变对多个任务的控制流程。所有任务或中断服务程序均能向指定的任务发送信号,该信号的接收任务将立刻挂起当前的执行线程,而激活任务指定的信号处理程序。信号处理程序是由用户定义的,它关联与特定的信号,而且任务接收到该指定信号时的所有必要处理都在该程序中实现。信号的这种机制使得它特别适合于用来实现差错和异常处理。
SIG_BLOCK
结果信号集为当前信号集和指定信号集二者的并集,通过这种方式,可向当前信号集增添指定的元素;
SIG_UNBLOCK
结果信号集为指定信号集的补集和当前信号集二者的交集;通过这种方式,可从当前信号集删除指定的元素;
SIG_SETMASK
结果信号集为指定信号集;
3.
int raise (int signo )
{
if(sig==SIGUSR1)
printf("SIGUSR");
else
{
printf("ERROR\n");
exit(0);
}
}
输出结果为:
SIGUSRERROR
实例2:信号屏蔽
#include <stdio.h>
#include <stdlib.h>
#include <sigLib.h>
#include <sigCodes.h>
#include <signal.h>
void sigHandler(int sig);
void myMain()
{
int A[10];
sigset_t sigset1,sigset2;
sigemptyset(&sigset1);
sigaddset(&sigset1,SIGUSR1);
sigprocmask(SIG_SETMASK,&sigset1,&sigset2);
intsi_signo; /*信号的编号信息*/
intsi_code;/*信号的来源信息*/
union sigvalsi_value; /*信号的代码信息*/
} siginfo_t;
union sigval {
intsival_int;/*信号的代码*/
void*sival_ptr;
};
struct sigaction
{
int A[10];
signal(SIGILL,&myHandler);
signal(SIGBUS,&myHandler);
signal(SIGUSR1,&myHandler);
raise(SIGUSR1);
A[11]=1; /*人为设置的下标越界差错*/
}
void myHandler(int sig)
该函数建立信号signo与pAct结构中指定的处理函数之间的联系;同时,当前信号处理函数的有关信息将保存在结构pOact中;
另外,为了调用多参数处理程序,pAct结构中的成员sa_flags必须设置SA_SIGINFO;
voidsigHandler(int signo);
单参数信号处理程序,这里sigHandler为用户自己定义的函数名(下同),该函数只提供了不同的信号编号signo,进一步的信号代码信息无法获取。
SIGILL
ILL_INVALID_TSS
Invalid task state segment
SIGBUS
BUS_NO_SEGMENT
Segment not present
SIGBUS
BUS_STACK_FAULT
Stack exception
SIGILL
ILL_PROTECTION_FAULT
General protection
Debugger call
SIGILL
ILL_NON_MASKABLE
NMI interrupt
SIGEMT
EMT_BREAKPOINT
Breakpoint
SIGILL
ILL_OVERFLOW
INTO-detected overflow
SIGILL
ILL_BOUND
Bound range exceeded
SIGBUS
BUS_PAGE_FAULT
Page fault
SIGILL
ILL_RESERVED
(intel reserved)
SIGFPE
FPE_CP_ERROR
Coprocessor Error
SIGBUS
BUS_ALIGNMENT
Alignment check
对应于Signal的列也就是前面函数中的signo或第二方案中结构pInfo的成员si_signo,对应于Code的列也就是第一方案中的code和第二方案中结构pInfo的成员si_value.sival_int。具体实现参见后面的例子程序。
int setjmp ( jmp_buf env )
该函数用于保存任务的运行环境;正常情况下,其返回值为0,出现异常时,其返回值为非0,具体值由函数longjmp的第二个参数确定。
另外,保存的运行环境不包括公共变量。
void longjmp ( jmp_buf env, int val )
该函数恢复由保存的setjmp运行环境,并将控制转交给setjmp。
该函数初始化信号集,使得该信号集不包含任何信号;
int sigfillset (sigset_t *pSet )
该函数初始化信号集,使得该信号集包含所有信号;
int sigaddset ( sigset_t *pSet , int signo )
该函数向信号集中增加新的信号;
int sigdelset ( sigset_t *pSet , int signo )
voidsigHandler(int signo, siginfo_t * pInfo, void * pContext);
多参数信号处理程序,该函数只提供了不同的信号编号signo和信号代码code信息,可对信号接收所更加详细的处理。
这里有必要介绍一下几个数据结构:
typedef struct siginfo {
voidsigHandler(int signo);
单参数信号处理程序,这里sigHandler为用户自己定义的函数名(下同),该函数只提供了不同的信号编号signo,进一步的信号代码信息无法获取。
voidsigHandler(int signo, int code, struct sigcontext * pContext);
由于信号处理函数由操作系统调用,所以其函数形式有着严格的要求,包括下面的两种形式:
第一方案:利用signal函数实现信号与处理函数的关联
void* signal( int signo, void* pHandler () )()
该函数建立信号signo与处理函数pHandler之间的联系;同时,其返回当前信号处理函数的指针;
SIGILL
ILL_INVALID_OPCODE
Invalid opcode
SIGFPE
FPE_NO_DEVICE
Device not available
SIGILL
ILL_DOUBLE_FAULT
Double fault
SIGFPE
FPE_CP_OVERRUN
Coprocessor segment overrun
sigset_tsa_mask;/*信号屏蔽集*/
intsa_flags;/*处理方式*/
};
下面以Intel i386/i486为例进行进一步的解释:
列出信号定义如下:
Signal
Code
Exception
SIGILL
ILL_DIVIDE_ERROR
Divide error
SIGEMT
EMT_DEBUG
另外,VXWORKS操作系统定义了两个用户自定义信号,其对应的Signal列项为SIGUSR1和SIGUSR2,没有对应的Code列项。
5.
当任务在执行过程中出现硬件异常时,将自动的发送相应的信号,用户可以利用这种机制来实现异常处理。利用setjmp和longjmp的相互配合可实现对异常情况的处理。为了利用这两个函数必须包含头文件“setjmp.h”,同时定义类型为jmp_buf公共变量。
{
union{
void(*__sa_handler)(int);
void(*__sa_sigaction)(int, siginfo_t *, void *);
}sa_u;
#define sa_handlersa_u.__sa_handler /*单参数处理程序*/
#define sa_sigactionsa_u.__sa_sigaction /*多参数处理程序*/
void sigHandler(int sigNum,int code, struct sigcontext *pContext);
void myMain()
{
int A[10];
signal(SIGILL,&sigHandler);
signal(SIGBUS,&sigHandler);
signal(SIGUSR1,&sigHandler);
raise(SIGUSR1);
A[11]=10;
}
void sigHandler(int sigNum,int code, struct sigcontext *pContext)
{
if(sigNum==SIGUSR1)
printf("SIGUSR");
else
{
printf(" ERROR\n");
任务调用该函数来向自己发送指定的信号;
int kill (int tid, int signo )
该函数可向任何任务发送指定的信号;
4.
如果一个任务指定了对于某个信号的处理程序,不管该任务是否被挂起时,接收到该信号将立刻调用信号处理程序,信号处理程序执行完毕后,任务恢复到先前的状态,比如:任务在挂起状态接收到该信号,那么处理程序执行完毕后任务将返回到挂起状态。
该机制的具体运用见后面的实例程序。
6.
实例1:单参数信号处理程序以及信号的发送
#include <stdio.h>
#include <stdlib.h>
#include <sigLib.h>
#include <sigCodes.h>
void sigHandler(int sig);
void myMain()
多参数信号处理程序,该函数只提供了不同的信号编号signo和信号代码code信息,可对信号接收所更加详细的处理。
第二方案:利用sigaction函数实现信号与处理函数的关联
int sigaction ( int signo, const struct sigaction *pAct, struct sigaction *pOact );
2.
在信号处理时,可通过信号屏蔽来选择需要进行处理的信号,接收到被屏蔽的信号,即使指定了相应的处理程序,也不作任何处理。
为了实现对信号的屏蔽,需要定义数据类型为sigset_t的变量,同时必须包含头文件“signal.h”。
下面介绍实现这一功能的函数:
int sigemptyset (sigset_t *pSet )
signal(SIGILL,&sigHandler);
signal(SIGBUS,&sigHandler);
signal(SIGUSR1,&sigHandler);
raise(SIGUSR1);
A[11]=10;
}
void sigHandler(int sig)
{
if(sig==SIFra Baidu bibliotekUSR1)
printf("SIGUSR");
该函数删除信号集中的信号;
int sigismember ( sigset_t *pSet , int signo )
该函数用来判断信号集是否包含某信号;
int sigprocmask ( int how, const sigset_t *pSet, sigset_t *pOset )
该函数用来设置信号屏蔽;这里,pSet为新的信号集,pOset为当前的信号集,而how则指示处理方式,其取值与处理方式对应关系如下:
else
{
printf(" ERROR\n");
exit(0);
}
}
输出结果:
ERROR
实例3:第一方案多参数处理程序
#include <stdio.h>
#include <stdlib.h>
#include <sigLib.h>
#include <sigCodes.h>
#include <signal.h>
相关文档
最新文档