一:调用abort函数会异常的终止进程,并且,会刷新缓冲区,因为abort函数内部调用了fflush(NULL),刷新缓冲区不代表调用了fclose。
范例一:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
void abort1(void);
//信号处理函数
void sig_usr(int signo)
{
if(signo == SIGABRT)
{
printf("收到了SIGABRT信号!\n");
}
}
int main ()
{
FILE *fp;
/*系统函数,参数1:是个信号,参数2:是个函数指针,代表一个针对该信号的捕捉处理函数*/
if(signal(SIGABRT,sig_usr) == SIG_ERR)
{
printf("无法捕捉SIGUSR1信号!\n");
}
printf("准备打开 nofile.txt\n");
fp = fopen( "nofile.txt","r" );
if(fp == NULL)
{
printf("准备终止程序\n");
/*abort函数会产生SIGABRT信号(POSIX1.0标准)*/
abort();
}
printf("准备关闭 nofile.txt\n");
fclose(fp);
return(0);
}
//执行完信号处理函数以后,程序将终止。
如果,没有设置信号处理函数,那么进程将直接异常终止,系统对于SIGABRT的默认动作是忽略该动作。
二:来看看基于POSIX1.0当中abort函数的实现吧。
void abort(void)
{
sigset_t mask;
struct sigaction action;
sigaction(SIGABRT, NULL, &action);
printf("action.sa_handler = %p\n", action.sa_handler);
//action.sa_handler = SIG_IGN;
/*如果信号处理函数的动作是忽略*/
if(action.sa_handler == SIG_IGN)/*忽略信号的处理程序*/
{
action.sa_handler = SIG_DFL;/*默认信号处理程序*/
sigaction(SIGABRT, NULL, &action);
}
if(action.sa_handler == SIG_DFL)/*默认信号处理程序*/
{
fflush(NULL);/*刷新缓冲区*/
}
/*先填充所有信号*/
sigfillset(&mask);
/*在单独把SIGABRT信号删除,即,
除了该信号,其它的所有信号都是屏蔽的*/
sigdelset(&mask, SIGABRT);
sigprocmask(SIG_SETMASK, &mask, NULL);
/*发送一个信号到本进程,如果没有对该信号进行捕抓,
那么收到SIGABRT信号以后,进程将异常终止*/
kill(getpid(), SIGABRT);
/*如果设置了信号处理函数,那么函数流程将继续往下执行*/
/*刷新缓冲区*/
fflush(NULL);
/*默认信号处理程序*/
action.sa_handler = SIG_DFL;
sigaction(SIGABRT, NULL, &action);
/*按照mask提供的信号设置,重新设置系统信号设置*/
sigprocmask(SIG_SETMASK, &mask, NULL);
/*由于把信号处理改为了默认方式,即忽略
那,再次收到该信号时,程序就会异常终止*/
kill(getpid(), SIGABRT);
/*程序执行流程应该不会走到这里*/
exit(1);
}
/*函数定义:int fflush(FILE *stream);
函数说明:调用fflush()会将缓冲区中的
内容写到stream所指的文件中去.若stream为NULL,
则会将所有打开的文件进行数据更新.*/