icmp协议
摘要:icmp(Internet Control Message Protocol)协议是在接收端在接收到发送端发送的数据后(分两种情况,接收和转发),无法把数据上传或转发,需要回馈一个信息给发送端,典型的例子,当接收端接收到数据包后,没有找到把数据发送出去的路由表项,此时就会发送一个icmp包给发送端,告诉发送端,目的不可达。而主机收到的icmp数据包一般都是应答包,比如接收发送目的不可达的数据包回来,接收端就会接收到这个包,并根据类型,把信息打印出来。当收到应答包时,接收方就不需要再回复一个应答包给对方,从而避免的循环回复。本地发送数据包,如果找不到IP地址对应的MAC地址时,会发送arp广播查
阅读全文
posted @
2012-04-12 09:53
image eye
阅读(2570)
推荐(0) 编辑
路由表项
摘要:本地路由表项由rt_base指针管理,记录本机路由表,当一个IP包需要传输到本子网以外的网络时,就需要通过网关使用路由器来转发,那怎么找到网关呢,就查找由rt_base指针所管理的路由表。在linux下,我们会用 route add default gw 192.168.1.1命令来设置默认网关,把默认网关设置到路由表中,使用route命令可以查看本机设置的路由表。如下是一个设置网关的函数static int set_gateway(void){ static int sock_fd = -1; struct rtentry rt; U32 dstaddr, gwaddr; dstaddr =
阅读全文
posted @
2012-04-10 17:05
image eye
阅读(8008)
推荐(1) 编辑
ip层的arp协议
摘要:Arp(adress resolution protocol—地址解析协议)是在传输IP包时,因不知道IP地址对应的MAC地址,无法传送数据引起的,通过arp,建立目的IP跟MAC地址的映射关系,从而获得目的IP的MAC地址。Arp头部的数据结构如下:typedefstruct arphdr { unsignedshort arp_hrd;/*硬件类型,*/ unsignedshort arp_pro;/*协议类型*/ unsignedchar arp_hln;/*硬件地址长度*/ unsignedchar arp_pln;/*协议地址长度*/ unsigne...
阅读全文
posted @
2012-04-09 11:21
image eye
阅读(3056)
推荐(3) 编辑
设备驱动基础1:设备模型之总线,驱动,设备
摘要:Kobject,kset是设备模型的基本结构体,设备模型使用这两个结构体来完成设备的层次关系,但在实际的设备驱动编写中,我们基本上用不到kobject,kset这些结构体,是因为这些结构体又被嵌入到更大的结构体中,原因在于kobject,kset结构体只能表征设备的层次关系,但是一个设备的驱动,并不是简单的一个层次关系而已,因此,必需要把kobject,kset结构体嵌入到更大的结构体中,使用kobject,kset来表征层次关系,用其他的成员表示设备驱动的具体功能。在设备模型中,我们将看到,设备驱动主要是由总线,驱动程序,设备三个部分构成,通过这三个标准部件,把各种纷繁杂乱的设备归结过来,达
阅读全文
posted @
2012-01-29 16:40
image eye
阅读(3412)
推荐(2) 编辑
网络协议栈17:connect函数分解之网络层接收数据处理
摘要:链路层经过对上层协议的检查,把数据包上传到了对应的上层协议层,在这里,就是IP层协议。数据到达IP层后,IP层需要进行相应的检查,判断后,才决定是否需要把数据上传到上层。下面就是IP层所需要做的事情.1.首先检测数据包的IP首部是否正确,即对数据包的IP部分的IP首部长度,版本,数据包的大小进行检查,如果符合要求,则继续进行下面的步骤,不符合要求,则释放数据包,直接退出2.检测IP首部是否包含了选项部分,方法就是查看IP首部的总长度字段是否大于IP首部的长度,如果是,则需要把选项部分解析,这个选项部分会在上传到上层协议时就告知是否有选项的。3.检测数据包是否是一个分片数据,如果是一个分片数据,
阅读全文
posted @
2012-01-18 15:32
image eye
阅读(828)
推荐(0) 编辑
网络协议栈16:connect函数分解之链路层接收数据
摘要:Connect函数在发送了数据之后,就进入了休眠等待的状态,等待远方发过来的数据来确认链接是否成功。那么数据是如何从网卡那里传递到链路层?数据在网卡的内存中,形成了以256字节为1页的环形缓冲链,每当有数据到达,网卡就会发生一个中断信号,告诉CPU已经有数据到达,此时,CPU通过DMA的方式,去读取网卡内存中的数据,并把数据存放在一个专门开辟来接收这个数据包的skb_buff中,之后,就把接收数据的skb_buff进行排列,并且累加所有skb_buff的个数,如果超过一定的数量在排队等待被取走,则后面不能再继续从网卡中读取数据包,以防止系统内存被过度的消耗掉。因此,在数据链路层,skb_buf
阅读全文
posted @
2012-01-18 12:16
image eye
阅读(879)
推荐(0) 编辑
网络协议栈15:网卡接收/发送数据基础知识
摘要:网卡本身是有内存的,每个网卡一般都有4K以上的内存,用来发送,接收数据。数据在从主内存搬到网卡之后,不是立即就能被发送出去的,而是要先在网卡自身的内存中排队,再按照先后顺序发送;同样的,数据从以太网传递到网卡时,网卡也是先把数据存储到自身的内存中,等到收到一帧数据了,再经过中断的方式,告诉主CPU(不是网卡本身的微处理器)把网卡内存的数据读走,而读走后的内存,又被清空,再次被使用,用来接收新的数据,如此循环往复。而网卡本身的内存,又多是按照256字节为1页的方式,把所有内存分页,之后把这些页组成队列,大致的结构如图:一般会划分一小部分页面作为发送数据用的,大部分用于接收网络数据,大致如图:蓝色
阅读全文
posted @
2012-01-17 17:03
image eye
阅读(4339)
推荐(0) 编辑
网络协议栈14:Connect函数分解之网卡发送/接收数据流程
摘要:链路层经过对数据包的优先级进行排队后,把本次需要发送的数据包从优先级最高的队列的头部抽取出来,并下传给网卡驱动程序的数据发送函数,一般命名为xxx_hard_xmit(),由于硬件各个不同,写法也会各个不同,无法抽象出一个标准的写法,但其流程、目的是不变的,是可以抽像出来的,大致的流程如下:1.通过设备结构体net_device中的tbusy(transmit busy)来判断网卡现在是否忙,如果等于1,表示网卡在忙,即目前仍然有数据在传输数据,此时是不能传输数据的,而是判断是否超时,如果未超时,则表示网卡正在忙,正在发送数据包,此时直接返回;如果是超时了,则重新初始化相关寄存器,之后设置 t
阅读全文
posted @
2012-01-16 15:49
image eye
阅读(2037)
推荐(0) 编辑
网络协议栈13:Connect函数分解之链路层
摘要:Skb_buff数据包从IP层下传到链路层后,链路层开始对数据包进行处理首先,判断skb_buff数据包是不是不在skb_buff链表中,如果还在(即skb_buff->next!=NULL),则说明上面的处理有问题,代码要避开(人为的避开,代码还是有问题),即不能发送这个数据包,处理方式是,指定发送数据包的设备被指定为NULL,即数据包没有设备真实发送。第二步,判断是否已知下一跳的MAC地址,即skb->arp=1,如果不是,则需要调用arp_find来查找IP地址对应的MAC地址,如果找不到,则直接返回,不再进行发送。第三步,前面两步都正常了,则说明数据包正常,此时判断数据是否
阅读全文
posted @
2012-01-12 16:15
image eye
阅读(1038)
推荐(0) 编辑
网络协议栈12:Connect函数分解之IP层
摘要:Tcp层把数据从传输层下传到网络层,之后,网络层将对下传的数据进行处理。首先,要对下传的数据进行排列。经过TCP层的处理,现在的数据已经被放置到skb_buff结构体中的数据空间部分,TP层就要对这个skb_buff进行必要的排列,使得数据有个先来后到的顺序,从而达到公平。对skb_buff的排列,是通过skb_buff对应的sock结构体成员sock->send_tail , sock->send_head 和skb_buff->link3 这三个成员来完成的,大致的排列图示如下:当前sock的所有skb_buff结构体都被按照 图 1 /2 /3 的方式插入到队列中,so
阅读全文
posted @
2012-01-12 12:09
image eye
阅读(720)
推荐(0) 编辑
网络协议栈11:Connect函数分解之TCP层
摘要:Connect函数之分解1.首先,connect函数从参数获得远端的IP,把这个地址赋值给对应的sock结构体的对应变量,并设置了sock结构体中的一些其他变量后,首先分配(skb_buff+用户空间)大小内存,这两部分是通过调用kmalloc(sizeof(struct skb_buff)+size,priority)来分配的,分配后两个数据块是连续的地址;分配后的内存如下接下来,就是初始化这个刚刚分配好的skb_buff结构体的一些指针成员,之后,把整个数据空间的首地址返回给一个skb_buff指针,以后对skb结构体的操作,就通过这个指针来完成了。接着,把skb_buff跟sock关联起
阅读全文
posted @
2012-01-11 18:42
image eye
阅读(876)
推荐(0) 编辑
网络协议栈10:connect()函数之前之整体框图
摘要:Connect函数的执行流程,就是按照上图的顺序,一步一步的由各个协议层来封装或解封数据的而构成的,所以这些数据,都是在分配skb_buff这个结构体空间时加入的数据空间中,按照MAC/IP/TCP的先后顺序,把数据封装好,而不是按照TCP/IP/MAC的顺序来的,在connect中,系统会调用ip_send()的函数,返回MAC的数据,此时,有可能远端地址还没有知道(本地路由是否有记录),那么在数据即将发送之前,系统还会调用ARP协议,来解析地址并填充相应字段,如果ARP发送没有结果,就会调用ICMP协议还报告错误。创建完MAC首部之后,在把指针移动IP首部位置,填充IP地址,其中的IP数据
阅读全文
posted @
2012-01-09 11:32
image eye
阅读(962)
推荐(0) 编辑
网络协议栈9:connect()函数之前之skb_buff结构体
摘要:在使用socket函数创建套接字时,系统创建socket/sock两个结构体,用于本地数据的管理,组织,而这两个数据结构是不会被传送到网络上的,而真正被用来携带数据的结构体是skb_buff,系统在开辟skb_buff结构体空间时,同时把用户数据所需要的空间一起开辟了,也就是一次malloc(sizeof(struct skb_buff)+size)这么多空间,即skb_buff本身的大小,加上用户空间所需要的size大小的空间,由于malloc分配,所以这些空间时连续的一片空间的,也就是说skb_buff结构体数据结束后,接着就是用户的数据,因此,skb_buff结构体的最后成员unsign
阅读全文
posted @
2012-01-09 10:35
image eye
阅读(1883)
推荐(0) 编辑
网络协议栈8:connect()函数之前之以太网首部
摘要:IP(网络层)下传的数据就传输到了链路层,对于我们常用的设备来说,这个层次最主要的设备,就是网卡了,完整的称号是以太网卡,因为网卡有多种格式的,而我们常见到的是以太网卡。以太网的首部如下:数据结构如下struct ethhdr { unsigned char h_dest[ETH_ALEN]; /*目标MAC地址*/ unsigned char h_source[ETH_ALEN]; /* 源MAC地址*/ unsigned short h_proto; /*帧中数据协议类型*/};其中成员h_proto可以使用的数据#define ETH_P_LOOP 0x0060 /* Ethernet
阅读全文
posted @
2012-01-08 11:41
image eye
阅读(1300)
推荐(0) 编辑
网络协议栈7:connect()函数之前之IP
摘要:网络协议栈7:connect()函数之前之IPTcp的下一层,就是IP(internet protocol,网络协议),IP的结构图和结构体如下:Ip首部结构体struct iphdr {#if defined(LITTLE_ENDIAN_BITFIELD) __u8 ihl:4,/*首部长度*/ version:4;/*版本号,V4、V6*/#elif defined (BIG_ENDIAN_BITFIELD) __u8 version:4, ihl:4;#else#error "Please fix <asm/byteorder.h>"#endif __u8
阅读全文
posted @
2012-01-08 11:01
image eye
阅读(768)
推荐(0) 编辑
网络协议栈6:connect()函数之前之TCP
摘要:从connect开始,就涉及到各种各样的协议了,目前先把TCP/IP协议理清。首先,先把TCP(transmit control protocol, 传输控制协议)的结构图跟结构体对上:#define HEADER_SIZE 64 /* maximum header size */struct tcphdr {/*tcp头部*//*发送端端口号:16 比特标识该数据包源端数据发送进程。*/ __u16 source;/*目的端端口号:16 比特标识该数据包目的端数据接收进程。*/ __u16 dest;/*序列号:32比特本端发送的数据包中所包含数据的第一个字节的序列号。*/ __u32 se
阅读全文
posted @
2012-01-07 15:38
image eye
阅读(1227)
推荐(0) 编辑
网络协议栈5:connect()函数之前
摘要:我们的应用程序在调用了socket()函数,bind()函数之后,只是在本地创建了socket结构体,sock结构体,并把socket,sock这两个结构体跟I节点,文件句柄结合起来,在把socket创建时所指定的协议的操作集关联到sock结构体上,用于在socket指定了协议之后,使用这个操作集来完成相关的操作;之后的bind()函数则把本地的一个未被使用的端口号(一般大于1024,因为0~1024是知名端口号,保留下来做已知的特定用途,如端口号不是营养程序指定的,则查找空闲的端口号比较烦),用于表示当前sock所属的进程,并把本地的IP跟绑定到sock上,用于表示数据将从哪里被发送到网络上
阅读全文
posted @
2012-01-07 09:56
image eye
阅读(816)
推荐(0) 编辑
网络协议栈4:bind()函数
摘要:正常的情况下,socket函数的调用,只要有足够的内存用于分配socket结构体,sock结构体,以及空闲的I节点和当前进程有空闲的文件表项,就会返回分配给当前进程分配此I节点的文件表项的序号,即文件句柄,通过这个文件句柄,可以找到对应的文件表项,通过文件表项可以找到对应的I节点,通过I节点可以找到socket套接字,通过套接字可以找到对以的sock结构体,而这个结构体就是我们数据的信使了,注意,只是信使哦。当应用程序调用socket创建完套接字后,一般情况下,接下来就会调用bind()函数来给这个socket绑定一个本地地址,即绑定一个IP地址,也即绑定一块网卡,即这个套接字的数据,就是从指
阅读全文
posted @
2012-01-05 20:11
image eye
阅读(1442)
推荐(0) 编辑
网络协议栈3:sock结构体
摘要:sock结构体是我们在网络编程中遇到的第一个庞大的结构体struct sock { struct options *opt;/*IP选项缓存于此处*/ volatile unsigned long wmem_alloc;/*当前写缓冲区大小,该值不可大于系统规定的最大值*/ volatile unsigned long rmem_alloc;/*当前读缓冲区大小,该值不可大于系统规定最大值*/ unsigned long write_seq;/* write_seq 表示应用程序下一次写数据时所对应的第一个字节的序列号*/ unsigned long sent_seq;/* sent_seq
阅读全文
posted @
2012-01-05 16:43
image eye
阅读(3151)
推荐(1) 编辑