信号
同步
异步:什么时候到来不知道,产生什么结果不知道
处理:查询法、通知法
一、信号(初步异步、强烈异步)
1、信号的概念
信号是软件中断。
信号的响应依赖于中断。
2、signal();
void signal(int signum,void (*func)(int )))(int);
信号会打断阻塞的系统调用。如:open 和 read
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void int_handler(int s)
{
write(1,"!",1);
}
int main()
{
int i;
/*把打断信号忽略掉*/
//signal(SIGINT,SIG_IGN);
signal(SIGINT,int_handler);
for (i = 0; i < 10; i++)
{
write(1,"*",1);
sleep(1);
}
exit(0);
}
3、信号的不可靠
信号的行为不可靠,因为执行现场不可控。
4、可重入函数
所有的系统调用都是可重入的,一部分库函数也是可重入的,比如说:memcpy, localtime。函数有_r版本,原来的版本就不能用在信号处理中。
5、信号的响应过程
1)信号从收到到响应有一个不可避免的延迟。
思考:1、如何忽略掉一个信号的???
把指定信号的mask位置为0,阻止信号被响应。但是不能阻止信号到来。
2、标准信号为什么要丢失???
位图,来1W次还是置为1次1,不会累加,不会计数。
3、标准信号的响应没有严格的顺序。
每个进程都有这样的两个位图,当有一个信号发出的时候,pending会置1,然后mask&pending,从kernel态到user态有一个时延。
信号时从kernel到user的路上响应。
多线程再解释:mask置为0,是防止重入现象。
6、相关的常用函数
kill();
kill是用来给进程发出信号,
raise();
alarm();
里程碑式函数。有一个稍微准确点的时间。
setitimer();//精度控制更好,没有延迟累计的。
例:使用单一计时器构造一组函数,实现任意数量的计时器
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
int main()
{
/*无法实现多任务的计数器,会调用最后一个alarm*/
alarm(10);
alarm(5);
alarm(1);
while (1)
pause();
exit(0);
}
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
int main()
{
time_t end;
long long count = 0;
end = time(NULL) + 5;
while (time(NULL) <= end)
{
count++;
}
printf("%lld\n",count);
exit(0);
}
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <signal.h>
//易变符
static volatile int loop = 1;
static void alarm_handler(int s)
{
loop = 0;
}
int main()
{
long long count = 0;
//触发信号,需要放在alarm之前
signal(SIGALRM,alarm_handler);
alarm(5);
while (loop)
count++;
printf("%lld\n",count);
exit(0);
}
漏桶实现
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define BUFSIZE 1024
int main(int argc,char **argv)
{
int sfd,dfd = 1;
int ch,len,ret,pos = 0;
char buf[BUFSIZE];
if (argc < 2)
{
fprintf(stderr,"Usage : %s <source_filename> <dest_filename>\n",argv[0]);
exit(1);
}
do
{
sfd = open(argv[1],O_RDONLY);
if (sfd < 0)
{
if(errno != EINTR)
{
perror("open()");
exit(1);
}
}
} while (sfd < 0);
while (1)
{
/*len read 10 byte*/
len = read(sfd,buf,BUFSIZE);
if (len<0)
{
if (errno == EINTR)
continue;
perror("read()");
break;
}
if (len == 0)
{
break;
}
pos = 0;
/*判断len是否全部填入*/
while (len > 0)
{
/*from buf read len byte to dfd*/
ret = write(dfd,buf+pos,len);
if (ret < 0 )
{
if (errno == EINTR)
continue;
perror("write()");
exit(1);
}
/*计算下一个写入的位置*/
pos += ret;
/*计算剩下的没填入的字节数*/
len -= ret;
}
}
close(sfd);
exit(0);
}
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#define CPS 10
#define BUFSIZE CPS
static volatile int loop = 0;
static void alarm_handler(int s)
{
alarm(1);
loop = 1;
}
int main(int argc,char **argv)
{
int sfd,dfd = 1;
int ch,len,ret,pos = 0;
char buf[BUFSIZE];
if (argc < 2)
{
fprintf(stderr,"Usage : %s <source_filename> <dest_filename>\n",argv[0]);
exit(1);
}
signal(SIGALRM,alarm_handler);
alarm(1);
do
{
sfd = open(argv[1],O_RDONLY);
if (sfd < 0)
{
if(errno != EINTR)
{
perror("open()");
exit(1);
}
}
} while (sfd < 0);
while (1)
{
while(!loop)
;
loop = 0;
/*len read 10 byte*/
while(len = read(sfd,buf,BUFSIZE)<0)
{
if (errno == EINTR)
continue;
perror("read()");
break;
}
if (len == 0)
break;
pos = 0;
/*判断len是否全部填入*/
while (len > 0)
{
/*from buf read len byte to dfd*/
ret = write(dfd,buf+pos,len);
if (ret < 0 )
{
if (errno == EINTR)
continue;
perror("write()");
exit(1);
}
/*计算下一个写入的位置*/
pos += ret;
/*计算剩下的没填入的字节数*/
len -= ret;
}
}
close(sfd);
exit(0);
}
slowcat重构
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#define CPS 10
#define BUFSIZE CPS
#define BURST 100
/*保证赋值操作一定是一条机器指令完成的*/
static volatile sig_atomic_t token = 0;
static void alarm_handler(int s)
{
alarm(1);
token++;
if (token > 100)
{
token = BURST;
}
}
int main(int argc,char **argv)
{
int sfd,dfd = 1;
int ch,len,ret,pos = 0;
char buf[BUFSIZE];
if (argc < 2)
{
fprintf(stderr,"Usage : %s <source_filename> <dest_filename>\n",argv[0]);
exit(1);
}
/*给SIGALRM发送信号*/
signal(SIGALRM,alarm_handler);
alarm(1);
do
{
sfd = open(argv[1],O_RDONLY);
if (sfd < 0)
{
if(errno != EINTR)
{
perror("open()");
exit(1);
}
}
} while (sfd < 0);
while (1)
{
while(token <= 0)
pause();//等待一个系统调用,暂时去掉盲等的情况。
token--;
/*len read 10 byte*/
while(len = read(sfd,buf,BUFSIZE)<0)
{
if (errno == EINTR)
continue;
perror("read()");
break;
}
if (len == 0)
break;
pos = 0;
/*判断len是否全部填入*/
while (len > 0)
{
/*from buf read len byte to dfd*/
ret = write(dfd,buf+pos,len);
if (ret < 0 )
{
if (errno == EINTR)
continue;
perror("write()");
exit(1);
}
/*计算下一个写入的位置*/
pos += ret;
/*计算剩下的没填入的字节数*/
len -= ret;
}
}
close(sfd);
exit(0);
}
pause();
abort();
给当前进程发送 abort信号。人为制造一个异常,杀掉当前进程得到出错的现场。
system();
调用shell完成shell。
sleep();
sleep有问题是因为sleep是 alarm和pause加起来封装的。当前没有错是因 为sleep使用nanosleep封装的。可以使用nanosleep,usleep替代。
usleep();
nanosleep();
select();
令牌桶
#ifndef MYTBF_H__
#define MYTBF_H__
#define MYTBF_MAX 1024
typedef void mytbf_t;
mytbf_t *mytbf_init(int cps,int burst);
/*取令牌*/
int mytbf_fetchtoken(mytbf_t *,int );
/*归还令牌*/
int mytbf_returntoken(mytbf_t *,int );
int mytbf_destory(mytbf_t *);
#endif // DEBUG
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include "mytbf.h"
static __sighandler_t alarm_handler_save;
static struct mytbf_st* job[MYTBF_MAX];
static int inited = 0;
struct mytbf_st
{
int cps;//每秒传输的字节数
int burst;//传输的上限
int token;//令牌桶
int pos;//下标
};
static void alarm_handler(int s)
{
int i;
alarm(1);
for (i = 0; i < MYTBF_MAX; i++)
{
if (job[i] != NULL)
{
job[i]->token += job[i]->cps;
if (job[i]->token>job[i]->burst)
job[i]->token = job[i]->burst;
}
}
}
/*模块卸载,保持进出的状态都一致*/
static void module_unload(void)
{
int i;
/*恢复功能*/
signal(SIGALRM,alarm_handler_save);
alarm(0);
for (i = 0; i < MYTBF_MAX; i++)
free(job[i]);
}
static void module_load(void)
{
alarm_handler_save = signal(SIGALRM,alarm_handler);
alarm(1);
atexit(module_unload);
}
static int get_free_pos(void)
{
int i;
for (i = 0; i < MYTBF_MAX; i++)
{
if (job[i] == NULL)
return i;
}
return -1;
}
static int min(int a,int b)
{
if (a<b)
return a;
return b;
}
mytbf_t *mytbf_init(int cps,int burst)
{
struct mytbf_st *me;
int pos;
if (!inited)
{
module_load();
inited = 1;
}
pos = get_free_pos();
if (pos < 0)
return NULL;
me = malloc(sizeof(*me));
if (me == NULL)
return NULL;
me->token = 0;
me->cps = cps;
me->burst = burst;
me->pos = pos;
job[pos] = me;
return me;
}
/*取令牌*/
int mytbf_fetchtoken(mytbf_t *ptr,int size)
{
struct mytbf_st *me = ptr;//指针转换
int n;
if (size <= 0)
return -EINVAL;
while(me->token <= 0)
pause();//等待,阻塞的实现
n = min(me->token,size);
me->token -= n;
return n;
}
/*归还令牌*/
int mytbf_returntoken(mytbf_t *ptr,int size)
{
struct mytbf_st *me = ptr;//指针转换
if (size <= 0)
return -EINVAL;
me->token += size;
if (me->token > me->burst)
me->token = me->burst;
return size;
}
int mytbf_destory(mytbf_t *ptr)
{
struct mytbf_st *me = ptr;//指针转换
job[me->pos] = NULL;
free(ptr);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include "mytbf.h"
#define CPS 10
#define BUFSIZE 1024
#define BURST 100
int main(int argc,char **argv)
{
int sfd,dfd = 1;
int size;
int ch,len,ret,pos = 0;
char buf[BUFSIZE];
mytbf_t *tbf;
if (argc < 2)
{
fprintf(stderr,"Usage : %s <source_filename> <dest_filename>\n",argv[0]);
exit(1);
}
tbf = mytbf_init(CPS,BURST);
if (tbf == NULL)
{
fprintf(stderr,"mytbf_init()failed\n");
exit(1);
}
do
{
sfd = open(argv[1],O_RDONLY);
if (sfd < 0)
{
if(errno != EINTR)
{
perror("open()");
exit(1);
}
}
} while (sfd < 0);
while (1)
{
size = mytbf_fetchtoken(tbf,BUFSIZE);
if (size < 0)
{
fprintf(stderr,"mytbf_fetchtoken():%s\n",strerror(-size));
exit(1);
}
/*len read 10 byte*/
while(len = read(sfd,buf,size)<0)
{
if (errno == EINTR)
continue;
perror("read()");
break;
}
if (len == 0)
break;
if (size - len>0)
mytbf_returntoken(tbf,size-len);
pos = 0;
/*判断len是否全部填入*/
while (len > 0)
{
/*from buf read len byte to dfd*/
ret = write(dfd,buf+pos,len);
if (ret < 0 )
{
if (errno == EINTR)
continue;
perror("write()");
exit(1);
}
/*计算下一个写入的位置*/
pos += ret;
/*计算剩下的没填入的字节数*/
len -= ret;
}
}
close(sfd);
mytbf_destory(tbf);
exit(0);
}
anytime实现
.c文件
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
#include <sys/time.h>
#include "anytimer.h"
enum
{
STATE_RUNNING = 1,
STATE_CANCEL,
STATE_OVER
};
struct at_job_st
{
int job_state;
int sec;
int time_remain;
at_addjob_t *jobp;
void *arg;
};
static struct at_job_st *job[JOB_MAX];
static int inited = 0;
static struct sigaction alrm_sa_save;
static void alrm_action(int s,siginfo_t *infop,void *unused)
{
int i;
if (infop->si_code != SI_KERNEL)
return;
for ( i = 0; i < JOB_MAX; i++)
{
if(job[i]->job_state == STATE_RUNNING&&job[i]!=NULL)
{
job[i]->time_remain--;
if(job[i]->time_remain == 0)
{
job[i]->jobp(job[i]->arg);
job[i]->job_state = STATE_OVER;
}
}
}
}
static void module_unload(void)
{
struct sigaction sa,alrm_sa_save;
struct itimerval itv;
sa.sa_sigaction = alrm_action;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGALRM,&sa,&alrm_sa_save)<0)
{
perror("sigaction()");
exit(1);
}
itv.it_interval.tv_sec = 1;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 1;
itv.it_value.tv_usec = 0;
if (setitimer(ITIMER_REAL,&itv,NULL)<0)
{
perror("setitimer()");
exit(1);
}
}
static void module_load(void)
{
struct itimerval itv;
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec = 0;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_REAL,&itv,NULL);
if (sigaction(SIGALRM,&alrm_sa_save,NULL)<0)
{
perror("sigaction()");
exit(1);
}
atexit(module_unload);
}
static int get_free_pos(void)
{
int i;
for ( i = 0; i < JOB_MAX; i++)
{
if (job[i] == NULL)
return i;
}
}
int at_addjob(int sec,at_addjob_t *jobp,void* arg)
{
int pos;
struct at_job_st *me;
//只调用一次函数
if (!inited)
{
module_load();
inited = 1;
}
pos = get_free_pos();
if (pos<0)
return -ENOSPC;
me = malloc(sizeof(*me));
if (me == NULL)
return -ENOMEM;
//初始化
me->job_state = STATE_RUNNING;
me->sec = sec;
me->time_remain = me->sec;
me->jobp = jobp;
me->arg = arg;
job[pos] = me;
return pos;
}
int at_canceljob(int id)
{
if (id < 0 || id>=JOB_MAX||job[id] == NULL)
return -EINVAL;
if (job[id]->job_state == STATE_CANCEL)
return -ECANCELED;
if (job[id]->job_state == STATE_OVER)
return -EBUSY;
job[id]->job_state = STATE_CANCEL;
return 0;
}
int at_waitjob(int id)
{
if (id < 0 || id >= JOB_MAX||job[id] == NULL)
return -EINVAL;
while(job[id]->job_state == STATE_RUNNING)
pause();
if (job[id]->job_state == STATE_CANCEL||job[id]->job_state == STATE_OVER)
{
free(job[id]);
job[id] = NULL;
}
}
.h文件
#ifndef MYTBF_H__
#define MYTBF_H__
#define JOB_MAX 1024
typedef void at_addjob_t(void*);
int at_addjob(int sec,at_addjob_t *jobp,void* arg);
/*
* return >= 0 成功,返回任务ID
* == -EINVAL 失败,参数非法
* == -ENOSPC 失败,数组满
* == -ENOMEM 失败,内存空间不足
**/
int at_addjob_repeat(int sec,at_addjob_t *jobp,void* arg);
/*
* return >= 0 成功,返回任务ID
* == -EINVAL 失败,参数非法
* == -ENOSPC 失败,数组满
* == -ENOMEM 失败,内存空间不足
**/
int at_canceljob(int id);
/*
* return == 0 取消,指定任务成功取消
* == -EINVAL 失败,参数非法
* == -EBUSY 失败,任务已完成
* == -ECANCELED 失败,指定任务重复取消
**/
int at_waitjob(int id);
/*
* return == 0 取消,指定任务成功释放
* == -EINVAL 失败,参数非法
**/
#endif
main.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <errno.h>
static void f1(void *p)
{
printf("f1():%s\n",p);
}
static void f2(void *p)
{
printf("f2():%s\n",p);
}
int main(int argc,char **argv)
{
int job1,job2,job3;
puts("Begin!");
job1 = at_addjob(5,f1,"aaa");
if (job1 < 0)
{
fprintf(stderr,"at_addjob():%s\n",strerror(-job1));
exit(1);
}
at_addjob(2,f2,"bbb");
at_addjob(7,f1,"ccc");
puts("End!");
}
7、信号集合
信号集类型:sigset_t
sigemptyset();
sigfillset();
sigaddset();
sigdelset();
sigismember();
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>
void int_handler(int s)
{
write(1,"!",1);
}
int main()
{
int i,j;
/*把打断信号忽略掉*/
//signal(SIGINT,SIG_IGN);
sigset_t set,oset,saveset;
signal(SIGINT,int_handler);
sigemptyset(&set);
sigaddset(&set,SIGINT);
sigprocmask(SIG_BLOCK,&set,&oset);
for (j = 0; i < 1000; j++)
{
/*代码执行过程中,不受信号影响*/
sigprocmask(SIG_BLOCK,&set,&oset);
for (i = 0; i < 5; i++)
{
write(1,"*",1);
sleep(1);
}
write(1,"\n",1);
/*解除阻塞,返回之前的状态*/
sigprocmask(SIG_SETMASK,&oset,NULL);
}
sigprocmask(SIG_SETMASK,&saveset,NULL);
/*一头一尾表示进入这个状态和出去这个状态是没有影响的*/
exit(0);
}
8、信号屏蔽字/pending集合的处理
sigprocmask();//相当于给一种机会来人为的控制mask。不能确定信号什么时候到来,但是可以确定信号什么时候被响应。
sigpending();//不知道用在什么环境下
9、扩展
sigsuspend();
信号驱动程序
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>
void int_handler(int s)
{
write(1,"!",1);
}
int main()
{
int i,j;
/*把打断信号忽略掉*/
//signal(SIGINT,SIG_IGN);
sigset_t set,oset,saveset;
signal(SIGINT,int_handler);
sigemptyset(&set);
sigaddset(&set,SIGINT);
sigprocmask(SIG_UNBLOCK,&set,&saveset);
sigprocmask(SIG_BLOCK,&set,&oset);
for (j = 0; i < 1000; j++)
{
/*代码执行过程中,不受信号影响*/
for (i = 0; i < 5; i++)
{
write(1,"*",1);
sleep(1);
}
write(1,"\n",1);
sigsuspend(&oset);//相当于如下的原子操作。
/*解除阻塞,返回之前的状态*/
/*
sigset_t tmpset;
sigprocmask(SIG_SETMASK,&oset,&tmpset);
pause();
sigprocmask(SIG_SETMASK,&tmpset,NULL);
*/
}
sigprocmask(SIG_SETMASK,&saveset,NULL);
exit(0);
}
sigaction();
setitimer();
守护进程的重构
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <glob.h>
#include <syslog.h>
#include <errno.h>
#include <signal.h>
#define FNAME "tmp/out"
static FILE *fp;
/*多个信号可以共用同一个信号处理函数*/
static void daemon_exit(int s)
{
fclose(fp);
closelog();
}
static int daemonize()
{
pid_t pid;
int fd;
pid = fork();
if (pid<0)
return -1;
if (pid>0) //parent
{
exit(0);
}
fd = open("/dev/null",O_RDWR);
if (fd<0)
return -1;
//将来要脱离控制终端的,0、1、2不需要关联设备,因此需要重定向。
dup2(fd,0);
dup2(fd,1);
dup2(fd,2);
if (fd > 2)
{
close(fd);
}
setsid();
chdir("/");
return 0;
}
int main()
{
int i;
//当你受到INTERRUPT这个信号的时候,就来执行
struct sigaction sa;
sa.sa_handler = daemon_exit;
__sigemptyset(&sa.sa_mask);
__sigaddset(&sa.sa_mask,SIGQUIT);
__sigaddset(&sa.sa_mask,SIGTERM);
__sigaddset(&sa.sa_mask,SIGINT);
sa.sa_flags = 0;
sigaction(SIGINT,&sa,NULL);
sigaction(SIGTERM,&sa,NULL);
sigaction(SIGQUIT,&sa,NULL);
openlog("mydaemon",LOG_PID,LOG_DAEMON);
if (daemonize())
{
syslog(LOG_ERR,"daeonize() failed!");
exit(1);
}
else
{
syslog(LOG_INFO,"daemonize() successded!");
}
fp = fopen(FNAME,"w");
if (fp == NULL)
{
syslog(LOG_ERR,"fopen():%s",strerror(errno));
exit(1);
}
syslog(LOG_INFO,"%s was opened.",FNAME);
for (i = 0; ; i++)
{
fprintf(fp,"%d\n",i);
fflush(fp);
syslog(LOG_DEBUG,"%d is printed",i);
sleep(1);
}
fclose(fp);
closelog();
exit(0);
}
令牌桶改装sigaction
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <sys/time.h>
#include "mytbf.h"
static struct mytbf_st* job[MYTBF_MAX];
static int inited = 0;
static struct sigaitvction alrm_sa_save;
struct mytbf_st
{
int cps;//每秒传输的字节数
int burst;//传输的上限
int token;//令牌桶
int pos;//下标
};
static void alrm_action(int s,siginfo_t *infop,void *unused)
{
int i;
//alarm(1);
if (infop->si_code != SI_KERNEL)
return;
for (i = 0; i < MYTBF_MAX; i++)
{
if (job[i] != NULL)
{
job[i]->token += job[i]->cps;
if (job[i]->token>job[i]->burst)
job[i]->token = job[i]->burst;
}
}
}
/*模块卸载,保持进出的状态都一致*/
static void module_unload(void)
{
int i;
/*恢复功能*/
struct itimerval itv;
sigaction(SIGALRM,&alrm_sa_save,NULL);
itv.it_interval.tv_sec = 0;
itv.it_interval.tv_usec =0;
itv.it_value.tv_sec = 0;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_REAL,&itv,NULL);
for (i = 0; i < MYTBF_MAX; i++)
free(job[i]);
}
static void module_load(void)
{
struct sigaction sa;
struct itimerval itv;
sa.sa_sigaction = alrm_action;
__sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sigaction(SIGALRM,&sa,&alrm_sa_save);
/*if error*/
itv.it_interval.tv_sec = 1;
itv.it_interval.tv_usec =0;
itv.it_value.tv_sec =1;
itv.it_value.tv_usec = 0;
setitimer(ITIMER_REAL,&itv,NULL);
/*if error*/
atexit(module_unload);
}
static int get_free_pos(void)
{
int i;
for (i = 0; i < MYTBF_MAX; i++)
{
if (job[i] == NULL)
return i;
}
return -1;
}
static int min(int a,int b)
{
if (a<b)
return a;
return b;
}
mytbf_t *mytbf_init(int cps,int burst)
{
struct mytbf_st *me;
int pos;
if (!inited)
{
module_load();
inited = 1;
}
pos = get_free_pos();
if (pos < 0)
return NULL;
me = malloc(sizeof(*me));
if (me == NULL)
return NULL;
me->token = 0;
me->cps = cps;
me->burst = burst;
me->pos = pos;
job[pos] = me;
return me;
}
/*取令牌*/
int mytbf_fetchtoken(mytbf_t *ptr,int size)
{
struct mytbf_st *me = ptr;//指针转换
int n;
if (size <= 0)
return -EINVAL;
while(me->token <= 0)
pause();//等待,阻塞的实现
n = min(me->token,size);
me->token -= n;
return n;
}
/*归还令牌*/
int mytbf_returntoken(mytbf_t *ptr,int size)
{
struct mytbf_st *me = ptr;//指针转换
if (size <= 0)
return -EINVAL;
me->token += size;
if (me->token > me->burst)
me->token = me->burst;
return size;
}
int mytbf_destory(mytbf_t *ptr)
{
struct mytbf_st *me = ptr;//指针转换
job[me->pos] = NULL;
free(ptr);
return 0;
}
10、实时信号
实时信号和标准信号。当信号同时发生的时候,先响应标准信号。
实时信号示例
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <signal.h>
#define MYRTSIG (SIGRTMIN+6)
void mysig_handler(int s)
{
write(1,"!",1);
}
int main()
{
int i,j;
/*把打断信号忽略掉*/
//signal(SIGINT,SIG_IGN);
sigset_t set,oset,saveset;
signal(MYRTSIG,mysig_handler);
sigemptyset(&set);
sigaddset(&set,MYRTSIG);
sigprocmask(SIG_UNBLOCK,&set,&saveset);
sigprocmask(SIG_BLOCK,&set,&oset);
for (j = 0; i < 1000; j++)
{
/*代码执行过程中,不受信号影响*/
for (i = 0; i < 5; i++)
{
write(1,"*",1);
sleep(1);
}
write(1,"\n",1);
sigsuspend(&oset);//相当于如下的原子操作。
/*解除阻塞,返回之前的状态*/
/*
sigset_t tmpset;
sigprocmask(SIG_SETMASK,&oset,&tmpset);
pause();
sigprocmask(SIG_SETMASK,&tmpset,NULL);
*/
}
sigprocmask(SIG_SETMASK,&saveset,NULL);
exit(0);
}