做的好的阅读类的网站有哪些,onepress wordpress,海尔网站的建设目标,电脑微信怎么进入公众号令牌桶实例
令牌桶三要素
cps 每秒钟传输字节数
burst 令牌桶内最多能传输的字节数#xff0c;token的最大值
token 令牌的个数
之前是一个令牌(token)对应一个字节#xff0c;现在将一个token变为一个cps#xff0c;cps是解码速率#xff0c;每攒到一个令牌#xff…令牌桶实例
令牌桶三要素
cps 每秒钟传输字节数
burst 令牌桶内最多能传输的字节数token的最大值
token 令牌的个数
之前是一个令牌(token)对应一个字节现在将一个token变为一个cpscps是解码速率每攒到一个令牌就tokencps
不同的速率使用不同的令牌桶将令牌桶存储在一个数组中。
代码
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 *);#endifmytbf.c
#include stdlib.h
#include stdio.h
#include unistd.h
#include signal.h#include mytbf.htypedef void (*sighandler_t)(int);//将令牌桶的数据结构存在数组中
static struct mytbf_st * job[MYTBF_MAX];
static int inited 0;
#define MIN(A,B) (A B ? A : B)
static sighandler_t alrm_handler_save;/*每个token代表一个字节cps代表解码速率burst应该是cps的倍数tokentokencps*/
//这是令牌桶的数据结构这个数据结构存在数组中
struct mytbf_st
{int cps; //每秒钟传输的字节数int burst; //令牌桶中令牌最大数量int token; //令牌的个数int pos; //记录令牌桶在数组的位置下标
};//信号捕捉函数
static void alrm_handler(int s)
{alarm(1);//为数组中的令牌桶中的令牌做累计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;}}
}
//关闭时钟发送信号恢复
static void module_unload(void)
{int i;//恢复SIGALRM到之前的功能signal(SIGALRM,alrm_handler_save);//取消时钟发送信号alarm(0);//释放令牌桶for(i 0;i MYTBF_MAX;i){free(job[i]);}}
//第一次发时钟信号的函数
static void module_load(void)
{//signal的返回值是注册新的行为之前的行为alrm_handler_save signal(SIGALRM,alrm_handler);alarm(1);//注册钩子函数这个不是函数调用而是当调用exit的时候才会调用atexit(module_unload);
}static int get_free_pos(void)
{int i 0;for(i 0;i MYTBF_MAX; i){if(job[i] NULL)return i;}return -1;
}mytbf_t *mytbf_init(int cps,int burst)
{int pos 0;struct mytbf_st *me;//在数组中找到空位下标pospos get_free_pos();if(pos 0){return NULL;}if( !inited ){module_load();inited 1;}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)
{int n;struct mytbf_st *me ptr;if(size 0)return -1;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 -1;me-token size;if(me-token me-burst)me-token me-burst;return size;
}//销毁令牌桶
int mytbf_destroy(mytbf_t *ptr)
{ //因为mytbf_t 是void类型转换下struct mytbf_st *me ptr;job[me-pos] NULL;free(me);return 0;
}main.c
#include stdio.h
#include stdlib.h
#include sys/types.h
#include sys/stat.h
#include fcntl.h
#include unistd.h
#include signal.h
#include errno.h
#include mytbf.h#define CPS 10
#define BUFSIZE 1024
#define BURST 100int main(int argc,char**argv)
{int sfd,dfd 1;int size,errnor;char buf[BUFSIZE];int len,ret,pos;mytbf_t * tbf;if(argc 2){fprintf(stderr,Usage ....\n);exit(1);}//初始化令牌桶tbf mytbf_init(CPS,BURST);//打开要读取的文件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 is error\n);exit(1);}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;//使用循环读因为是向终端写while(len 0){ret write(dfd,bufpos,len);if(ret 0){ //假错继续读if(ret EINTR)continue;perror(write());exit(1);}pos ret;len - ret;}}mytbf_destroy(tbf);exit(0);
}
makefile
all:mytbf
mytbf:main.o mytbf.ogcc $^ -o $
clean:rm *.o mytbf