要对一个信号进行处理,就需要给出此信号发生时系统所调用的处理函数。可以对一个特定的信号(除去SIGKILL和SIGSTOP信号)注册相应的处理函数。注册某个信号的处理函数后,当进程接收到此信号时,无论进程处于何种状态,就会停下当前的任务去执行此信号的处理函数。
1、注册信号函数。
#include<signal.h>
void(*signal(int signumber,void ((*func)(int))(int)
signumber表示信号处理函数对应的信号。func是一个函数指针。此函数有一整型参数,并返回void型。其实func还可以取其他定值如:SIG_IGN,SIG_DFL.
SIG_IGN表示:忽略signumber所指出的信号。SIG_DFL表示表示调用系统默认的处理函数。signal函数的返回值类型同参数func,是一个指向某个返回值为空并带有一个整型参数的函数指针。其正确返回值应为上次该信号的处理函数。错误返回SIG_ERR
signal示例如下:
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <signal.h>
void func(int sig)
{
printf("I get asignal!\n");
}
int main()
{ charbuffer[100];
if(signal(SIGINT, func) == SIG_ERR)
{
printf("signalerror exit now\n");
exit(0);
}
printf("pid:%ld\n",(long)getpid());
for(;;)
{
fgets(buffer,sizeof(buffer),stdin);
printf("bufferis:%s\n",buffer);
}
return 0;
}
通常情况下一个用户进程需要处理多个信号。可以在一个程序中注册多个信号处理函数。一个信号可以对应一个处理函数,同时多个信号可以对应一个处理函数。
对于SIGINT信号 我们可以用ctrl+c或ctrl+z来中断进程,来执行SIGINT注册的函数。
2、 高级信号处理。
在linux系统提供了一个功能更强的系统调用。
#include <signal.h>
int sigaction(int signumbet,const structsigaction *act,struct sigaction *oldact)
此函数除能注册信号函数外还提供了更加详细的信息,确切了解进程接收到信号,发生的具体细节。
struct sigaction的定义如下:在linux2.6.39/include/asm-generic/signal.h中实现
struct sigaction
{
void(*sa_handler)(int);
void(*sa_sigaction)(int,siginfo_t *,void *);
sigset_t sa_mask;
int sa_flags;
}
siginfo_t在linux2.6.39/include/asm-generic/siginfo.h中实现:
sa_flags的取值如下表,取0表示选用所有默认选项。
SA_NOCLDSTOP:用于表示信号SIGCHLD,当子进程被中断时,不产生此信号,当且仅当子进程结束时产生此信号。
SA_NOCLDWATI:当信号为SIGCHLD,时可避免子进程僵死。
SA_NODEFER:当信号处理函数正在进行时,不堵塞对于信号处理函数自身信号功能。
SA_RESETHAND:同SA_ONESHOT
其实sinaction完全可以替换signal函数
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <signal.h>
void func(int sig)
{
printf("I get a signal!\n");
}
int main()
{ char buffer[100];
struct sigaction act;
act.sa_handler=func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if(sigaction(SIGINT,&act, NULL) == -1)
{
printf("sigaction error exit now\n");
exit(0);
}
printf("pid:%ld\n",(long)getpid());
for(;;)
{
fgets(buffer,sizeof(buffer),stdin);
printf("buffer is:%s\n",buffer);
}
return 0;
1、注册信号函数。
#include<signal.h>
void(*signal(int signumber,void ((*func)(int))(int)
signumber表示信号处理函数对应的信号。func是一个函数指针。此函数有一整型参数,并返回void型。其实func还可以取其他定值如:SIG_IGN,SIG_DFL.
SIG_IGN表示:忽略signumber所指出的信号。SIG_DFL表示表示调用系统默认的处理函数。signal函数的返回值类型同参数func,是一个指向某个返回值为空并带有一个整型参数的函数指针。其正确返回值应为上次该信号的处理函数。错误返回SIG_ERR
signal示例如下:
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <signal.h>
void func(int sig)
{
printf("I get asignal!\n");
}
int main()
{ charbuffer[100];
if(signal(SIGINT, func) == SIG_ERR)
{
printf("signalerror exit now\n");
exit(0);
}
printf("pid:%ld\n",(long)getpid());
for(;;)
{
fgets(buffer,sizeof(buffer),stdin);
printf("bufferis:%s\n",buffer);
}
return 0;
}
通常情况下一个用户进程需要处理多个信号。可以在一个程序中注册多个信号处理函数。一个信号可以对应一个处理函数,同时多个信号可以对应一个处理函数。
对于SIGINT信号 我们可以用ctrl+c或ctrl+z来中断进程,来执行SIGINT注册的函数。
2、 高级信号处理。
在linux系统提供了一个功能更强的系统调用。
#include <signal.h>
int sigaction(int signumbet,const structsigaction *act,struct sigaction *oldact)
此函数除能注册信号函数外还提供了更加详细的信息,确切了解进程接收到信号,发生的具体细节。
struct sigaction的定义如下:在linux2.6.39/include/asm-generic/signal.h中实现
struct sigaction
{
void(*sa_handler)(int);
void(*sa_sigaction)(int,siginfo_t *,void *);
sigset_t sa_mask;
int sa_flags;
}
siginfo_t在linux2.6.39/include/asm-generic/siginfo.h中实现:
sa_flags的取值如下表,取0表示选用所有默认选项。
SA_NOCLDSTOP:用于表示信号SIGCHLD,当子进程被中断时,不产生此信号,当且仅当子进程结束时产生此信号。
SA_NOCLDWATI:当信号为SIGCHLD,时可避免子进程僵死。
SA_NODEFER:当信号处理函数正在进行时,不堵塞对于信号处理函数自身信号功能。
SA_NOMASK:同SA_NODEFER
SA_RESETHAND:同SA_ONESHOT
SA_RESTART:是本来不能重新于运行的系统调用自动重新运行。
其实sinaction完全可以替换signal函数
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <signal.h>
void func(int sig)
{
printf("I get a signal!\n");
}
int main()
{ char buffer[100];
struct sigaction act;
act.sa_handler=func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
if(sigaction(SIGINT,&act, NULL) == -1)
{
printf("sigaction error exit now\n");
exit(0);
}
printf("pid:%ld\n",(long)getpid());
for(;;)
{
fgets(buffer,sizeof(buffer),stdin);
printf("buffer is:%s\n",buffer);
}
return 0;
}
//程序异常时, 打印函数调用栈代码思路
/*===============================================================
* Copyright (C) 2014 All rights reserved.
*
* 文件名称:bt.c
* 创 建 者:sky
* 创建日期:2014 .05. 17
* 描 述:
*
* 更新日志:
*
================================================================*/
#include<unistd.h>
#include<stdio.h>
#include <signal.h>
#include <memory.h>
#define TestPrintf(fmt, args...) \
printf("FUNC:: %s, line:%d\n", __FUNCTION__, __LINE__);\
printf(fmt,##args);\
printf("\n")
char g_procname[100]={0};
char g_xthreadName[100]={0};
void getProcName(char * name, int length)
{
char filename[30]={0} ;
int pid=getpid();
memset(name, 0, length);
//read porcname
TestPrintf(filename, "/proc/%d/cmdline", pid);
FILE *fp = fopen(filename, "r");
if(fp == NULL)
{
TestPrintf("error return ...");
return ;
}
fread(name, length, 1,fp);
TestPrintf("name :: %s\n", name);
}
void getThreadName(char * name, int length)
{
int ppid=getppid();
//read porcname
char filename[20]={0};
TestPrintf(filename, "/proc/%d/stat", ppid);
FILE *fp = fopen(filename, "r");
if(fp == NULL)
{
TestPrintf("error return ...");
return ;
}
fread(name, length, 1,fp);
TestPrintf("threadname :: %s\n", name);
}
void parasregister(unsigned int * pc, unsigned int* bp, unsigned int* sp, void *ct)
{
return ;
}
void exception(int signum, siginfo_t *info, void *c)
{
TestPrintf("good");
unsigned int pc, bp, sp;
if(signal(signum, SIG_DFL) == SIG_ERR)
{
TestPrintf("error\n");
return ;
}
else
{
TestPrintf("pc..\n");
}
getProcName(g_procname, sizeof(g_procname));
getThreadName(g_xthreadName, sizeof(g_xthreadName));
//寄存器中保存程序当前pc sp bp
parasregister(&pc, &bp, &sp, c);
//可以解析elf文件符号表, 根据pc 指针定位当前函数
//根据具体平台函数调用规则, 打印函数调用顺序
TestPrintf("shit\n");
return ;
}
void backtraceinit()
{
struct sigaction act;
act.sa_flags = SA_ONESHOT | SA_SIGINFO;
act.sa_handler= exception;
sigemptyset(&act.sa_mask);
sigaction(SIGINT, &act, NULL);
sigaction(SIGSEGV, &act, NULL);
sigaction(SIGBUS, &act, NULL);
}
int main()
{
TestPrintf("cdcd\n");
backtraceinit();
while(1)
sleep(200);
}
转载于:https://blog.51cto.com/enjoyit/1412963