- 浏览: 321837 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
JQ_AK47:
...
Linux下直接发送以太包 -
winsen2009:
谢谢分享,如果能再来一个列子就更好了,刚接触看完还是不懂的用
UNPv1_r3读书笔记: SCTP编程
本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,
严禁用于任何商业用途。
msn: yfydz_no1@hotmail.com
来源:http://yfydz.cublog.cn
严禁用于任何商业用途。
msn: yfydz_no1@hotmail.com
来源:http://yfydz.cublog.cn
5.2 FIFO FIFO算法在net/sched/sch_fifo.c中定义, 既可以单独使用, 也可以被其他流控算法(如TBF)作为内 部流控算法使用. 5.2.1 流控结构 FIFO分两种, 一种是PFIFO, 一种是BFIFO, 分别按包数和字节数进行FIFO的流量控制. // 私有数据结构, 就是流量参数 struct fifo_sched_data { u32 limit; }; // 包数流控 struct Qdisc_ops pfifo_qdisc_ops = { .id = "pfifo", .priv_size = sizeof(struct fifo_sched_data), .enqueue = pfifo_enqueue, .dequeue = qdisc_dequeue_head, .requeue = qdisc_requeue, .drop = qdisc_queue_drop, .init = fifo_init, .reset = qdisc_reset_queue, .change = fifo_init, .dump = fifo_dump, .owner = THIS_MODULE, }; // 字节数流控 struct Qdisc_ops bfifo_qdisc_ops = { .id = "bfifo", .priv_size = sizeof(struct fifo_sched_data), .enqueue = bfifo_enqueue, .dequeue = qdisc_dequeue_head, .requeue = qdisc_requeue, .drop = qdisc_queue_drop, .init = fifo_init, .reset = qdisc_reset_queue, .change = fifo_init, .dump = fifo_dump, .owner = THIS_MODULE, }; 在这两个结构中, 处理enqueue, init, reset, dump外, 其他操作函数都是用流控缺省操作函数. 5.2.2 初始化 static int fifo_init(struct Qdisc *sch, struct rtattr *opt) { // FIFO私有数据 struct fifo_sched_data *q = qdisc_priv(sch); if (opt == NULL) { // 如果没提供流量参数情况 // limit缺省取网卡的发送队列长度, 而且至少为1 u32 limit = sch->dev->tx_queue_len ? : 1; // 如果是字节流控, 用的是队列长度*MTU作为限制值 if (sch->ops == &bfifo_qdisc_ops) limit *= sch->dev->mtu; // 如果是包流控, 直接用队列长度作为限制值 q->limit = limit; } else { // 提供合法流量参数时用提供的流控值作为流控限制参数 struct tc_fifo_qopt *ctl = RTA_DATA(opt); if (RTA_PAYLOAD(opt) < sizeof(*ctl)) return -EINVAL; q->limit = ctl->limit; } return 0; } 5.2.3 入队 // 字节流控入队 static int bfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct fifo_sched_data *q = qdisc_priv(sch); // 如果当前队列数据总长加数据包长度不超过限制值, 将数据包添加到队列尾 if (likely(sch->qstats.backlog + skb->len <= q->limit)) return qdisc_enqueue_tail(skb, sch); return qdisc_reshape_fail(skb, sch); } // 包数流控入队 static int pfifo_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct fifo_sched_data *q = qdisc_priv(sch); // 如果缓存队列数据包数小于限制值, 将数据包添加到队列尾 if (likely(skb_queue_len(&sch->q) < q->limit)) return qdisc_enqueue_tail(skb, sch); return qdisc_reshape_fail(skb, sch); } 5.2.4 输出 // 就是将私有数据limit作为参数返回, 用的应该是netlink套接口 static int fifo_dump(struct Qdisc *sch, struct sk_buff *skb) { struct fifo_sched_data *q = qdisc_priv(sch); struct tc_fifo_qopt opt = { .limit = q->limit }; RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); return skb->len; rtattr_failure: return -1; } 5.3 TBF(Token Bucket Filter queue, 令牌桶过滤队列) TBF算法是一种限制流量算法,基本原理是将入队的数据包缓存在队列中,同时按指定的速度产生令 牌,只有拥有令牌才能数据包出队,这样就控制了出口流量,目前netfilter中的limit匹配实际也是 用TBF算法, 该算法在net/sched/sch_tbf.c中定义,在该文件的注释中定义的算法如下: /* Description. ------------ A data flow obeys TBF with rate R and depth B, if for any time interval t_i...t_f the number of transmitted bits does not exceed B + R*(t_f-t_i). Packetized version of this definition: The sequence of packets of sizes s_i served at moments t_i obeys TBF, if for any i<=k: s_i+....+s_k <= B + R*(t_k - t_i) Algorithm. ---------- Let N(t_i) be B/R initially and N(t) grow continuously with time as: N(t+delta) = min{B/R, N(t) + delta} If the first packet in queue has length S, it may be transmitted only at the time t_* when S/R <= N(t_*), and in this case N(t) jumps: N(t_* + 0) = N(t_* - 0) - S/R. Actually, QoS requires two TBF to be applied to a data stream. One of them controls steady state burst size, another one with rate P (peak rate) and depth M (equal to link MTU) limits bursts at a smaller time scale. It is easy to see that P>R, and B>M. If P is infinity, this double TBF is equivalent to a single one. When TBF works in reshaping mode, latency is estimated as: lat = max ((L-B)/R, (L-M)/P) */ 5.3.1 操作结构定义 // TBF属性结构 struct tc_tbf_qopt { // 速率 struct tc_ratespec rate; // 峰值速率 struct tc_ratespec peakrate; // 限制值 __u32 limit; // 缓冲区大小 __u32 buffer; // MTU参数 __u32 mtu; }; // TBF算法私有数据结构, 这个结构让人想起limit匹配结构, 也是分两部分, 固定参数和可变参数 struct tbf_sched_data { /* Parameters */ // 以下是固定参数 // 流量限制值 u32 limit; /* Maximal length of backlog: bytes */ // 桶深, 也就是缓冲区大小 u32 buffer; /* Token bucket depth/rate: MUST BE >= MTU/B */ // 网卡MTU u32 mtu; // 允许的最大包长 u32 max_size; struct qdisc_rate_table *R_tab; struct qdisc_rate_table *P_tab; /* Variables */ // 以下是变化数据, 在每次算法计算时会发生改变 // B型token的数量 long tokens; /* Current number of B tokens */ // P型token的数量 long ptokens; /* Current number of P tokens */ // 时间 psched_time_t t_c; /* Time check-point */ // 定时器 struct timer_list wd_timer; /* Watchdog timer */ // 内部流控结构, 缺省使用bfifo struct Qdisc *qdisc; /* Inner qdisc, default - bfifo queue */ }; // TBF流控算法操作结构 static struct Qdisc_ops tbf_qdisc_ops = { .next = NULL, .cl_ops = &tbf_class_ops, .id = "tbf", .priv_size = sizeof(struct tbf_sched_data), .enqueue = tbf_enqueue, .dequeue = tbf_dequeue, .requeue = tbf_requeue, .drop = tbf_drop, .init = tbf_init, .reset = tbf_reset, .destroy = tbf_destroy, .change = tbf_change, .dump = tbf_dump, .owner = THIS_MODULE, }; // TBF类别操作结构 static struct Qdisc_class_ops tbf_class_ops = { .graft = tbf_graft, .leaf = tbf_leaf, .get = tbf_get, .put = tbf_put, .change = tbf_change_class, .delete = tbf_delete, .walk = tbf_walk, .tcf_chain = tbf_find_tcf, .dump = tbf_dump_class, }; 5.3.2 初始化 static int tbf_init(struct Qdisc* sch, struct rtattr *opt) { // TBF私有数据 struct tbf_sched_data *q = qdisc_priv(sch); if (opt == NULL) return -EINVAL; // 获取当前实际 PSCHED_GET_TIME(q->t_c); // 初始化定时器 init_timer(&q->wd_timer); // 定时函数 q->wd_timer.function = tbf_watchdog; // 数据就是流控结构本身 q->wd_timer.data = (unsigned long)sch; // 内部流控初始化为noop_qdisc q->qdisc = &noop_qdisc; // 调用tbf_change设置TBF流控结构参数 return tbf_change(sch, opt); } // 定时器函数, 功能就是清除阻塞标识, 让网卡重新调度 static void tbf_watchdog(unsigned long arg) { struct Qdisc *sch = (struct Qdisc*)arg; // 清除阻塞标志 sch->flags &= ~TCQ_F_THROTTLED; // 重新进行网卡调度 netif_schedule(sch->dev); } 5.3.3 入队 // TBF是根据数据包长度而不是个数来进行流控的, 缺省内部流控结构是bfifo static int tbf_enqueue(struct sk_buff *skb, struct Qdisc* sch) { // TBF私有数据 struct tbf_sched_data *q = qdisc_priv(sch); int ret; // 如果数据包长度超过TBF允许最大长度, 丢包 if (skb->len > q->max_size) { sch->qstats.drops++; #ifdef CONFIG_NET_CLS_POLICE if (sch->reshape_fail == NULL || sch->reshape_fail(skb, sch)) #endif kfree_skb(skb); return NET_XMIT_DROP; } // 调用内部流控结构的入队操作, 失败丢包 if ((ret = q->qdisc->enqueue(skb, q->qdisc)) != 0) { sch->qstats.drops++; return ret; } // 入队成功增加相关统计量 sch->q.qlen++; sch->bstats.bytes += skb->len; sch->bstats.packets++; return 0; } // 重入队操作 static int tbf_requeue(struct sk_buff *skb, struct Qdisc* sch) { // TBF私有数据 struct tbf_sched_data *q = qdisc_priv(sch); int ret; // 调用内部流控结构的重入队操作, 成功则增加统计计数 if ((ret = q->qdisc->ops->requeue(skb, q->qdisc)) == 0) { sch->q.qlen++; sch->qstats.requeues++; } return ret; } 5.3.4 出队 // 长度转换为相应大小的令牌数 #define L2T(q,L) ((q)->R_tab->data[(L)>>(q)->R_tab->rate.cell_log]) // 长度转换为相应大小的P令牌数 #define L2T_P(q,L) ((q)->P_tab->data[(L)>>(q)->P_tab->rate.cell_log]) static struct sk_buff *tbf_dequeue(struct Qdisc* sch) { struct tbf_sched_data *q = qdisc_priv(sch); struct sk_buff *skb; // 调用内部流控结构的出队函数, 对于BFIFO来说就是直接取队列头的那个数据包 skb = q->qdisc->dequeue(q->qdisc); if (skb) { // 取到数据包的情况 psched_time_t now; long toks, delay; long ptoks = 0; // 长度初始化为数据包长度 unsigned int len = skb->len; // 获取当前时间 PSCHED_GET_TIME(now); // 根据当前时间和上次流控计算时间的时间差来计算可用的令牌量 toks = PSCHED_TDIFF_SAFE(now, q->t_c, q->buffer); // 如果也按包数流控 if (q->P_tab) { // 计算当前可用的P令牌数: 当前P令牌数加新增令牌量 ptoks = toks + q->ptokens; // 如果超过了MTU值, 限制为MTU if (ptoks > (long)q->mtu) ptoks = q->mtu; // 当前可用P令牌数减去当前数据包长度对应的P令牌量 ptoks -= L2T_P(q, len); } // 再加上原来已经有的令牌量 toks += q->tokens; // 如果令牌量超过了全部缓冲区大小, 限制为缓冲区大小 if (toks > (long)q->buffer) toks = q->buffer; // 当前令牌量减去当前数据包长度对应的令牌量 toks -= L2T(q, len); // 如果当前令牌量大于0, 表示桶中的令牌量允许发送该数据包 if ((toks|ptoks) >= 0) { // 更新流控时间 q->t_c = now; // 更新当前令牌数 q->tokens = toks; // 更新P令牌数 q->ptokens = ptoks; // 队列长度减 sch->q.qlen--; // 此时没阻塞 sch->flags &= ~TCQ_F_THROTTLED; // 返回数据包 return skb; } // 现在是令牌数不够, 说明要发送的数据量超过了限制值, 发生了阻塞 // 计算延迟时间值 delay = PSCHED_US2JIFFIE(max_t(long, -toks, -ptoks)); // 至少定时一个时间片 if (delay == 0) delay = 1; // 修改定时器的定时时间 mod_timer(&q->wd_timer, jiffies+delay); /* Maybe we have a shorter packet in the queue, which can be sent now. It sounds cool, but, however, this is wrong in principle. We MUST NOT reorder packets under these circumstances. Really, if we split the flow into independent subflows, it would be a very good solution. This is the main idea of all FQ algorithms (cf. CSZ, HPFQ, HFSC) */ // 将数据包重新入队等待发送 if (q->qdisc->ops->requeue(skb, q->qdisc) != NET_XMIT_SUCCESS) { /* When requeue fails skb is dropped */ sch->q.qlen--; sch->qstats.drops++; } // 设置阻塞标识 sch->flags |= TCQ_F_THROTTLED; sch->qstats.overlimits++; } return NULL; } 5.3.5 丢包 static unsigned int tbf_drop(struct Qdisc* sch) { struct tbf_sched_data *q = qdisc_priv(sch); unsigned int len = 0; // 就是调用内部流控结构的类别操作结构中的丢包操作函数 if (q->qdisc->ops->drop && (len = q->qdisc->ops->drop(q->qdisc)) != 0) { sch->q.qlen--; sch->qstats.drops++; } return len; } 5.3.6 复位 static void tbf_reset(struct Qdisc* sch) { struct tbf_sched_data *q = qdisc_priv(sch); // 调用内部流控结构的复位函数 qdisc_reset(q->qdisc); // 复位TBF流控结构参数 // 清空队列长度 sch->q.qlen = 0; // 获取当前时间 PSCHED_GET_TIME(q->t_c); // B令牌数为缓冲区大小 q->tokens = q->buffer; // P令牌数为MTU值 q->ptokens = q->mtu; // 清除被阻塞标志 sch->flags &= ~TCQ_F_THROTTLED; // 删除定时器 del_timer(&q->wd_timer); } 5.3.7 生成内部流控结构 static struct Qdisc *tbf_create_dflt_qdisc(struct net_device *dev, u32 limit) { // 分配一个bfifo的流控结构 struct Qdisc *q = qdisc_create_dflt(dev, &bfifo_qdisc_ops); struct rtattr *rta; int ret; if (q) { // 分配动态流控参数空间,不知道为什么不直接用静态结构而用动态分配的, 该结构也不大 rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); if (rta) { // 设置该流控的属性, 也就是BFIFO中的流控限制值的大小 // bfifo的change函数实际就是init函数 rta->rta_type = RTM_NEWQDISC; rta->rta_len = RTA_LENGTH(sizeof(struct tc_fifo_qopt)); ((struct tc_fifo_qopt *)RTA_DATA(rta))->limit = limit; ret = q->ops->change(q, rta); kfree(rta); if (ret == 0) return q; } qdisc_destroy(q); } return NULL; } 5.3.8 更新控制参数 // 根据opt参数设置TBF流控结构私有参数 static int tbf_change(struct Qdisc* sch, struct rtattr *opt) { int err = -EINVAL; // TBF私有数据 struct tbf_sched_data *q = qdisc_priv(sch); // 属性表, TCA_TBF_PTAB=3 struct rtattr *tb[TCA_TBF_PTAB]; // TBF属性结构参数 struct tc_tbf_qopt *qopt; struct qdisc_rate_table *rtab = NULL; struct qdisc_rate_table *ptab = NULL; struct Qdisc *child = NULL; int max_size,n; // 解析rtattr结构属性值 if (rtattr_parse_nested(tb, TCA_TBF_PTAB, opt) || tb[TCA_TBF_PARMS-1] == NULL || RTA_PAYLOAD(tb[TCA_TBF_PARMS-1]) < sizeof(*qopt)) goto done; // 数据转换为具体的属性参数结构指针 qopt = RTA_DATA(tb[TCA_TBF_PARMS-1]); // 根据新流量速率表参数生成新节点返回(系统流量速率链表为空)或 // 拷贝到当前流量速率表链表的头节点返回流量速率表节点 rtab = qdisc_get_rtab(&qopt->rate, tb[TCA_TBF_RTAB-1]); if (rtab == NULL) goto done; // 如果设置了峰值速率 if (qopt->peakrate.rate) { // 如果峰值速率大于规定速率, 新生成峰值速率节点 if (qopt->peakrate.rate > qopt->rate.rate) ptab = qdisc_get_rtab(&qopt->peakrate, tb[TCA_TBF_PTAB-1]); if (ptab == NULL) goto done; } // 找一个大于限制值的数组项 for (n = 0; n < 256; n++) if (rtab->data[n] > qopt->buffer) break; // 计算最大数据包长度 max_size = (n << qopt->rate.cell_log)-1; if (ptab) { // 如果峰值速率控制非空 int size; // 计算峰值速率发送下的最大数据包长度 for (n = 0; n < 256; n++) if (ptab->data[n] > qopt->mtu) break; size = (n << qopt->peakrate.cell_log)-1; if (size < max_size) max_size = size; } // 计算出来的最大值小于0, 返回错误 if (max_size < 0) goto done; if (qopt->limit > 0) { // 根据流量限制值生成内部BFIFO流控结构 if ((child = tbf_create_dflt_qdisc(sch->dev, qopt->limit)) == NULL) goto done; } sch_tree_lock(sch); if (child) qdisc_destroy(xchg(&q->qdisc, child)); // 填充TBF流控私有结构参数 q->limit = qopt->limit; q->mtu = qopt->mtu; q->max_size = max_size; q->buffer = qopt->buffer; q->tokens = q->buffer; q->ptokens = q->mtu; rtab = xchg(&q->R_tab, rtab); ptab = xchg(&q->P_tab, ptab); sch_tree_unlock(sch); err = 0; done: if (rtab) qdisc_put_rtab(rtab); if (ptab) qdisc_put_rtab(ptab); return err; } 5.3.9 释放 static void tbf_destroy(struct Qdisc *sch) { struct tbf_sched_data *q = qdisc_priv(sch); // 删除定时器 del_timer(&q->wd_timer); // 释放P,R流控速率控制表结构 if (q->P_tab) qdisc_put_rtab(q->P_tab); if (q->R_tab) qdisc_put_rtab(q->R_tab); // 释放流控结构 qdisc_destroy(q->qdisc); } 5.3.10 输出 static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) { struct tbf_sched_data *q = qdisc_priv(sch); // 数据包的数据尾用来存储流控参数 unsigned char *b = skb->tail; struct rtattr *rta; // TBF选项结构 struct tc_tbf_qopt opt; // 数据包的数据尾定义为rtattr结构 rta = (struct rtattr*)b; // 扩展数据包数据长度 RTA_PUT(skb, TCA_OPTIONS, 0, NULL); // 填充TBF选项结构: 限制值和当前P, R速率值, MTU, 缓冲区大小 opt.limit = q->limit; opt.rate = q->R_tab->rate; if (q->P_tab) opt.peakrate = q->P_tab->rate; else memset(&opt.peakrate, 0, sizeof(opt.peakrate)); opt.mtu = q->mtu; opt.buffer = q->buffer; // 拷贝到skb中 RTA_PUT(skb, TCA_TBF_PARMS, sizeof(opt), &opt); // 属性数据长度 rta->rta_len = skb->tail - b; // 返回数据总长 return skb->len; rtattr_failure: skb_trim(skb, b - skb->data); return -1; } // 输出类别结构 static int tbf_dump_class(struct Qdisc *sch, unsigned long cl, struct sk_buff *skb, struct tcmsg *tcm) { struct tbf_sched_data *q = qdisc_priv(sch); // 只有一个类别, 返回失败 if (cl != 1) /* only one class */ return -ENOENT; // 填充TCMSG结构 tcm->tcm_handle |= TC_H_MIN(1); tcm->tcm_info = q->qdisc->handle; return 0; } ...... 待续 ...... 发表于: 2007-07-29,修改于: 2007-07-29 15:29,已浏览3828次,有评论10条 推荐 投诉 网友: 本站网友 时间:2007-08-17 14:56:55 IP地址:222.68.182.★ tbf_dequeue这个函数没看太懂,想请教一下: 1. R_tab和P_tab是什么关系?分别代表什么意思? 2. 这一段程序是什么意思?能否更详细解释一下?谢谢 if (q->P_tab) { ptoks = toks + q->ptokens; if (ptoks > (long)q->mtu) ptoks = q->mtu; ptoks -= L2T_P(q, len); } 3. 这个数据结构struct tbf_sched_data中的mtu究竟是什么意思?起什么作用呢? 谢谢了 网友: yfydz 时间:2007-08-18 12:06:10 IP地址:123.116.100.★ 1. R_tab和P_tab是用于流控计算的,一个根据长度计算令牌数,一个根据包数计算流控, 2. 计算P令牌 3.MTU是在包数流控时作为最大包数限制 网友: 本站网友 时间:2007-08-20 10:18:34 IP地址:222.68.182.★ 可是MTU不是指最大传输单元吗?应该是指一个数据包在当前链路上的最大字节数。它怎么能用来表示包流控时的最大包数限制?就是这里不太明白 网友: 本站网友 时间:2007-08-21 08:45:20 IP地址:60.191.4.★ //普通令牌桶表R_tab; //峰值令牌桶表P_tab: mtu指最打传输峰值 if (q->P_tab) { //有峰值速率限制 ptoks = toks + q->ptokens;//总峰值令牌数 if (ptoks > (long)q->mtu) ptoks = q->mtu;//不能超过峰值令牌桶容量 ptoks -= L2T_P(q, skb->len);//本包消耗的峰值令牌数 } toks += q->tokens;//累计普通令牌数 if (toks > (long)q->buffer) toks = q->buffer;//不能超过普通令牌桶容量 toks -= L2T(q, skb->len);//本包消耗的普通令牌数 网友: 本站网友 时间:2007-08-21 11:21:39 IP地址:222.68.182.★ 谢谢。不过峰值令牌为什么要用MTU来度量呢?两个从道理上似乎没什么关系。 网友: 本站网友 时间:2007-10-12 15:18:26 IP地址:222.64.17.★ 强烈的顶顶顶!!! 15G空间=5个网站=500元/年 可免费试用 www.abcnic.com QQ:1012727 5GB 独立WEB空间、5GB 企业邮箱空间、5GB MSSQL数据库 IIS连接数据 500 个、500GB/月流量、共享日志文件空间 数据库功能 支持5GB MSSQL数据库空间,5个用户数据库、Access 主机功能支持 采用安全稳定的Win2003 .net2.0 架构 支持ASP、PHP、ASP.NET、PERL等脚本、支持自定义CGI 全面支持.net2.0版本,独立的Application应用池, 支持SSI(Shtml),支持FrontPage扩展 可免费自行绑定5个域名、500个解析、500个子域名 企业邮箱功能 赠送5GB 超大企业邮箱,500个Email企业邮箱用户 自动回复、自动转发、POP3、SMTP收发信、SMTP发信认证 邮件过滤、邮件拒收、邮件夹管理、邮件域管理、定制邮件数 网友: dreamagean 时间:2009-03-24 20:38:37 IP地址:219.238.94.★ 请您讲一下L2T函数的实现? 看了好长时间不能理解。 谢谢! 网友: dreamagean 时间:2009-03-25 09:13:49 IP地址:114.255.20.★ 请大牛解释一下! 网友: 本站网友 时间:2009-09-01 10:26:06 IP地址:219.143.137.★ l2t用来算btoken数 qdisc_rate_table里面的data数组记录令牌数 (q)->R_tab->data[(L)>>(q)->R_tab->rate.cell_log]这一句就是去找由L和q决定的令牌数 计算当前令牌量是通过时间和缓冲长度来完成 toks = PSCHED_TDIFF_SAFE(now, q->t_c, q->buffer); 网友: allen 时间:2010-05-24 14:34:36 IP地址:210.3.50.★ #define PSCHED_GET_TIME(stamp) ((stamp) = (get_jiffies_64()<<PSCHED_JSCALE)) 请问下这里的PSCHED_JSCALE的含义是什么?以及通过proc提供给user space用的psched_tick_per_us, psched_us_per_tick的含义?
发表评论
-
Linux内核中流量控制(24)
2011-01-10 16:33 2245本文档的Copyleft归yfydz所 ... -
Linux内核中流量控制(23)
2011-01-10 16:30 1532本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(22)
2011-01-10 16:29 1980本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(21)
2011-01-10 16:28 1401本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(20)
2011-01-10 16:27 1567本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(19)
2011-01-10 16:27 2022本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(18)
2011-01-10 16:26 1616Linux内核中流量控制(18) ... -
Linux内核中流量控制(17)
2011-01-10 16:25 1991本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(16)
2011-01-10 16:25 1849本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(15)
2011-01-10 16:24 1979本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(14)
2011-01-10 16:23 2001本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(13)
2011-01-10 16:22 2686本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(12)
2011-01-10 16:21 2166本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(11)
2011-01-10 16:21 3289本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(10)
2011-01-10 16:20 2040本文档的Copyleft归yfydz所 ... -
Linux内核中流量控制(9)
2011-01-10 16:19 1876本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(8)
2011-01-10 16:18 1544本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(7)
2011-01-10 16:18 2973本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(6)
2011-01-10 16:17 1539本文档的Copyleft归yfydz所有,使用GPL发布,可以 ... -
Linux内核中流量控制(5)
2011-01-10 16:16 1767本文档的Copyleft归yfydz所有,使用GPL发布,可以 ...
相关推荐
在Linux内核中,TCP和UDP模块处理连接建立、数据传输、流量控制和拥塞控制等问题。 5. **应用层**:这一层包含各种应用协议,如HTTP、FTP、SMTP等,它们直接与用户交互。Linux内核通过socket API为上层应用提供了与...
【基于Linux内核的BT流量控制的原理与实现】 Linux操作系统以其开源、可定制的特点,在系统开发领域广泛应用,尤其在网络流量控制方面具有显著优势。针对BitTorrent(BT)这种大量占用带宽的P2P协议,Linux内核提供...
4. **网络堆栈**:从硬件接口到应用层协议的整个网络传输流程,如TCP/IP协议族、套接字API、网络设备驱动程序以及流量控制策略。 5. **设备驱动**:内核如何与硬件交互,驱动程序的工作原理,包括字符设备、块设备...
通过分析源码,我们可以了解到数据包的接收与发送过程,理解TCP连接的建立与断开、拥塞控制、流量控制等机制,这对于网络编程和网络故障排查非常有帮助。 此外,Linux内核还涉及中断处理、设备驱动、I/O管理等多个...
【基于Linux内核扩展模块的P2P流量控制】这篇文献主要探讨了如何在Linux操作系统中,通过内核扩展模块来实现对P2P流量的有效控制。P2P(Peer-to-Peer)技术的兴起改变了互联网的中心化结构,使得资源分享更为便捷,...
基于Linux内核扩展模块的P2P流量控制
基于LQL库的流量控制方法可以直接在Linux内核的框架下实现,而不需要使用传统方法中的TC命令解析、netlink传输和内核空间执行的三层结构。这可以提高流量控制的效率和可靠性,同时也可以减少流量控制的延迟和资源...
书中的内容涵盖了从内核基础到高级技术的方方面面,为那些希望提升Linux内核理解和开发能力的读者提供了宝贵的资源。在本文中,我们将探讨几个关键的知识点,包括Linux内核的基本结构、进程管理、内存管理和设备驱动...
2.6.24版本在网络方面加强了IPv6的支持,并改进了网络流量控制算法。 6. **安全与权限管理**:Linux内核采用了用户和组的概念,通过权限系统(如chmod、chown等)来控制文件访问。此外,还有SELinux(Security-...
接着,作者深入剖析了网络设备数据结构net_device,它包含了设备的配置信息、统计信息、状态标志以及各种管理列表和流量控制字段,这些细节揭示了网络设备如何在内核中被抽象和管理。 通过以上内容,我们可以看到,...
3. **文件系统**:文件系统是Linux内核中用于组织和管理磁盘上数据的重要组成部分。它支持多种文件系统类型,如EXT4、XFS、Btrfs等,并实现了VFS(虚拟文件系统)层,为各种不同的文件系统提供统一的接口。 4. **...
在Linux操作系统中,高级路由和流量控制是网络管理员和系统管理员必须掌握的关键技能。这篇文档“Linux高级路由和流量控制HOWTO中文版”由牛老师翻译,为读者提供了深入理解这些概念的宝贵资源。以下是对其中核心...
该模型内置于Linux内核中,并利用队列算法对不同服务质量(Quality of Service, QoS)需求的数据流进行分类,以提供灵活且差异化的服务。实验结果表明,采用该流量控制模型后,网络性能显著提高,并能很好地适应未来...
同时,还会讨论TCP的流量控制和拥塞控制机制,如滑动窗口、慢启动、快速重传和快速恢复算法等,这些都是保证网络通信质量和效率的关键。 其次,关于IP协议,书里会涉及IP地址、子网掩码、路由选择等概念,以及IP分...
TC 工具基于 Linux 内核的网络设备驱动程序,通过对网络设备的控制,来实现流量控制。TC 的工作原理可以分为以下三个阶段: 1. 流量控制方式:TC 提供了多种流量控制方式,包括 Token Bucket Filter(TBF)、...
TC(Linux 下流量控制工具)详细说明及应用实例 TC 是 Linux 下的一种流量控制工具,用于控制和管理网络流量。它提供了一个灵活的方式来管理网络带宽、延迟和丢包率等网络性能参数,以满足不同应用场景的需求。 TC...
3. **套接字接口**:Linux内核提供了一套标准的API,即套接字接口,供用户空间应用程序进行网络通信。通过socket()、bind()、listen()、connect()、accept()、send()和recv()等函数,程序员可以方便地创建和管理网络...
在 TCP/IP 四层协议的运用中,其能够通过建立虚链接的方式确认数据报文,还能够通过流量控制的方式保证 VMDump 网络 Linux 内核崩溃转储系统的可靠运行。 基于网络的 Linux 内核崩溃转储机制是 Linux 操作系统 的一...