1.一个令牌桶的三要素
①token 当前的令牌个数
②cps当前的流速
③burst最大令牌数
简单实现
mytbf.h
#ifndef __MYTBF_H__
#define __MYTBF_H__
//数组的大小 也就是说总共有1024个桶
#define MYTBF_MAX 1024
//对内部的数据结构进行一个封装返回void *
typedef void mytbf_st;
//这里返回一个void*
mytbf_st * InitMytbf(int nCps, int nBurst);
//从令牌桶中取出n个令牌 返回值是真正取到的令牌数
int TakeToken(mytbf_st *, int );
//没有用完的令牌的回收
int ReturnToken(mytbf_st *, int);
//释放空间
int DestoryMytbf(mytbf_st *);
#endif
mytbf.c
typedef void (*sighandler_t)(int);
struct mytbf_st
{
int token;//积累的传输量
int burst;//传输量的最大限制
int cps;//每秒增加的传输量
int pos;//在数组中下标的位置
};
struct mytbf_st * job[MYTBF_MAX];
static sighandler_t SignalRes;
static int Inited = 0;
int GetFreePos(void)
{
int i;
for(i = 0; i < MYTBF_MAX; i++)
{
if(NULL == job[i])
return i;
}
return -1;
}
void AlarmHandler(int nNum)
{
int i;
alarm(1);
for(i = 0; i < MYTBF_MAX; i++)
{
if(NULL != job[i])
{
job[i]->token += job[i]->cps ;
if(job[i]->burst < job[i]->token)
job[i]->token = job[i]->burst;
}
}
}
void ModuleUnload(void)
{
int i;
signal(SIGALRM, SignalRes);
alarm(0);
for(i = 0; i < MYTBF_MAX; i++)
{
free(job[i]);
}
}
void ModuleLoad(void)
{
SignalRes = signal(SIGALRM, AlarmHandler);
alarm(1);
Inited = 1;
//钩子函数
atexit(ModuleUnload);
}
//这里返回一个void*
mytbf_st * InitMytbf(int nCps, int nBurst)
{
struct mytbf_st *me;
int nPos;
if(!Inited)
{
ModuleLoad();
}
nPos = GetFreePos();
if(-1 == nPos)
return NULL;
me = (struct mytbf_st *)malloc(sizeof(struct mytbf_st));
if(NULL == me)
return me;
me->cps = nCps;
me->token = 0;
me->burst = nBurst;
me->pos = nPos;
job[nPos] = me;
return me;
}
//从令牌桶中取出n个令牌 返回值是真正取到的令牌数
int TakeToken(mytbf_st *ptr , int nNum)
{
struct mytbf_st *me = ptr;
int min;
if(nNum <= 0)
return -1;
while(me->token <= 0)
pause();
//取最小值
min = nNum > me->token ? me->token : nNum;
me->token -= min;
return min;
}
//没有用完的令牌的回收
int ReturnToken(mytbf_st *ptr, int nNum)
{
struct mytbf_st *me = ptr;
int min;
if(nNum <= 0)
return -1;
me->token += nNum;
//不能超过上限
if(me->token > me->burst)
me->token = me->burst;
return nNum;
}
//释放空间
int DestoryMytbf(mytbf_st *ptr)
{
struct mytbf_st *me = ptr;
job[me->pos] = NULL;
free(me);
return 0;
}
main.c
#define BUFSIZE 255
int main(int argc, char **argv)
{
int fd;
char Buf[BUFSIZE];
int RealSize;
mytbf_st *tbf;
int TokenSize;
if(argc < 2)
{
fprintf(stderr, "No enough argc\n");
exit(1);
}
fd = open(argv[1], O_RDONLY );
if(fd < 0)
{
perror("open()");
exit(1);
}
tbf = InitMytbf(10, 20);
while(1)
{
TokenSize = TakeToken(tbf, BUFSIZE);
//printf("Size == %d\n", TokenSize);
RealSize = read(fd, Buf, TokenSize);
write(1, Buf, RealSize);
ReturnToken(tbf, TokenSize - RealSize);
if(RealSize < 10)
break;
}
close(fd);
DestoryMytbf(tbf);
return 0;
}
该博客介绍了令牌桶算法的原理,包括其核心的三要素:令牌数量、流速和最大令牌数,并提供了一个简单的C语言实现。通过创建、取令牌、归还令牌和销毁令牌桶的函数,展示了如何在实际场景中使用令牌桶来控制数据传输速率。在main.c文件中,令牌桶被应用于读写文件操作,以限制读取速度。
948

被折叠的 条评论
为什么被折叠?



