SCP限速邏輯實(shí)現(xiàn)--帶中文注釋的bandwidth_limit函數(shù)
SCP限速邏輯實(shí)現(xiàn)--帶中文注釋的bandwidth_limit函數(shù)
SCP支持限速, 通過(guò)-l參數(shù), 指定拷貝的速度
-l limit
Limits the used bandwidth, specified in Kbit/s.
Limits the used bandwidth, specified in Kbit/s.
具體實(shí)現(xiàn), 是在misc.c中的bandwidth_limit函數(shù)
下面附上帶中文注釋的bandwidth_limit函數(shù)代碼
1 struct bwlimit {
2 size_t buflen; // 每次read的buf長(zhǎng)度
3 u_int64_t rate, thresh, lamt; // rate: 限速速率, 單位kpbs
4 // thresh:統(tǒng)計(jì)周期,read長(zhǎng)度到了指定閾值, 觸發(fā)限速統(tǒng)計(jì)
5 // lamt: 一次統(tǒng)計(jì)周期內(nèi), read了多少長(zhǎng)度
6 struct timeval bwstart, bwend; // bwstart: 統(tǒng)計(jì)周期之開(kāi)始時(shí)間
7 // bwend: 統(tǒng)計(jì)周期之結(jié)束時(shí)間
8 };
9
10 void bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen)
11 {
12 bw->buflen = buflen; // 初始化read buf長(zhǎng)度
13 bw->rate = kbps; // 初始化限速速率
14 bw->thresh = bw->rate; // 初始化統(tǒng)計(jì)周期
15 bw->lamt = 0; // 初始化當(dāng)前read長(zhǎng)度
16 timerclear(&bw->bwstart); // 初始化統(tǒng)計(jì)開(kāi)始時(shí)間
17 timerclear(&bw->bwend); // 初始化統(tǒng)計(jì)結(jié)束時(shí)間
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 // 設(shè)置統(tǒng)計(jì)開(kāi)始時(shí)間, 為當(dāng)前時(shí)間
26 if (!timerisset(&bw->bwstart)) {
27 gettimeofday(&bw->bwstart, NULL);
28 return;
29 }
30
31 // 設(shè)置當(dāng)前read長(zhǎng)度
32 bw->lamt += read_len;
33 // 判斷當(dāng)前read長(zhǎng)度是否到達(dá)統(tǒng)計(jì)周期的閾值
34 if (bw->lamt < bw->thresh)
35 return;
36
37 // 設(shè)置統(tǒng)計(jì)結(jié)束時(shí)間,為當(dāng)前時(shí)間
38 gettimeofday(&bw->bwend, NULL);
39 // bwend變量復(fù)用, 這個(gè)時(shí)候, bwend含義為, 本次統(tǒng)計(jì)周期實(shí)際開(kāi)銷(xiāo)的時(shí)間: 既read thresh長(zhǎng)度字節(jié),花了多少時(shí)間.
40 timersub(&bw->bwend, &bw->bwstart, &bw->bwend);
41 if (!timerisset(&bw->bwend))
42 return;
43
44 // 將單位從Byte變成bit
45 bw->lamt *= 8;
46 // 根據(jù)限速速率, 計(jì)算理論應(yīng)該花費(fèi)多少時(shí)間
47 waitlen = (double)1000000L * bw->lamt / bw->rate;
48 // bwstart變量復(fù)用, 這個(gè)時(shí)候, bwstart含義為, 本次統(tǒng)計(jì)周期理論開(kāi)銷(xiāo)的時(shí)間
49 bw->bwstart.tv_sec = waitlen / 1000000L;
50 bw->bwstart.tv_usec = waitlen % 1000000L;
51
52 // 如果理論開(kāi)銷(xiāo)時(shí)間 > 實(shí)際開(kāi)銷(xiāo)時(shí)間, 則需要做限速
53 if (timercmp(&bw->bwstart, &bw->bwend, >)) {
54 // bwend變量復(fù)用, 這個(gè)時(shí)間, bwend含義為, 理論開(kāi)銷(xiāo)時(shí)間 和 實(shí)際開(kāi)銷(xiāo)時(shí)間的差值, 既需要sleep的時(shí)間, 確保達(dá)到限速到指定的rate值
55 timersub(&bw->bwstart, &bw->bwend, &bw->bwend);
56
57 // 如果差值達(dá)到了秒級(jí), 則需要降低統(tǒng)計(jì)周期閾值, 確保統(tǒng)計(jì)相對(duì)精確
58 // thresh變?yōu)樵鹊?/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毫秒, 則需要加大統(tǒng)計(jì)周期閾值, 確保統(tǒng)計(jì)相對(duì)精確
65 // thresh變?yōu)樵鹊?倍, 但不能高于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 // 乖乖的睡一會(huì)吧, 以達(dá)到限速目的
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 // 新的統(tǒng)計(jì)周期開(kāi)始, 初始化lamt, bwstart變量
82 bw->lamt = 0;
83 gettimeofday(&bw->bwstart, NULL);
84 }
2 size_t buflen; // 每次read的buf長(zhǎng)度
3 u_int64_t rate, thresh, lamt; // rate: 限速速率, 單位kpbs
4 // thresh:統(tǒng)計(jì)周期,read長(zhǎng)度到了指定閾值, 觸發(fā)限速統(tǒng)計(jì)
5 // lamt: 一次統(tǒng)計(jì)周期內(nèi), read了多少長(zhǎng)度
6 struct timeval bwstart, bwend; // bwstart: 統(tǒng)計(jì)周期之開(kāi)始時(shí)間
7 // bwend: 統(tǒng)計(jì)周期之結(jié)束時(shí)間
8 };
9
10 void bandwidth_limit_init(struct bwlimit *bw, u_int64_t kbps, size_t buflen)
11 {
12 bw->buflen = buflen; // 初始化read buf長(zhǎng)度
13 bw->rate = kbps; // 初始化限速速率
14 bw->thresh = bw->rate; // 初始化統(tǒng)計(jì)周期
15 bw->lamt = 0; // 初始化當(dāng)前read長(zhǎng)度
16 timerclear(&bw->bwstart); // 初始化統(tǒng)計(jì)開(kāi)始時(shí)間
17 timerclear(&bw->bwend); // 初始化統(tǒng)計(jì)結(jié)束時(shí)間
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 // 設(shè)置統(tǒng)計(jì)開(kāi)始時(shí)間, 為當(dāng)前時(shí)間
26 if (!timerisset(&bw->bwstart)) {
27 gettimeofday(&bw->bwstart, NULL);
28 return;
29 }
30
31 // 設(shè)置當(dāng)前read長(zhǎng)度
32 bw->lamt += read_len;
33 // 判斷當(dāng)前read長(zhǎng)度是否到達(dá)統(tǒng)計(jì)周期的閾值
34 if (bw->lamt < bw->thresh)
35 return;
36
37 // 設(shè)置統(tǒng)計(jì)結(jié)束時(shí)間,為當(dāng)前時(shí)間
38 gettimeofday(&bw->bwend, NULL);
39 // bwend變量復(fù)用, 這個(gè)時(shí)候, bwend含義為, 本次統(tǒng)計(jì)周期實(shí)際開(kāi)銷(xiāo)的時(shí)間: 既read thresh長(zhǎng)度字節(jié),花了多少時(shí)間.
40 timersub(&bw->bwend, &bw->bwstart, &bw->bwend);
41 if (!timerisset(&bw->bwend))
42 return;
43
44 // 將單位從Byte變成bit
45 bw->lamt *= 8;
46 // 根據(jù)限速速率, 計(jì)算理論應(yīng)該花費(fèi)多少時(shí)間
47 waitlen = (double)1000000L * bw->lamt / bw->rate;
48 // bwstart變量復(fù)用, 這個(gè)時(shí)候, bwstart含義為, 本次統(tǒng)計(jì)周期理論開(kāi)銷(xiāo)的時(shí)間
49 bw->bwstart.tv_sec = waitlen / 1000000L;
50 bw->bwstart.tv_usec = waitlen % 1000000L;
51
52 // 如果理論開(kāi)銷(xiāo)時(shí)間 > 實(shí)際開(kāi)銷(xiāo)時(shí)間, 則需要做限速
53 if (timercmp(&bw->bwstart, &bw->bwend, >)) {
54 // bwend變量復(fù)用, 這個(gè)時(shí)間, bwend含義為, 理論開(kāi)銷(xiāo)時(shí)間 和 實(shí)際開(kāi)銷(xiāo)時(shí)間的差值, 既需要sleep的時(shí)間, 確保達(dá)到限速到指定的rate值
55 timersub(&bw->bwstart, &bw->bwend, &bw->bwend);
56
57 // 如果差值達(dá)到了秒級(jí), 則需要降低統(tǒng)計(jì)周期閾值, 確保統(tǒng)計(jì)相對(duì)精確
58 // thresh變?yōu)樵鹊?/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毫秒, 則需要加大統(tǒng)計(jì)周期閾值, 確保統(tǒng)計(jì)相對(duì)精確
65 // thresh變?yōu)樵鹊?倍, 但不能高于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 // 乖乖的睡一會(huì)吧, 以達(dá)到限速目的
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 // 新的統(tǒng)計(jì)周期開(kāi)始, 初始化lamt, bwstart變量
82 bw->lamt = 0;
83 gettimeofday(&bw->bwstart, NULL);
84 }
posted on 2014-09-22 17:45 stone2083 閱讀(2489) 評(píng)論(4) 編輯 收藏 所屬分類(lèi): c