mytbf.h
#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_destroy(mytbf_t *);
#endif
mytbf.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include "mytbf.h"
#include <sys/time.h>
struct mytbf_st
{
int cps;
int token;
int burst;
int pos;
};
static struct mytbf_st* job[MYTBF_MAX];
static int inited = 0;
//typedef void(*sighandler_t)(int);
//static sighandler_t alrm_handler_save;
struct sigaction alrm_sigaction_save;
static void alrm_sigaction(int signo,siginfo_t* info,void*)
{
if( info->si_code != SI_KERNEL)
{
return ;
}
for( int 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;
}
}
// alarm(1);
}
static void module_unload()
{
// signal(SIGALRM,alrm_handler_save);
// alarm(0);
sigaction(SIGALRM,&alrm_sigaction_save,NULL);
struct itimerval timeval;
timeval.it_interval.tv_sec = 0;
timeval.it_interval.tv_usec = 0;
timeval.it_value.tv_sec = 0;
timeval.it_value.tv_usec = 0;
setitimer(ITIMER_REAL,&timeval,NULL);
for( int i = 0; i < MYTBF_MAX;i++)
{
free(job[i]);
}
}
static void module_load()
{
// alrm_handler_save = signal(SIGALRM,alrm_handler);
// alarm(1);
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = alrm_sigaction;
sigaction(SIGALRM,&sa,&alrm_sigaction_save);
struct itimerval timeval;
timeval.it_interval.tv_sec = 1;
timeval.it_interval.tv_usec = 0;
timeval.it_value.tv_sec = 1;
timeval.it_value.tv_usec = 0;
setitimer(ITIMER_REAL,&timeval,NULL);
atexit(module_unload);
}
static int get_free_pos(void)
{
int i = 0;
for( ;i < MYTBF_MAX; i++)
{
if( job[i] == NULL)
{
return i;
}
}
return -1;
}
mytbf_t * mytbf_init(int cps,int burst)
{
struct mytbf_st* me;
if( !inited)
{
module_load();
inited = 1;
}
int 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;
}
static int min(int a,int b)
{
return a > b? b: a;
}
int mytbf_fetchtoken(mytbf_t*ptr ,int size)
{
struct mytbf_st * me = ptr;
if( size <=0)
{
return -EINVAL;
}
while(me->token <=0)
pause();
int 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_destroy(mytbf_t *ptr)
{
struct mytbf_st * me = ptr;
job[me->pos] = NULL;
free(ptr);
return 0;
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <stdbool.h>
#include <errno.h>
#include <fcntl.h>
#define CPS 100
#define BUFFSIZE 10240
#define BURST 1000
volatile static int token =0;
#include "mytbf.h"
int main( int argc, char** argv)
{
if( argc < 2)
{
fprintf(stderr,"Usage:%s <src_file> \n",argv[0]);
exit(0);
}
int sfd,dfd = 1;
char buff[BUFFSIZE];
mytbf_t *tbf;
int size;
tbf = mytbf_init(CPS,BURST);
if( tbf == NULL)
{
fprintf(stderr,"mytbf_init() error");
exit(0);
}
if( (sfd = open(argv[1],O_RDONLY))<0)
{
perror("open()");
exit(1);
}
while(1)
{
size = mytbf_fetchtoken(tbf,BUFFSIZE);
ssize_t read_size;
errno =0;
while((read_size = read(sfd,buff,size)) < 0)
{
if( errno == EINTR)
{
continue;
}
}
if( size - read_size > 0)
mytbf_returntoken(tbf,size - read_size);
// read_size = read(sfd,buff,BUFFSIZE);
if( read_size == 0)
break;
if( read_size < 0)
break;
ssize_t write_size = 0;
errno = 0;
while( read_size)
{
ssize_t ret = write(dfd,buff+write_size,read_size);
if( ret < 0 && errno != EINTR)
{
break;
}
errno =0;
read_size -= ret;
}
}
mytbf_destroy(tbf);
close(sfd);
exit(0);
}
makefile
all:mytbf
mytbf: main.o mytbf.o
gcc $^ -o $@
clean:
rm *.o mytbf