01 2012 档案
Usb设备驱动1:root hub 设备驱动安装
摘要:按照设备模型的总线,设备,驱动模式,一条总线会把所有这条总线上的设备和驱动都挂载到总线的设备链表和驱动链表上,具体到usb总线上,就是usb主控制器,hub等设备,都需要按照设备模型的要求,作为设备挂载到usb总线的设备链表上,同时也需要把usb主控制器,hub的驱动也挂载到驱动链表上,并且使得设备和设备驱动能够相互关联起来,才能使得设备能够使用,完成应有的设备功能。那么usb hub驱动是如何被挂载的,驱动又是如何跟hub设备关联在一起的?首先,要有一条usb总线,就必须有一个usb主控制器,一个usb主控制器对应一条usb总线。一个系统有多少个usb主控制器,就有多少条usb总线,我们常见 阅读全文
posted @ 2012-01-31 16:06 image eye 阅读(18955) 评论(0) 推荐(0)
Usb设备驱动0:从usb设备被发现开始
摘要:经过对设备模型的整理,消化,就有了编写一个设备驱动程序的基础。因工作关系,需要熟悉usb设备驱动,因此,就选择usb设备驱动作为开始。一个usb设备,是如何被usb系统发现并安装对应的设备驱动程序的,从而使得usb设备可以正常工作?当一个usb设备通过usb接口,连接到主机时,实际上是链接到了一个usb集线器( hub)的一个接口上,集线器的接口上有了电平的变化(高速设备在D+上有上拉,低速设备D+上有上拉),从而知道这个端口上有了设备的接入,从而可以通知usb主控制器,在集线器的某一个接口上有设备插入了,此时,要采取什么行动,就由usb主机来决定。一般的usb设备可以直接连接到跟集线器上,也 阅读全文
posted @ 2012-01-30 11:37 image eye 阅读(2311) 评论(0) 推荐(0)
设备驱动基础1:设备模型之总线,驱动,设备
摘要:Kobject,kset是设备模型的基本结构体,设备模型使用这两个结构体来完成设备的层次关系,但在实际的设备驱动编写中,我们基本上用不到kobject,kset这些结构体,是因为这些结构体又被嵌入到更大的结构体中,原因在于kobject,kset结构体只能表征设备的层次关系,但是一个设备的驱动,并不是简单的一个层次关系而已,因此,必需要把kobject,kset结构体嵌入到更大的结构体中,使用kobject,kset来表征层次关系,用其他的成员表示设备驱动的具体功能。在设备模型中,我们将看到,设备驱动主要是由总线,驱动程序,设备三个部分构成,通过这三个标准部件,把各种纷繁杂乱的设备归结过来,达 阅读全文
posted @ 2012-01-29 16:40 image eye 阅读(3431) 评论(0) 推荐(2)
设备驱动基础0:设备模型之kobject,kset及其关系
摘要:Linux2.6以后的设备驱动,都是在设备模型的基础上构建的,因此,要编写linux下的设备驱动程序,不论是usb设备,pci设备等,都需要了解设备模型。设备模型的基础结构体主要是kobject,kset这两个结构体:struct kobject { char * k_name; char name[KOBJ_NAME_LEN]; struct kref kref; struct list_head entry; struct kobject * parent; struct kset * kset; struct kobj_type * ktype; struct dentry * dent 阅读全文
posted @ 2012-01-29 09:48 image eye 阅读(7814) 评论(2) 推荐(2)
网络协议栈17:connect函数分解之网络层接收数据处理
摘要:链路层经过对上层协议的检查,把数据包上传到了对应的上层协议层,在这里,就是IP层协议。数据到达IP层后,IP层需要进行相应的检查,判断后,才决定是否需要把数据上传到上层。下面就是IP层所需要做的事情.1.首先检测数据包的IP首部是否正确,即对数据包的IP部分的IP首部长度,版本,数据包的大小进行检查,如果符合要求,则继续进行下面的步骤,不符合要求,则释放数据包,直接退出2.检测IP首部是否包含了选项部分,方法就是查看IP首部的总长度字段是否大于IP首部的长度,如果是,则需要把选项部分解析,这个选项部分会在上传到上层协议时就告知是否有选项的。3.检测数据包是否是一个分片数据,如果是一个分片数据, 阅读全文
posted @ 2012-01-18 15:32 image eye 阅读(839) 评论(0) 推荐(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 阅读(893) 评论(0) 推荐(0)
网络协议栈15:网卡接收/发送数据基础知识
摘要:网卡本身是有内存的,每个网卡一般都有4K以上的内存,用来发送,接收数据。数据在从主内存搬到网卡之后,不是立即就能被发送出去的,而是要先在网卡自身的内存中排队,再按照先后顺序发送;同样的,数据从以太网传递到网卡时,网卡也是先把数据存储到自身的内存中,等到收到一帧数据了,再经过中断的方式,告诉主CPU(不是网卡本身的微处理器)把网卡内存的数据读走,而读走后的内存,又被清空,再次被使用,用来接收新的数据,如此循环往复。而网卡本身的内存,又多是按照256字节为1页的方式,把所有内存分页,之后把这些页组成队列,大致的结构如图:一般会划分一小部分页面作为发送数据用的,大部分用于接收网络数据,大致如图:蓝色 阅读全文
posted @ 2012-01-17 17:03 image eye 阅读(4474) 评论(0) 推荐(0)
网络协议栈14:Connect函数分解之网卡发送/接收数据流程
摘要:链路层经过对数据包的优先级进行排队后,把本次需要发送的数据包从优先级最高的队列的头部抽取出来,并下传给网卡驱动程序的数据发送函数,一般命名为xxx_hard_xmit(),由于硬件各个不同,写法也会各个不同,无法抽象出一个标准的写法,但其流程、目的是不变的,是可以抽像出来的,大致的流程如下:1.通过设备结构体net_device中的tbusy(transmit busy)来判断网卡现在是否忙,如果等于1,表示网卡在忙,即目前仍然有数据在传输数据,此时是不能传输数据的,而是判断是否超时,如果未超时,则表示网卡正在忙,正在发送数据包,此时直接返回;如果是超时了,则重新初始化相关寄存器,之后设置 t 阅读全文
posted @ 2012-01-16 15:49 image eye 阅读(2094) 评论(0) 推荐(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 阅读(1057) 评论(0) 推荐(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 阅读(733) 评论(0) 推荐(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 阅读(895) 评论(0) 推荐(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 阅读(972) 评论(0) 推荐(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 阅读(1900) 评论(0) 推荐(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 阅读(1323) 评论(0) 推荐(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 阅读(782) 评论(0) 推荐(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 阅读(1235) 评论(0) 推荐(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 阅读(826) 评论(0) 推荐(0)
网络协议栈4:bind()函数
摘要:正常的情况下,socket函数的调用,只要有足够的内存用于分配socket结构体,sock结构体,以及空闲的I节点和当前进程有空闲的文件表项,就会返回分配给当前进程分配此I节点的文件表项的序号,即文件句柄,通过这个文件句柄,可以找到对应的文件表项,通过文件表项可以找到对应的I节点,通过I节点可以找到socket套接字,通过套接字可以找到对以的sock结构体,而这个结构体就是我们数据的信使了,注意,只是信使哦。当应用程序调用socket创建完套接字后,一般情况下,接下来就会调用bind()函数来给这个socket绑定一个本地地址,即绑定一个IP地址,也即绑定一块网卡,即这个套接字的数据,就是从指 阅读全文
posted @ 2012-01-05 20:11 image eye 阅读(1465) 评论(0) 推荐(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 阅读(3231) 评论(0) 推荐(1)
网络协议栈2:socket函数
摘要:首先,这里会用到一个结构体,先把这个结构体整理出来struct socket {{short type;/*套接字所用的流类型,可取值SOCK_RAW,SOCK_DGRAM,SOCK_STREAM,SOCK_SEQPACKET,SOCK_PACKET,其中SOCK_STREAM 就是通常所说的TCP协议所用*/socket_state state;/*套接字状态,可取值SS_FREE ,SS_UNCONNECTED ,SS_CONNECTING ,SS_CONNECTED ,SS_DISCONNECTING */long flags;/*一些标志信息*/struct proto_ops *op 阅读全文
posted @ 2012-01-05 12:21 image eye 阅读(1792) 评论(0) 推荐(1)
网络协议栈1:socket函数调用之前
摘要:client代码中,第一个被调用的函数是socket(),在这个函数被调用之前,系统做了什么事情,让socket()可以正常调用?首先,socket函数实际上是一个系统调用,它是内核中的代码,我们应用层通过系统调用,调用了系统的函数。其次,在系统启动时,已经调用sock_init()对socket进行了初始化,在我们调用socket函数之前,socket的初始化部分已经为我们的调用做好的铺垫了。void sock_init(void){ int i; ...... for (i = 0; i < NPROTO; ++i) pops[i] = NULL; proto_init(); ... 阅读全文
posted @ 2012-01-05 10:37 image eye 阅读(2724) 评论(0) 推荐(1)
网络协议栈0:从一个例子开始
摘要:最近因工作需要写一个网卡驱动,晕倒,没有任何网络知识,就写网络驱动!可是,为了五斗米糊口,不得不从啊于是,打算从网络协议栈开始,把网络搞一搞。我们常常知道socket的用法(其实我还没有真正的写过socket代码,常常都是指那些socket高手了^-^),因此,打算从一个常用的实例开始,把网络协议栈整理一下,即把自己的学习经过进行记录,看看菜鸟的轨迹,是如何拐弯,颠簸。通常的socket编程分两部分吧(错了别怪我,我不是高手),一是client部分,二是server部分,而更通常的情况是我们都以写client的任务为多,因此,从简单下手,当然选择client端开始了。下面的代码,就是随便一个网 阅读全文
posted @ 2012-01-05 10:36 image eye 阅读(2129) 评论(0) 推荐(1)
Linux内核配置(三) :电源,总线配置
摘要:[*] Power Management support//如果你想让你的Linux支持高级电源管理(也就是平常我们说的软关机、系统休眠等)需要选择它[ ] Power Management Debug Support//不想调试ACPI,不选[*] Suspend to RAM and standby//待机到内存,即内存供电而暂时关闭硬盘等外设[ ] Hibernation (aka 'suspend to disk')//休眠,即把内存内容保存在交换分区后关闭电脑,因为技术不是很成熟而且由于兼容性等问题,建议关闭此功能[*] ACPI (Advanced Configur 阅读全文
posted @ 2012-01-05 09:44 image eye 阅读(2968) 评论(0) 推荐(0)
linux 内核配置 library routines
摘要:这个库仅在那些不包含在内核原码中的第三方内核模块才可能需要,可以全不选,内核中若有其他部分依赖它,会自动选上。CRC-CCITT functions ----->传送8-bit字符,欧洲标准CRC16 functions ----->传送8-bit字符,美国标准CRC32 functions----->用于点对点的同步数据传输,传输网路数据包所必须的CRC32c(castagnli,et al )Cyclic redundancy-check--->用于点对点的同步数据传输,比如iscsi设备 阅读全文
posted @ 2012-01-05 09:43 image eye 阅读(562) 评论(0) 推荐(0)
vmware虚拟机中redhat 2.6新编内核无法启动的几个问题
摘要:1.Kernel panic:VFS:unable to mount root fs on XXX解决方法:i.配置内核选项时确保文件系统选项配置正确,最好将ext2,ext3都编进内核ii.在block devices中将Initial RAM filesystem and RAM disk (initramfs/initrd) support选中如果启动计算机必须的模块并不是都编在了内核中,它将无法启动。2.Unable to find device_mapper major/minor可能的原因是内核不支持lvm 逻辑卷管理,而你的系统又使用的逻辑卷解决方法:在Multi-device 阅读全文
posted @ 2012-01-05 09:43 image eye 阅读(890) 评论(0) 推荐(0)
CPU内核配置(一):通用内核配置
摘要:General setup 常规设置 Prompt for development and/or incomplete code/drivers 显示尚在开发中或尚未完成的代码与驱动 Local version - append to kernel release 在内核版本后面加上自定义的版本字符串(小于64字符),可以用"uname -a"命令看到 Automatically append version information to the version string 自动在版本字符串后面添加版本信息,编译时需要有perl以及git仓库支持 Support for 阅读全文
posted @ 2012-01-05 09:43 image eye 阅读(3274) 评论(0) 推荐(0)
Linux内核配置(二) :CPU类型配置
摘要:5. Processor type and features 处理器类型及特性 5.1. Symmetric multi-processing support (SMP) 对称多处理器支持。 这将支持有多CPU的系统。如果你的系统只有一个CPU,选N。反之,选Y。 如果你选N,内核将会在单个或者多个CPU的机器上运行,但是只会使用一个CPU。如果你选Y,内核可以在很多(但不是所有)单CPU的机器上运行,在这样的机器,你选N会使内核运行得更快。 注意如果你选Y,然后在Processor family选项中选择"586" or "Pentium" ,内核将不 阅读全文
posted @ 2012-01-05 09:43 image eye 阅读(10930) 评论(0) 推荐(0)