SCP限速逻辑实现--带中文注释的bandwidth_limit函数

SCP限速逻辑实现--带中文注释的bandwidth_limit函数

SCP限速逻辑实现--带中文注释的bandwidth_limit函数

SCP支持限速, 通过-l参数, 指定拷贝的速度
 -l limit
             Limits the used bandwidth, specified in Kbit/s.

具体实现, 是在misc.c中的bandwidth_limit函数
下面附上带中文注释的bandwidth_limit函数代码
 1  struct bwlimit {
 2     size_t buflen;                  //  每次read的buf长度
 3      u_int64_t rate, thresh, lamt;   //  rate:  限速速率, 单位kpbs
 4                                      //  thresh:统计周期,read长度到了指定阈值, 触发限速统计
 5                                      //  lamt:  一次统计周期内, read了多少长度
 6       struct timeval bwstart, bwend;  //  bwstart: 统计周期之开始时间
 7                                      //  bwend:   统计周期之结束时间
 8  };
 9 
10  void bandwidth_limit_init( struct bwlimit *bw, u_int64_t kbps, size_t buflen)
11 {
12     bw->buflen = buflen;           //  初始化read buf长度
13      bw->rate = kbps;               //  初始化限速速率
14      bw->thresh = bw->rate;         //  初始化统计周期
15      bw->lamt = 0;                  //  初始化当前read长度
16      timerclear(&bw->bwstart);      //  初始化统计开始时间
17      timerclear(&bw->bwend);        //  初始化统计结束时间
18  }
19 
20  void bandwidth_limit( struct bwlimit *bw, size_t read_len)
21 {
22     u_int64_t waitlen;
23      struct timespec ts, rm;
24 
25      //  设置统计开始时间, 为当前时间
26       if (!timerisset(&bw->bwstart)) {
27         gettimeofday(&bw->bwstart, NULL);
28          return;
29     }
30 
31      //  设置当前read长度
32      bw->lamt += read_len;
33      //  判断当前read长度是否到达统计周期的阈值
34       if (bw->lamt < bw->thresh)
35          return;
36 
37      //  设置统计结束时间,为当前时间
38      gettimeofday(&bw->bwend, NULL);
39      //  bwend变量复用, 这个时候, bwend含义为, 本次统计周期实际开销的时间: 既read thresh长度字节,花了多少时间.
40      timersub(&bw->bwend, &bw->bwstart, &bw->bwend);
41      if (!timerisset(&bw->bwend))
42          return;
43 
44      //  将单位从Byte变成bit
45      bw->lamt *= 8;
46      //  根据限速速率, 计算理论应该花费多少时间
47      waitlen = ( double)1000000L * bw->lamt / bw->rate;
48      //  bwstart变量复用, 这个时候, bwstart含义为, 本次统计周期理论开销的时间
49      bw->bwstart.tv_sec = waitlen / 1000000L;
50     bw->bwstart.tv_usec = waitlen % 1000000L;
51 
52      //  如果理论开销时间 >  实际开销时间, 则需要做限速
53       if (timercmp(&bw->bwstart, &bw->bwend, >)) {
54          //  bwend变量复用, 这个时间, bwend含义为, 理论开销时间 和 实际开销时间的差值, 既需要sleep的时间, 确保达到限速到指定的rate值
55          timersub(&bw->bwstart, &bw->bwend, &bw->bwend);
56 
57          //  如果差值达到了秒级, 则需要降低统计周期阈值, 确保统计相对精确
58           //  thresh变为原先的1/2, 但不能低于buflen的1/4
59           if (bw->bwend.tv_sec) {
60             bw->thresh /= 2;
61              if (bw->thresh < bw->buflen / 4)
62                 bw->thresh = bw->buflen / 4;
63         } 
64          //  如果差值小于10毫秒, 则需要加大统计周期阈值, 确保统计相对精确
65           //  thresh变为原先的2倍, 但不能高于buflen的8倍
66           else  if (bw->bwend.tv_usec < 10000) {
67             bw->thresh *= 2;
68              if (bw->thresh > bw->buflen * 8)
69                 bw->thresh = bw->buflen * 8;
70         }
71 
72          //  乖乖的睡一会吧, 以达到限速目的
73          TIMEVAL_TO_TIMESPEC(&bw->bwend, &ts);
74          while (nanosleep(&ts, &rm) == -1) {
75              if (errno != EINTR)
76                  break;
77             ts = rm;
78         }
79     }
80 
81      //  新的统计周期开始, 初始化lamt, bwstart变量
82      bw->lamt = 0;
83     gettimeofday(&bw->bwstart, NULL);
84 }

你可能感兴趣的:(SCP限速逻辑实现--带中文注释的bandwidth_limit函数)