十六、Linux系统编程-信号(三)其他信号发送函数、可重入及不可重入函数

时间:2021-01-15 14:45:36
一、更多信号发送函数 (1)、alarm 发送时钟信号 函数声明:
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
函数参数: 秒数 返回值: 由于调度剩余的秒数
示例:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <signal.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
}while(0)
void handle(int sig);
int main(int argc,char* argv[])
{
if ( signal(SIGALRM,handle) == SIG_ERR)
ERR_EXIT("signal error");
alarm(2);
for(;;)
pause();
return 0;
}

void handle(int sig)
{
printf("recv a sig=%d\n",sig);
alarm(2);
}

(2)setitimer 发送SIGALRM,SIGPROF,SIGVTALRM 函数声明:
#include <sys/time.h>
int getitimer(int which, struct itimerval *curr_value);
int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);
函数参数: 返回值:成功返回0,失败返回-1并设置errno (3)、abort 发送SIGABRT信号 函数声明:
#include <stdlib.h>
void abort(void);
函数参数:返回值:成功返回0,失败返回-1并设置errno 二、可重入函数与不可重入函数         所谓可重入函数是指一个可以被多个任务调用的过程,任务在调用时不必担心数据是否会出错。因为进程在收到信号后,就将跳转到信号处理函数去接着执行。如果信号处理函数中使用了不可重入函数,那么信号处理函数可能会修改原来进程中不应该被修改的数据,这样进程从信号处理函数中返回接着执行时,可能会出现不可预料的后果。不可再入函数在信号处理函数中被视为不安全函数。        满足下列条件的函数多数是不可再入的:(1)使用静态的数据结构,如getlogin(),gmtime(),getgrgid(),getgrnam(),getpwuid()以及getpwnam()等等;(2)函数实现时,调用了malloc()或者free()函数;(3)实现时使用了标准I/O函数的        为了增强程序的稳定性,在信号处理函数中应使用可重入函数。且应该降低信号处理函数的规模。
三、不可重入函数示例 示例:
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <fcntl.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#define ERR_EXIT(m) \
do \
{ \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)


typedef struct
{
int a;
int b;
} TEST;

TEST g_data;

void handler(int sig);
int main(int argc, char *argv[])
{
TEST zeros = {0, 0};
TEST ones = {1, 1};
if (signal(SIGALRM, handler) == SIG_ERR)
ERR_EXIT("signal error");

g_data = zeros;
alarm(1);
for (;;)
{
g_data = zeros;
g_data = ones;
}
return 0;
}

void unsafe_fun()
{
printf("%d %d\n", g_data.a, g_data.b);
}

void handler(int sig)
{
unsafe_fun();
alarm(1);
}
在这个程序中,在g_data没有完全修改完成的时候有可能被信号打断,造成输入结果和预期不一致。