鸿蒙源码分析(六十六)

令牌桶代码介绍

token_bucket主要是令牌桶相关处理,本篇博客主要是分析一下令牌桶代码,理论知识见下篇博客。

令牌桶理论介绍

理论知识。

先从头文件开始

头文件是相关结构体的申明,我们先看最重要的结构体TokenBucket,这个就是最基础的令牌桶。主要有下面几个属性

  • rate:这个参数是指令牌生成速度的指标
  • burst:我们可以看作是桶的大小
  • last:是指消息传送时候最后一个消息的时间
  • used:当前正在使用的桶
#define TOKEN_PRE_MSG 1000
typedef struct TokenBucket TokenBucket;
struct TokenBucket {
    
    
    int rate;  // 每毫秒生成令牌的速率。现在,我们改用TPS。
    int burst; // The burst size of the token bucket
    uint64 last; // 最后一个消息的时间
    int used; // 使用的桶
};

桶状态结构体BucketStatus
主要只有三个状态:busy、Idle、Invalid。
其中busy指的是该令牌桶正在被使用中,他已经完成了初始化等等前期步骤,已经是可以使用了。
Idle状态指的是闲置状态,就是完成初始化了,但是还没有使用这个桶,这时候可以理解为这个桶是一个可用状态。
invalid状态是指不可用,可能是在使用过程中:堆栈溢出、不合法调用等等错误操作导致桶处于无效状态。
这一步常常伴随初始化过程.

typedef enum BucketStatus {
    
    
    BUCKET_BUSY,
    BUCKET_IDLE,
    BUCKET_INVALID,
} BucketStatus;

下面是一个初始化函数TB_InitBucket
这个函数用来初始化令牌桶,我们之前分析可以知道令牌桶有四个属性,但是这里初始化时候只用了两个变量。下面我们来看具体函数。
从参数开始:

  • bucket:要操作的桶指针
  • rate:桶生成速度
  • burst:桶的size大小

其他两个参数这里全部置为了0,一个是上一条消息的时间,另外一个是当前使用的桶。这时候如果rate变量是TPS的化,这个used对应的变量就是TOKEN_PRE_MSG------宏定义为1000。

inline static void TB_InitBucket(TokenBucket *bucket, int rate, int burst)
{
    
    
    bucket->last = 0;
    bucket->rate = rate;
    bucket->burst = burst;
    bucket->used = 0;
}

源文件中的参数分析

令牌桶的.c文件中只有一个函数,TB_CheckMessage。该函数顾名思义是令牌桶在检查消息是否可以处理,核心部分只有下面几行
在这里插入图片描述
全部代码如下:

int TB_CheckMessage(TokenBucket *bucket)
{
    
    
    if (bucket == NULL) {
    
    
        return BUCKET_INVALID;
    }
    uint64 now = SAMGR_GetProcessTime();
    //这里获取一次当前内核时间
    uint64 generated = (now > bucket->last) ? ((now - bucket->last) * bucket->rate) : 0;
    //这时候当前时间如果大于桶内last属性,generated变量就是(当前时间减去last)*TPS,否则generate就是0
    //这里的意义就是生成令牌的数量
    int used = bucket->used + TOKEN_PRE_MSG;
    //当前使用令牌+1000
    used = (generated > used) ? 0 : (used - (int)generated);
    //生成得到令牌>used时候,就是令牌不够用了,这时候讲used置为0,否则当前令牌就是之前的used前去生成的generated
    if (used >= bucket->burst * TOKEN_PRE_MSG) {
    
    
    //当前使用令牌多于桶大小和消息乘积,说明桶正在处理数据,处于busy状态
        return BUCKET_BUSY;
    }
    bucket->used = used;
    bucket->last = now;
    //如果令牌数量少于消息所用令牌,说明无法处理,这时候桶处于闲置状态,可用
    return BUCKET_IDLE;
}

这个函数主要就是检查消息是否可以通过令牌桶处理或者发送,因为令牌桶内令牌的数量决定当前消息是否可以处理,如果可以处理就将桶的状态置为可用,否则就是busy。

猜你喜欢

转载自blog.csdn.net/m0_46976252/article/details/120983991
今日推荐