令牌桶封装成库

该博客介绍了令牌桶算法的原理,包括其核心的三要素:令牌数量、流速和最大令牌数,并提供了一个简单的C语言实现。通过创建、取令牌、归还令牌和销毁令牌桶的函数,展示了如何在实际场景中使用令牌桶来控制数据传输速率。在main.c文件中,令牌桶被应用于读写文件操作,以限制读取速度。

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;
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值