alarm函数
设置定时器(闹钟)。在指定seconds后,内核会给当前进程发送 14 SIGALRM信号。进程收到该信号,默认动作终止
#include
unsigned int alarm(unsigned int seconds);
返回值:
上次定时剩余时间
无错误现象
定时,与进程状态无关(自然定时法)!就绪,运行,终止,挂起(阻塞,暂停),僵尸…无论进程处于何种状态,alarm都会计时。
eg: 编写程序测试你使用的计算机1秒能数对多少个数。
#include
#include
#include
#include
#include
int main()
{
int i=0;
alarm(1);
while(1)
printf("%d\n",i++);
return 0;
}
time命令可以查看程序执行的时间
实际执行时间=系统时间+用户时间+等待时间
setitimer函数
setitimer函数为设置定时器(闹钟),可替代alarm函数,比alarm函数精确度更高,精度为微秒,可以实现周期定时。
函数头文件为 #include
函数原型为 int setitimer(int which,const struct itimerval *new_value,struct itimerval *old_value);
返回值
成功返回 0
失败返回 -1 error
参数
which:指定定时方式
1.自然定时:ITIMER_REAL 计算自然时间
2.虚拟空间记时(用户空间):ITIMER_VIRTUAL 只计算进程占cpu的时间
3.运行时记时(用户+内核):ITIMER_PROF 计算占用cpu及系统调用的时间
old_value:上次定时剩余时间
new_value:新计时时间
struct itimerval 结构体
struct itimerval {
struct timeval it_interval; /* Interval for periodic timer */
struct timeval it_value; /* Time until next expiration */
};
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
eg : 编写程序测试你使用的计算机1秒能数对多少个数
#include
#include
int main()
{
int i=0;
struct itimerval new_t;
struct itimerval old_t;
new_t.it_interval.tv_sec=0;//周期定时 //秒
new_t.it_interval.tv_usec=0; //微妙
new_t.it_value.tv_sec=1;//定时时长 //秒
new_t.it_value.tv_usec=0; //微妙
if(setitimer(ITIMER_REAL,&new_t,&old_t)==-1)
{
perror("setitimer error");
return -1;
}
while(1)
printf("%d\n",++i);
return 0;
}
信号集操作函数
自定义信号集操作函数
#include
int sigemptyset(sigset_t *set); //清空信号集,全置为零
int sigfillset(sigset_t *set); //填满信号集 ,全置为一
int sigaddset(sigset_t *set, int signum); //将一个信号添加到信号集中
int sigdelset(sigset_t *set, int signum);//将一个信号从信号集中移除
int sigismember(const sigset_t *set, int signum);
//判断一个信号是否在信号集合中(在返回1,不在返回0)
设置信号屏蔽字和解除屏蔽
int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);
参数:
how
SIG_BLOCK
设置阻塞SIG_UNBLOCK
取消阻塞SIG_SETMASK
用自定义set替换mask
set
自定义set
oldset
旧有的mask
查看未决信号集
int sigpending(sigset_t *set);
set :传出的未决信号集
eg: 练习阻塞SIGNIT信号并查看
#include
#include
void print(sigset_t set)
{
int i=0;
for(i=0;i<32;i++)
{
if(sigismember(&set,i))
putchar('1');
else
putchar('0');
}
printf("\n");
}
int main()
{
sigset_t set;
sigset_t oldset;
sigset_t pedset;
sigemptyset(&set);
sigaddset(&set,SIGINT);
sigprocmask(SIG_BLOCK,&set,&oldset);
sigpending(&pedset);
print(pedset);
while(1);
return 0;
}
信号捕捉
signal函数
注册一个信号捕捉函数
#include
typedef void (*sighandler_t)(int); //函数指针
sighandler_t signal(int signum, sighandler_t handler);
eg:
#include
#include
void sig_catch(int signo)
{
printf("catch you ! %d\n",signo);
}
int main()
{
signal(SIGINT,sig_catch);
while(1);
return 0;
}
sigaction函数
修改信号处理动作(通常在Linux用其注册一个信号的捕捉函数)
#include
int sigaction(int signum, const struct sigaction *act,struct sigaction *oldact);
参数:
act : 传入参数,新的处理方式
old: 传出参数,旧的处理方式
struct sigaction
{
void (*sa_handler)(int); //捕捉到信号后要干的事情
void (*sa_sigaction)(int, siginfo_t *, void *);
sigset_t sa_mask; //只作用于信号捕捉期间
int sa_flags;
void (*sa_restorer)(void);
};
eg:捕捉信号SIGINT
#include
#include
#include
void sig_catch(int signo)
{
printf("catch you ! %d\n",signo);
}
int main()
{
struct sigaction act,oldact;
act.sa_handler = sig_catch;//set callback function name
sigemptyset(&act.sa_mask);//清零set mask when sig_catch working
act.sa_flags=0; //usually use
int ret=sigaction(SIGINT,&act,&oldact);
if(ret==-1)
{
perror("error");
exit(1);
}
while(1);
return 0;
}
信号捕捉特性
- 1)进程正常运行时,默认PCB中有一个信号屏蔽字,假定为☆,它决定了进程自动屏蔽哪些信号。当注册了某个信号捕捉函数,捕捉到该信号以后,要调用该函数。而该函数有可能执行很长时间,在这期间所屏蔽的信号不由☆来指定。而是用sa_mask来指定。调用完信号处理函数,再恢复为☆。
- 2)XXX信号捕捉函数执行期间,XXX信号自动被屏蔽。
- 3)阻塞的常规信号不支持排队,产生多次只记录一次。(后32个实时信号支持排队)
测试:
#include
#include
#include
#include
void sig_catch(int signo)
{
printf("catch you ! %d\n",signo);
sleep(3);
}
int main()
{
struct sigaction act,oldact;
act.sa_handler = sig_catch;//set callback function name
sigemptyset(&act.sa_mask);//清零set mask when sig_catch working
act.sa_flags=0; //usually use
int ret=sigaction(SIGINT,&act,&oldact);
if(ret==-1)
{
perror("error");
exit(1);
}
while(1);
return 0;
}