令牌桶封裝成庫示例

token_bucket.h文件(主要用來函數(shù)聲明)

#ifndef __TOKEN_BUCKET_H
#define __TOKEN_BUCKET_H
/*
 * 實(shí)現(xiàn)令牌桶
 *      token  令牌
 *      cps    速率
 *      burst  上限
 */

#define TBF_MAX    1024

//創(chuàng)建令牌桶
int tbf_init(int cps, int burst);

//取令牌
int tbf_fetch(int id, int size);

//還令牌
int tbf_return(int id, int size);

//銷毀令牌桶
int tbf_destory(int id);

#endif

token_bucket.c文件

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#include "token_bucket.h"

//定義桶的類型
struct tbf_st
{
    int cps;
    int burst;
    int token;
};

//定義1024的數(shù)組存桶的結(jié)構(gòu)體地址
static struct tbf_st *line[TBF_MAX];
static int inited = 0;
struct sigaction oldact;
struct itimerval olditv;

//模塊卸載房午,信號(hào)行為和時(shí)鐘恢復(fù)
static void  mouder_unload(void)
{
    sigaction(SIGALRM, &oldact, NULL);
    setitimer(ITIMER_REAL, &olditv, NULL);
}

/******************************************/
static void alrm_handler(int s)
{
    for(int i=0; i<TBF_MAX; i++)
    {
        if(line[i] != NULL)
        {
            line[i] -> token += line[i] -> cps;
            if(line[i]->token >= line[i] -> burst)
                line[i] -> token = line[i] -> burst;
        }
    }
}

static void mouder_load(void)
{
    struct sigaction act;
    struct itimerval itv;

    act.sa_handler = alrm_handler;
    act.sa_flags = 0;
    sigemptyset(&act.sa_mask);
    
    sigaction(SIGALRM, &act, &oldact);
    
    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, &olditv);

    atexit(mouder_unload);
}


//創(chuàng)建令牌桶
int tbf_init(int cps, int burst)
{
    struct tbf_st *new;
    int i;

    if(inited == 0)
    {
        mouder_load();
        inited = 1;
    }

    //找空位
    for(i=0; i<TBF_MAX; i++)
    {
        if(line[i] == NULL)
            break;
        return -1;
    }

    new = malloc(sizeof(*new));
    if( new == NULL)
        return -1;

    new->token = 0;
    new->cps = cps;
    new->burst = burst;

    line[i] = new;

    return i;
}

/**********************************************/
//找最小值
static int min(int a,int b)
{
    return a>b?a:b;
}

//取令牌
int tbf_fetch(int id, int size)
{
    int n;
    if(size <= 0)
        return -1;
    while(line[id]->token <= 0)
    {
        pause();
    }

    //取兩者最小
    n = min(line[id]->token,size);

    line[id]->token -= n;

    return 0;
}
/**********************************************/

//還令牌
int tbf_return(int id, int size)
{
    if(size <= 0)
        return -1;
    line[id]->token += size;
    if(line[id]->token > line[id]->burst)
        line[id]->token = line[id]->burst;
    return size;
}

//銷毀令牌桶
int tbf_destory(int id)
{
    if(id < 0 || id > TBF_MAX-1)
    {
        return -1;
    }
    free(line[id]);
    line[id] = NULL;
    return 0;
}

調(diào)試文件main.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <stdlib.h>

#include "token_bucket.h"

#define BUFSIZE 10
#define CPS BUFSIZE 
#define BURST CPS*10

