美文网首页
协议栈纪要

协议栈纪要

作者: Yihulee | 来源:发表于2017-05-03 15:50 被阅读35次

5月27日

基本上,我想要的功能都已经完成了,接下来需要做的事情就是修修补补.还有,需要写博文记录一下到底干了什么以及怎么去干.

5月24日

c语言最让人头疼的事情是指针,真的,一旦指针出了一点儿故障,你都找不到原因.我跟你说.

今天的问题最终还是解决了,原因很简单,是我的指针越界了,然后我往越界的地方写入了一点东西,今天这个玩意折腾了我一个下午.郁闷.

5月21日

现在已经基本上对这部分代码非常熟悉了,所以修改起来也得心应手,很爽.

5月20日

昨天一天改了很多代码,添加了很多代码,删除了很多代码,总之关于tcp部分的工作已经做得差不多了.我觉得努力一把,在5月底的时候完成这个简陋的该死的协议栈,还是有望的.

5月16日

最近突然有一项任务要完成,抽不出太多时间来弄协议栈啦,所以,协议栈的事情可能要延迟了,应该不会超过一个月吧,一个月后,我会继续来干的.

5月14日

造一个轮子代价昂贵,我太想吐槽这一点了,直到今天,我感觉还有非常多的事情要干,不知道一个简单的协议栈什么时候才能搞得完.

5月12日

今天改进和精简了一点代码,发现要实现一个简易的posix标准的网络函数,如bind, accept,listen等,还有一大段代码要写,而这,真是乐趣之所在,鬼知道还有多久能够弄完这个协议栈,不过,在读协议栈的实现和精简协议栈的过程中,unp的不少内容,现在已经能够读懂了,记住,是真正懂了,原来unp上一些东西我压根就不知道在讲什么,包括那些高级的部分.

5月9日

拨开云雾见青天.终于调试正确了,tap设备正常工作.今天是非常非常重要的一天,因为今天终于将苦大仇深的代码调试成功了.

5月8日

最近被tun/tap这个概念折磨得很惨,使用百度搜索了一下这个玩意,没有一篇文章将这个东西完全讲清楚了,自己对着书,对着自己的想法,鼓捣了很久,依旧不得法,我接近放弃的时候,明智地用了一下谷歌搜索,很幸运,搜到了几篇文章,将tun/tap这个概念讲清楚了,接下来的事情就好办了.

5月6日

流年不利,我发现用tun/tap实现协议栈,貌似没有很好的调试方法,特别蛋疼.或许是我还没有找到一种好的调试办法吧,今天尝试了很多,试图让实现的这个协议栈连接上外网,但是失败了,老是失败,我要重新理解一下,到底什么才是tun/tap.

大概能花在这个协议栈上的时间,只能有1个月啦,6月份开始,要立马刷题了.希望最近几天能够找到一种好的方法来将它调试成功.

5月5日

废了好大的劲,终于将昨天那个malloc,free的问题给解决了.这里我稍微记录一下思路,以便给将来引以为戒.

昨天遇到的问题是,一旦我使用malloc,然后调用free,类似于这样:

void *address = malloc(42);
free(address);  // 代码没有任何问题

立马就报类似于这样的错误,同时程序立马崩溃:

free(): invalid next size (fast):

是不是非常诡异,我昨天调试了一个晚上,愣是没有找出原因,今天想了一点小办法,终于干掉了这个bug.

事实上,上面的代码并没有错,真正的错误原因在于,我在调用上面的代码之前,已经在别的地方用malloc分配了一块内存,然后一不小心,在操纵这块内存的时候,往越界的地址写入了一些数据,此后,我调用malloc不会出问题,但是调用free有很大的几率程序会立即崩溃掉,同时会爆出上面的错误.

个人怀疑是我越界写入的那些数据覆盖了malloc分配内存时记录的一些关于内存块大小的信息,使得调用free的时候无法找到这些信息,也就无从回收内存,导致出错.八九不离十啦.

我这里试图还原一下当时的场景:

#define ETH_HDR_LEN 10
#define IP_HDR_LEN 20
#define TCP_HDR_LEN 20

struct sk_buff {
    ...
    uint32_t dlen;          // 数据的大小,不包含头部(以太网,ip,tcp头部)
    uint8_t *end;
    uint8_t *head;
    uint8_t *data;
    uint8_t *payload;
};

// skb_reserve丢弃掉前len个数据,或者说是保留前面长度为len的数据
void *
skb_reserve(struct sk_buff *skb, unsigned int len)
{
    skb->data += len;
    return skb->data;
}


void 
free_skb(struct sk_buff *skb)
{
    free(skb->head);
    free(skb);
}

struct sk_buff *
alloc_skb(unsigned int size)
{
    struct sk_buff *skb = malloc(sizeof(struct sk_buff));
    memset(skb, 0, sizeof(struct sk_buff));
    skb->data = malloc(size);    // 记录下数据
    memset(skb->data, 0, size);

    skb->refcnt = 0;
    skb->head = skb->data;       // 数据开始的地方
    skb->end = skb->data + size; // 数据结束的地方
    list_init(&skb->list);
    return skb;
}