int main(int argc, char **argv)
{
    int rfd, wfd;
    char buf[BUFSIZE] = {};
    int cnt, ret, pos;
    int tb,n;

    if (argc < 2) 
    {
        fprintf(stderr, "Usage....\n");
        return 1;
    }

    while (1) 
    {
        rfd = open(argv[1], O_RDONLY);
        if (rfd == -1) 
        {
            if (errno == EINTR)
            {
                // 信號(hào)打斷---》假錯(cuò)
                continue;
            }
            perror("open()"); // 輸出到標(biāo)準(zhǔn)錯(cuò)誤輸出
            return 1;
        }
        break;
    }

    tb = tbf_init(CPS, BURST);

    if(tb < 0)
    {
        fprintf(stderr, "tbf_init():");
        exit(1);
    }

    wfd = 1;

    while (1)
    {
        n = tbf_fetch(tb, CPS);
        if(n < 0)
        {
            fprintf(stderr, "tbf_fetch():");
            goto ERROR1;
        }

        cnt = read(rfd, buf, CPS); // 阻塞
        if (-1 == cnt) {
            if (errno == EINTR)
                continue;
            perror("read()");
            goto ERROR1;
        }
        if (0 == cnt) {
            // rfd結(jié)束標(biāo)志
            break;
        }
        pos = 0;
        while (1) {
            ret = write(wfd, buf+pos, cnt);
            if (ret < 0) {
                if (errno == EINTR)
                    continue;
                perror("write()");
                goto ERROR1;
            }
            cnt -= ret;
            if (cnt > 0) {
                // 沒寫完
                pos += ret;
            } else {
                break;
            }
        }
    }

    tbf_destory(tb);

    close(rfd);

    return 0;
ERROR1:
    close(rfd);
    return 1;
}

makefile文件

SRC=main.o token_bucket.o
OBJ=tbf

$(OBJ):$(SRC)
    gcc -o $@ $^

clean:
    rm *.o $(OBJ)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末纤勒,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌前塔,老刑警劉巖陪竿,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件迄汛,死亡現(xiàn)場(chǎng)離奇詭異寂恬,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)哲银,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門扛吞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呻惕,“玉大人,你說我怎么就攤上這事滥比⊙谴啵” “怎么了?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵守呜,是天一觀的道長型酥。 經(jīng)常有香客問我,道長查乒,這世上最難降的妖魔是什么弥喉? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮玛迄,結(jié)果婚禮上由境,老公的妹妹穿的比我還像新娘。我一直安慰自己蓖议,他們只是感情好虏杰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著勒虾,像睡著了一般纺阔。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上修然,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天笛钝,我揣著相機(jī)與錄音,去河邊找鬼愕宋。 笑死玻靡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的中贝。 我是一名探鬼主播囤捻,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼邻寿!你這毒婦竟也來了蝎土?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤绣否,失蹤者是張志新(化名)和其女友劉穎瘟则,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體枝秤,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年慷嗜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了淀弹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丹壕。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖薇溃,靈堂內(nèi)的尸體忽然破棺而出菌赖,到底是詐尸還是另有隱情,我是刑警寧澤沐序,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布琉用,位于F島的核電站,受9級(jí)特大地震影響策幼,放射性物質(zhì)發(fā)生泄漏邑时。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一特姐、第九天 我趴在偏房一處隱蔽的房頂上張望晶丘。 院中可真熱鬧,春花似錦唐含、人聲如沸浅浮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽滚秩。三九已至,卻和暖如春淮捆,著一層夾襖步出監(jiān)牢的瞬間郁油,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來泰國打工争剿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留已艰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓蚕苇,卻偏偏與公主長得像哩掺,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子涩笤,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容

  • 稀缺是永恒的嚼吞,而短缺和過剩都是價(jià)格受到人為干預(yù)的結(jié)果。 當(dāng)價(jià)格過低的時(shí)候蹬碧,人們不得不展開價(jià)格以外的競(jìng)爭(zhēng)方...
    鐘樹堂閱讀 712評(píng)論 0 1
  • 今天又再一次深深地體會(huì)到舱禽,我們做人有空杯心是多么的重要。其實(shí)我們每天早上做的第一件事情是什么恩沽,我們肯定是先去上衛(wèi)生...
    林玉珍閱讀 380評(píng)論 0 1
  • 我這個(gè)人,自尊心很強(qiáng)里伯,但能力一般城瞎,意志力又差,沒有什么過人之處疾瓮,可以總結(jié)為死要面子的屌絲一枚脖镀。這就很矛盾了,沒實(shí)力...
    皮德拉閱讀 356評(píng)論 6 3
  • 在成年人的世界里狼电,讀書這一行為多少帶有目的性和功利性蜒灰。有時(shí),我們閱讀是為了實(shí)現(xiàn)自己的目標(biāo)與理想肩碟,有時(shí)是為了提升...
    無涯的生活日志閱讀 533評(píng)論 5 4
  • 教育故事----蹲下身子和孩子說話 題記:“馮博羹唠,如果在期末考試中語文虐译、數(shù)學(xué)都考九十分以上弦追,來找我驴娃,發(fā)獎(jiǎng)...
    東原郡人閱讀 655評(píng)論 0 1