static struct sk_buff *
tcp_alloc_skb(int optlen, int size)
{
    // optlen表示tcp首部选项的大小
    // 这里要特别注意一下,因为忘记了TCP_HDR_LEN导致出错
    // ===============================================
    int reserved = ETH_HDR_LEN + IP_HDR_LEN + /*TCP_HDR_LEN +*/ optlen + size; // 如果这里丢了一个TCP_HDR_LEN
    struct sk_buff *skb = alloc_skb(reserved);

    skb_reserve(skb, reserved); // skb->data部分留出reserved个字节
    skb->dlen = size;   // dlen表示数据的大小
    return skb;
}

void manipulate()
{
    struct sk_buff *skb = tcp_alloc_skb(0, 0);
    // 因为optlen和size都为0
    // 用一个tcphdr的结构的指针tcp获取skb中的tcp头部部分,并填入数据,其实在这里就越界了.
    ...
    // 用一个iphdr的结构的指针ip获取skb中关于ip头部部分,填入数据
    ...
    // 用一个ethhdr结构的指针eth获取skb中关于以太网头部部分,填入数据
    // 用一副示意图表示如下,其实在第一步,tcp就指向了不属于自己的内存的首部,对其进行填充之后
    // 当时没有任何问题,但是到了free_skb的时候,立马出错,我怀疑malloc函数将内存块的信息恰好填
    // 入到了tcphdr那一部分
    /*
            |-------------------|   <--- skb->head, eth
            |     ethhdr       |
            |-------------------|   <--- iphdr, ip  
            |     iphdr     |       
            |                  |
            |-------------------|   <--- skb->end, tcp
            |     tcphdr       |     bad memory 
            |                  |    
    */
    
    free_skb(skb); // 立马出错,因为在不属于你的内存部分写入了数据
}

上面的问题看似很简单,或许你会拍一拍胸膛,我绝对不会犯这种错误,但是真的当代码多了之后,估计你就不会说这样的话了,如果尝试过调试了7,8个小时,连bug的半点头绪都找不到这种绝望的话,估计你也会说--c语言呀,指针这个东西,真的需要特别小心.

5月4日

原来没有想到的一个问题是,应用程序究竟是如何同协议栈进行交流的,现在明白了,使用的是IPC机制,从昨天一直到现在,终于将unix本机通信的程序调通了.接下来就只要将三次握手调试成功就差不多了.

妈蛋,c语言的内存分配真是个大问题,调了半天不知道错在哪里,先malloc,然后free,立马出错,这玩意和玄学差不多.

5月3日

学习网络编程最好的方式,的确是摸透一个TCP IP协议栈的实现.读level-ip,结合tcp ip详解卷,再配合上手实验,个人感觉收获非常大,毕竟看到了抽象背后的东西.

越是读源代码实现,我越是觉得,真正要在linux做系统编程的话,对操作系统原理的理解是必不可少的,最好的操作系统教程,不是书本,而是源码.当然,书本比不可少,它记录了一些原理性的东西,但是源码会使我们对一些东西明白得更加透彻.xv6, ucore都是不错的教材.

=======================
这篇文章什么也不干,我就是想记录一下自己读tcp ip协议栈的实现,自己的一点感想.仅此而已.

相关文章

  • 协议栈纪要

    5月27日 基本上,我想要的功能都已经完成了,接下来需要做的事情就是修修补补.还有,需要写博文记录一下到底干了什么...

  • 网络协议、端口和Socket

    1、网络协议分层 网络层次可划分为五层因特网协议栈和七层因特网协议栈。 1.1 五层因特网协议栈 因特网协议栈共有...

  • 协议栈和网卡的相关知识——基本概念

    协议栈和网卡的相关知识 问题代入 什么是协议栈? 协议栈的内部结构是什么? 协议栈是如何配合网卡进行数据收发的? ...

  • LTE学习笔记(二)

    LTE协议栈 LTE协议栈的两个面 用户面协议栈:负责用户数目传输 控制面协议栈:负责系统信令传输 用户面的主要功...

  • 用户态协议栈的实现

    协议栈,指的是TCP/IP协议栈。linux系统中,协议栈是内核实现的。 Client发送数据给server,数据...

  • 了解一下BLE协议栈整体架构

    协议栈框架 一般而言,我们把某个协议的实现代码称为协议栈(protocol stack),BLE协议栈就是实现低功...

  • 蓝牙4.0BLE中协议栈详解

    蓝牙4.0BLE协议栈介绍 问题:什么是BLE协议栈?BLE协议栈与BLE协议的关系? 顾名思义,人类之间需要一种...

  • 【二】iOS蓝牙开发(BLE4.0)技术信息-蓝牙协议栈

    技术信息 蓝牙协议栈 主要文章:蓝牙协议栈和蓝牙协议 蓝牙被定义为协议层架构,包括核心协议、电缆替代协议、电话传送...

  • 2.3收发数据

    2.3收发数据 将HTTP消息交给协议栈 应用程序调用socket库中的write将发送的数据交给协议栈协议栈收到...

  • TCP协议三次握手和四次挥手

    TCP协议 TCP/IP协议栈 由上图可知,TCP/IP协议栈包含很多的协议。 二. 什么是TCP TCP是TCP...

网友评论

      本文标题:协议栈纪要

      本文链接:https://www.haomeiwen.com/subject/paaktxtx.html