![[互联网]Linux网络设备驱动.ppt_第1页](http://file.renrendoc.com/FileRoot1/2018-12/23/d987d481-5064-4df3-930a-99202e21692b/d987d481-5064-4df3-930a-99202e21692b1.gif)
![[互联网]Linux网络设备驱动.ppt_第2页](http://file.renrendoc.com/FileRoot1/2018-12/23/d987d481-5064-4df3-930a-99202e21692b/d987d481-5064-4df3-930a-99202e21692b2.gif)
![[互联网]Linux网络设备驱动.ppt_第3页](http://file.renrendoc.com/FileRoot1/2018-12/23/d987d481-5064-4df3-930a-99202e21692b/d987d481-5064-4df3-930a-99202e21692b3.gif)
![[互联网]Linux网络设备驱动.ppt_第4页](http://file.renrendoc.com/FileRoot1/2018-12/23/d987d481-5064-4df3-930a-99202e21692b/d987d481-5064-4df3-930a-99202e21692b4.gif)
![[互联网]Linux网络设备驱动.ppt_第5页](http://file.renrendoc.com/FileRoot1/2018-12/23/d987d481-5064-4df3-930a-99202e21692b/d987d481-5064-4df3-930a-99202e21692b5.gif)
已阅读5页,还剩42页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Linux 网络设备驱动,,TCP/IP协议,TCP/IP(传输入控制地议/网际协议)是一种网络通信协议,它规范了网络上的所有通信设备,尤其是一个主机与另一个主机之间的数据传输格式以及传送方式。TCP/IP是因特网的基础协议。 在数据传送中,可以形象的理解为有两个信封:TCP和IP信封。要送递的信息被分成若干段,每一段塞入一个TCP信封,并在该信封上记录有分段号的信息,再将TCP信封塞入IP大信封里,发送到网上。在扫收端,一个TCP软件包收集信封,抽出数据,按发送关的顺序还原,并加以校验,若发现差错,TCP将会要求重发。因此TCP/IP在因特网中几乎可以无差错地传送数据。对因特网用户来说,并不需要了解网络协议的整个结构,仅需了解IP的地址格式,即可与世界各地进行网络通信。,,OSI七层网络模型,1. OSI网络分层参考模型 网络协议设计者不应当设计一个单一、巨大的协议来为所有形式的通信规定完整的细节,而应把通信问题划分成多个小问题,然后为每一个小问题设计一个单独的协议。这样做使得每个协议的设计、分析、时限和测试比较容易。协议划分的一个主要原则是确保目标系统有效且效率高。为了提高效率,每个协议只应该注意没有被其他协议处理过的那部分通信问题;为了主协议的实现更加有效,协议之间应该能够共享特定的数据结构;同时这些协议的组合应该能处理所有可能的硬件错误以及其它异常情况。为了保证这些协议工作的协同性,应当将协议设计和开发成完整的、协作的协议系列(即协议族),而不是孤立地开发每个协议。 在网络历史的早期,国际标准化组织(ISO)和国际电报电话咨询委员会(CCITT)共同出版了开放系统互联的七层参考模型。一台计算机操作系统中的网络过程包括从应用请求(在协议栈的顶部)到网络介质(底部) ,OSI参考模型把功能分成七个分立的层次。,,OSI七层网络模型, 应用层 第七层 表示层 会话层 传输层 网络层 数据链路层 物理层 第一层 OSI七层参考模型,,OSI七层网络模型,第一层:物理层 负责最后将信息编码成电流脉冲或其它信号用于网上传输。它由计算机和网络介质之间的实际界面组成,可定义电气信号、符号、线的状态和时钟要求、数据编码和数据传输用的连接器。如最常用的RS-232规范、10BASE-T的曼彻斯特编码以及RJ-45就属于第一层。所有比物理层高的层都通过事先定义好的接口而与它通话。如以太网的附属单元接口(AUI),一个DB-15连接器可被用来连接层一和层二。,,OSI七层网络模型,第二层:数据链路层 数据链路层定义了不同的网络和协议特征,其中包括物理编址、网络拓扑结构、错误校验、帧序列以及流控。 数据链路层实际上由两个独立的部分组成: 介质存取控制(Media Access Control,MAC) 逻辑链路控制层(Logical Link Control,LLC)。 MAC描述在共享介质环境中如何进行站的调度、发生和接收数据。MAC确保信息跨链路的可靠传输,对数据传输进行同步,识别错误和控制数据的流向。一般地讲,MAC只在共享介质环境中才是重要的,只有在共享介质环境中多个节点才能连接到同一传输介质上。 IEEE 802.2标准定义了LLC。LLC支持无连接服务和面向连接的服务。在数据链路层的信息帧中定义了许多域。这些域使得多种高层协议可以共享一个物理数据链路。,,OSI七层网络模型,第三层:网络层 负责在源和终点之间建立连接。它一般包括网络寻径,还可能包括流量控制、错误检查等。相同MAC标准的不同网段之间的数据传输一般只涉及到数据链路层,而不同的MAC标准之间的数据传输都涉及到网络层。例如IP路由器工作在网络层,因而可以实现多种网络间的互联。 第四层:传输层 向高层提供可靠的端到端的网络数据流服务。传输层的功能一般包括流控、多路传输、虚电路管理及差错校验和恢复。流控管理设备之间的数据传输,确保传输设备不发送比接收设备处理能力大的数据;多路传输使得多个应用程序的数据可以传输到一个物理链路上;虚电路由传输层建立、维护和终止;差错校验包括为检测传输错误而建立的各种不同结构;而差错恢复包括所采取的行动(如请求数据重发),以便解决发生的任何错误。传输控制协议(TCP)是提供可靠数据传输的TCP/IP协议族中的传输层协议。,,OSI七层网络模型,第五层:会话层 建立、管理和终止表示层与实体之间的通信会话。通信会话包括发生在不同网络应用层之间的服务请求和服务应答,这些请求与应答通过会话层的协议实现。它还包括创建检查点,使通信发生中断的时候可以返回到以前的一个状态。 第六层:表示层 提供多种功能用于应用层数据编码和转化,以确保以一个系统应用层发送的信息可以被另一个系统应用层识别。表示层的编码和转化模式包括公用数据表示格式、性能转化表示格式、公用数据压缩模式和公用数据加密模式。 公用数据表示格式就是标准的图像、声音和视频格式。通过使用这些标准格式,不同类型的计算机系统可以相互交换数据;转化模式通过使用不同的文本和数据表示,在系统间交换信息,例如ASCII(American Standard Code for Information Interchange,美国标准信息交换码);标准数据压缩模式确保原始设备上被压缩的数据可以在目标设备上正确的解压;加密模式确保原始设备上加密的数据可以在目标设备上正确地解密。 表示层协议一般不与特殊的协议栈关联,如QuickTime是Applet计算机的视频和音频的标准,MPEG是ISO的视频压缩与编码标准。常见的图形图像格式PCX、GIF、JPEG是不同的静态图像压缩和编码标准。,,OSI七层网络模型,第七层:应用层 最接近终端用户的OSI层,这就意味着OSI应用层与用户之间是通过应用软件直接相互作用的。注意,应用层并非由计算机上运行的实际应用软件组成,而是由向应用程序提供访问网络资源的API(Application Program Interface,应用程序接口)组成,这类应用软件程序超出了OSI模型的范畴。应用层的功能一般包括标识通信伙伴、定义资源的可用性和同步通信。因为可能丢失通信伙伴,应用层必须为传输数据的应用子程序定义通信伙伴的标识和可用性。定义资源可用性时,应用层为了请求通信而必须判定是否有足够的网络资源。在同步通信中,所有应用程序之间的通信都需要应用层的协同操作。,,TCP/IP分层模型(TCP/IP Layening Model)被称作因特网分层模型(Internet Layering Model)、因特网参考模型(Internet Reference Model)。,TCP/IP四层网络模型,,TCP/IP四层网络模型,TCP/IP协议被组织成四个概念层,其中有三层对应于ISO参考模型中的相应层。ICP/IP协议族并不包含物理层和数据链路层,因此它不能独立完成整个计算机网络系统的功能,必须与许多其他的协议协同工作。 TCP/IP分层模型的四个协议层分别完成以下的功能: 第一层:网络接口层 包括用于协作IP数据在已有网络介质上传输的协议。实际上TCP/IP标准并不定义与ISO数据链路层和物理层相对应的功能。相反,它定义像地址解析协议(Address Resolution Protocol,ARP)这样的协议,提供TCP/IP协议的数据结构和实际物理硬件之间的接口。,,TCP/IP四层网络模型,第二层:网间层 对应于OSI七层参考模型的网络层。本层包含IP协议、RIP协议(Routing Information Protocol,路由信息协议),负责数据的包装、寻址和路由。同时还包含网间控制报文协议(Internet Control Message Protocol,ICMP)用来提供网络诊断信息。 第三层:传输层 对应于OSI七层参考模型的传输层,它提供两种端到端的通信服务。其中TCP协议(Transmission Control Protocol)提供可靠的数据流运输服务,UDP协议(Use Datagram Protocol)提供不可靠的用户数据报服务。 第四层:应用层 对应于OSI七层参考模型的应用层和表达层。因特网的应用层协议包括Finger、Whois、FTP(文件传输协议)、Gopher、HTTP(超文本传输协议)、Telent(远程终端协议)、SMTP(简单邮件传送协议)、IRC(因特网中继会话)、NNTP(网络新闻传输协议)等,,TCP/IP四层网络模型,TCP/IP的重要协议: (1)地址解析协议(ARP) 在网络上进行通信的主机必须知道对方主机的硬件地址(网卡的物理地址)。地址解析协议的目的就是将IP地址映射成物理地址。这在使信息通过网络时特别重要。一个消息(或者其他数据)在发送之前,被打包到IP包里面,或适合于因特网传输信息块中,其中包括两台计算机的IP地址。 在这个包离开发送计算机前,必须找到目标的硬件地址,这就是ARP最初到达的地方。 一个ARP请求消息会在网上广播。请求由一个进程接收,它回复物理地址。这个回复消息由原先的那台发送广播消息的计算机接收,从而传输过程就开始了。,,TCP/IP四层网络模型,(2)因特网控制消息协议(ICMP) 因特网控制消息协议(ICMP)用于报告错误并对IP消息进行控制。IP运用互联组管理协议(IGMP)来告诉路由器某一网络上指导组中有哪些可用主机。 以ICMP实现的最著名的网络工具是Ping.Ping通常用来判断一台远程机器是否正开着,数据包从用户的计算机发到远程计算机,这些包通常返回到用户的计算机,如果数据据包没有返回到用户计算机,Ping程序就产生一个表示远程计算机关机的错误消息。,,Linux网络驱动程序,Linux网络驱动程序作为Linux网络子系统的一部分,位于TCP/IP网络体系结构的网络接口层,主要实现上层协议栈与网络设备的数据交换。Linux的网络系统主要是基于BSD Unix的套接字(socket)机制,网络设备与字符设备和块设备不同,没有对应地映射到文件系统中的设备节点。 Linux网络驱动程序的体系结构可划分为4个层次。Linux内核源代码中提供了网络设备接口及以网络子系统的上层的代码,移植特定网络硬件的驱动程序的主要工作就是完成设备驱动功能层的相应代码,根据底层具体的硬件特性,定义网络设备接口struct net_device类型的结构体变量,并实现其中相应的操作函数及中断处理程序。 Linux中所有的网络设备都抽象为一个统一的接口,即网络设备接口,通过struct net_device类型的结构体变量表示网络设备在内核中的运行情况,这里既包括回环(loopback)设备,也包括硬件网络设备接口。内核通过以dev_base为头指针的设备链表来管理所有的网络设备。,,网络设备接口层,net_device结构体的相关成员 网络设备的名称: char nameIFNAMESIZ 设备初始化函数指针,设备注册时被调用: int (*init)(struct net_device *dev); 硬件信息: unsigned long mem_end; unsigned long mem_start; 二者分别定义了设备所用的共享内存 的起始和结束地址 unsigned long base_addr;网络设备的I/O基地址 unsigned char irq;设备使用的中断号 unsigned char if_port;多端口设备中端口选择 unsigned char dma;分配给设备的DMA通道,,网络设备接口层,接口信息 unsigned short hard_header_len;网络设备的硬件头长度,在以太网设备的初始化函数中,该成员被赋值为ETH_HLEN,即14 unsigned short type;接口的硬件类型 unsigned mtu;最大传输单元 unsigned char dev_addrMAX_ADDR_LEN; unsigned char broadcaseMAX_ADDR_LEN; 二者分别用于存放设备的硬件地址和广播地址,以太网设备的广播地址为6个0xFF unsigned short flags;网络接口标志 设备操作函数 打开、关闭 int (*open)(struct net_device *dev); 获得设备需要的IO地址,IRQ及DMA通道 int (*stop)(struct net_device *dev);,,网络设备接口层,启动数据包发送 int (*hard_start_xmit)(struct sk_buff *skb, struct net_device *dev); 获得网络设备状态 struct net_device_status * (*get_status)(struct net_device *dev); 设备I/O控制 int (*do_ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); 配置接口,I/O地址,中断号 int (*set_config)(struct net_device *dev, struct ifmap *map); 设置MAC地址 int (*set_mac_address)(struct net_device *dev, void *addr);,,网络设备接口层,辅助成员 unsigned long trans_start; unsigned long last_rx; 二者分别为:最后一次开始发送的时间戳、最后一次接收到数据包的时间戳,这两个时间戳记录都是jiffies,驱动程序应维护这两个成员。 void *priv;私有信息指针 spinlock_t xmit_lock; int xmit_lock_owner; xmit_lock是避免hard_start_xmit函数同时多次调用的自旋锁。 xmit_lock_owner指向拥有此自旋锁的CPU的编号。,,Linux网络驱动程序,,网络协议接口层,1.网络协议接口层 在网络协议接口层,只提供了两个抽象函数dev_queue_xmit()与 netif_rx(),之所以称之为抽象函数,是因为这两个函数抽象了很多底层的操作,不管是那个芯片它在网络协议结构的操作函数都是这两个函数,采用这样的抽象后,给上层带来了很多的方便,给上层协议提供统一的数据包收发接口,无论上层是ARP协议还是IP协议,都通过dev_queue_xmit() 函数发送数据,通过netif_rx()函数接收数据。此层使上层协议独立于具体的设备。 相关数据结构sk_buff: sk_buff 称为“套接字缓冲区”,用于在Linux网络子系统中各层之间传递数据。是Linux网络子系统数据传递的“中枢神经”。sk_buff定义位置为:include/linux/skbuff.h,这个数据结构定义了很多用于网络操作的函数,更多的设计整个协议的实现,包括各层报文的头信息,以及报文的帧格式,,,网络协议接口层,sk_buff中的数据缓冲区的指针 Linux必须分配用于容纳数据包的缓冲区,sk_buff中定义了4个指向这片缓冲区的不同位置的指针head、data、tail、end。 head:指针指向内存中已分配的用于存储网路数据的缓冲区起始地址,sk_buff和相关数据块在分配后,该指针的值就固定了。 data:指针指向对应当前协议层有效数据的起始地址。每个协议的有效数据含义不同。 tail:指向对应当前协议层有效数据负载的结尾地址,与data对应。 end:指向内存分配的数据缓冲区的结尾地址,与head指针对应。和head一样,sk_buff和相关数据块被分配后,end指针也就固定了。,,网络协议接口层,套接字缓冲区sk_buff相关操作: 分配空间: struct sk_buff *dev_alloc_skb(unsigned len) 释放空间: dev_kfree_skb(struct sk_buff *skb) 用于非中断上下文 dev_kfree_skb_irq(struct sk_buff *skb) 用于中断上下文 dev_kfree_skb_any(struct sk_buff *skb) 上述两种情况均可 put操作: unsigned char *skb_put(struct sk_buff *skb, unsigned int len); unsigned char *_skb_put(struct sk_buff *skb, unsigned int len); 作用:在缓冲区尾部添加数据,tail指针下移len长度,并增加sk_buff中len的值,返回改变后的tail值。,,网络协议接口层,push操作: unsigned char *skb_push(struct sk_buff *skb, unsigned int len); unsigned char *_skb_push(struct sk_buff *skb, unsigned int len); 作用:将data指针上移,同时增加sk_buff中的len。主要用于在数据包发送时添加头部。函数带_和不带_的区别在于:带_的会检测放入缓冲区的数据,后则不会。 pull操作: unsigned char *skb_pull(struct sk_buff *skb, unsigned int len); 作用:将data指针下移,并减少sk_buff中的len值。这个操作一般用于下层协议向上层协议移交数据包,使data指针指向上一层协议的协议头 reserve操作: void skb_reserve(struct sk_buff *skb, unsigned int len); 作用:将data和tail指针同时下移,这个操作主要用于在存储空间的头部预留len长度的空隙。,,,数据发送时的sk_buff封装,,transport_header,network_header以及mac_header的变化,这几个指针都是随着数据包到达不同的层次才会有对应的值,我们来看下面的图,这个图表示了当从2层到达3层对应的指针的变化。,,,网络设备接口层,struct net_device_ops int (*ndo_init)(struct net_device *dev); void (*ndo_uninit)(struct net_device *dev); int (*ndo_open)(struct net_device *dev); int (*ndo_stop)(struct net_device *dev); int (*ndo_start_xmit) (struct sk_buff *skb,struct net_device *dev); u16 (*ndo_select_queue)(struct net_device *dev,struct sk_buff *skb); 实现这些函数中的一部分后,就实现了驱动的功能了,为千变万化的网络设备定义统一的、抽象的数据结构net_device结构体,以不变应万变,实现多种硬件在软件层次上的统一。net_device结构体在内核中指代一个网络设备,网络设备驱动只需填充其结构体就可以实现内核与具体硬件操作函数的挂接。实际驱动的编写过程中,我们并不需要实现全部的函数,实际上,我们只要根据具体的需要实现上边的部分就可以了。,,设备驱动功能层网、络设备与媒介层,设备驱动功能层 net_device结构体的成员需要被设备驱动功能层的具体数值和函数赋予。 由于网络数据包的接收可由中断引发,设备驱动功能层中另一个主体部分将是中断处理函数,它负责读取硬件上接收的数据包并传送给上层协议。 网络设备与媒介层 直接对应于实际的硬件设备。 网络设备驱动的注册与注销 注册与注销使用register_netdev()和unregister_netdev()函数。 生成net_device结构体 ,实现注册前的填充 alloc_netdev(),alloc_etherdev(); 释放结构体 free_netdev()。,,Linux网络设备驱动程序实现,,网络设备的初始化,网络设备的初始化 初始化完成如下工作: 进行硬件上的准备工作,检查网络设备是否存在,如果存在,则检测设备所使用的硬件资源。 进行软件接口上的准备工作,分配net_device结构体并对其数据和函数指针成员赋值。 获得设备的私有信息指针并初始化其各成员的值。,,网络设备的打开与释放,网络设备的打开与释放 打开函数完成工作: 使能设备使用的硬件资源,申请I/O区域、中断和DMA通道等。 调用内核提供的netif_start_queue(),激活设备发送队列。 关闭函数相反,调用函数netif_stop_queue()。,,数据包的发送与接收,数据包的发送与接收 数据包的发送和接收是实现Linux网络驱动程序中两个最关键的过程,对这两个过程处理的好坏将直接影响到驱动程序的整体运行质量。 首先在网络设备驱动加载时,通过device域中的init函数指针调用网络设备的初始化函数对设备进行初始化,如果操作成功就可以通过device域中的open函数指针调用网络设备的打开函数打开设备,再通过device域中的建立硬件包头函数指针hard_header来建立硬件包头信息。最后通过协议接口层函数dev_queue_xmit来调用device域中的hard_start_xmit函数指针来完成数据包的发送。该函数将把存放在套接字缓冲区中的数据发送到物理设备,该缓冲区是由数据结构sk_buff来表示的。 数据包的接收是通过中断机制来完成的,当有数据到达时,就产生中断信号,网络设备驱动功能层就调用中断处理程序,即数据包接收程序来处理数据包的接收,然后网络协议接口层调用netif_rx函数(详见/linux/net/core/dev.c)把接收到的数据包传输到网络协议的上层进行处理。,,数据收发流程,数据发送流程 发送流程如下: 网络设备驱动程序从上层传递过来的sk_buff参数获得数据包的有效数据和长度,将有效数据放入临时缓冲区。 对于以太网,有过有效数据的长度小于以太网冲突检测所要求数据帧的最小长度ETH_ZLEN,则给临时缓冲区的末尾填充0。 设置硬件的寄存器,驱使网络设备进行数据发送操作。 数据接收流程 网络设备接收数据的主要方法是由中断引发设备的中断处理函数,中断处理函数判断中断类型,如果为接收中断,则读取接收到的数据,分配sk_buff数据结构和数据缓冲区,将接收 的数据复制到数据缓冲区,并调用netif_rx()函数将sk_buff传递给上层协议。,,网络设备驱动实践,实现一个虚拟网卡s0设备驱动,加载成功后配置ip并测试 加载驱动后通过ifconfig -a 查看是否添加成功 ifconfig s0 34 ping 34 检测网卡是否正常工作,,#undef PDEBUG /* undef it, just in case */ #define PDEBUG(fmt, args.) printk( KERN_DEBUG “snull: “ fmt, # args) #undef PDEBUGG #define PDEBUGG(fmt, args.) /* nothing: its a placeholder */ #include #include #include /* printk() */ #include /* kmalloc() */ #include /* error codes */ #include /* size_t */ #include /* mark_bh */ #include #include /* struct device, and other headers */ #include /* eth_type_trans */ #include /* struct iphdr */ #include /* struct tcphdr */ #include #include #include #include #include #include ,,struct net_device *gecnet_devs;/定义一个网络设备gecnet_devs /网络设备结构体,作为net_device-priv struct gecnet_priv struct net_device_stats stats;/有用的统计信息 int status;/网络设备的状态信息,是发完数据包,还是接收到网络数据包 int rx_packetlen;/接收到的数据包长度 u8 *rx_packetdata;/接收到的数据 int tx_packetlen;/发送的数据包长度 u8 *tx_packetdata;/发送的数据 struct sk_buff *skb;/socket buffer结构体,网络各层之间传送数据都是通过这个结构体来实现的 spinlock_t lock;/自旋锁 ;,,/网络接口的打开函数 int gecnet_open(struct net_device *dev) int i; printk(“call gecnet_openn“); for (i = 0; i dev_addri = 0x33; netif_start_queue(dev);/打开传输队列,这样才能进行数据传输 return 0; int gecnet_release(struct net_device *dev) printk(“call gecnet_releasen“); netif_stop_queue(dev); /当网络接口关闭的时候,调用stop方法,这个函数表示不能再发送数据 return 0; ,,/接包函数 void gecnet_rx(struct net_device *dev, int len, unsigned char *buf) struct sk_buff *skb; struct gecnet_priv *priv = (struct gecnet_priv *) dev-ml_priv; skb = dev_alloc_skb(len+2);/分配一个socket buffer,并且初始化skb-data,skb-tail和skb-head if (!skb) printk(“gecnet rx: low on mem - packet droppedn“); priv-stats.rx_dropped+; return; skb_reserve(skb, 2); /* align IP on 16B boundary */ memcpy(skb_put(skb, len), buf, len);/skb_put是把数据写入到socket buffer /* Write metadata, and then pass to the receive level */ skb-dev = dev; skb-protocol = eth_type_trans(skb, dev);/返回的是协议号 skb-ip_summed = CHECKSUM_UNNECESSARY; /此处不校验 priv-stats.rx_packets+;/接收到包的个数1 priv-stats.rx_bytes += len;/接收到包的长度 printk(“gecnet rx n“); netif_rx(skb);/通知内核已经接收到包,并且封装成socket buffer传到上层 return; ,,/真正的处理的发送数据包 /模拟从一个网络向另一个网络发送数据包 void gecnet_hw_tx(char *buf, int len, struct net_device *dev) struct net_device *dest;/目标设备结构体,net_device存储一个网络接口的重要信息,是网络驱动程序的核心 struct gecnet_priv *priv; if (len ml_priv;/目标dest中的priv priv-rx_packetlen = len; priv-rx_packetdata = buf; printk(“gecnet tx n“); dev_kfree_skb(priv-skb); ,,/发包函数 int gecnet_tx(struct sk_buff *skb, struct net_device *dev) int len; char *data; struct gecnet_priv *priv = (struct gecnet_priv *) dev-ml_priv; if ( skb = NULL) PDEBUG(“tint for %p, skb %pn“, dev, skb); if (skb = NULL) return 0; len = skb-len len;/ETH_ZLEN是所发的最小数据包的长度 data = skb-data;/将要发送的数据包中数据部分 priv-skb = skb; gecnet_hw_t
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 襄州七中考试题目及答案
- 数学四上中考试卷及答案
- 专利实质审查检索报告对比文件类型相关试卷及答案
- 糕点配方多目标优化-第1篇-洞察与解读
- LED故障云诊断技术-洞察与解读
- 《内科呼吸系统》考试复习题库(带答案)
- 创新绩效竞争评估-洞察与解读
- 2025年事业单位招聘卫生类医学检验专业知识试卷(真题模拟)
- 2025内蒙古通辽市奈曼旗招募青年见习人员387人考前自测高频考点模拟试题完整答案详解
- 衡阳地理会考试卷及答案
- 2024年高考真题-历史(天津卷) 含解析
- 华为采购理念与采购运作剖析
- 矿泉水卫生管理制度
- 课件:《中华民族共同体概论》第六讲 五胡入华与中华民族大交融(魏晋南北朝)
- 慢性肺源性心脏病的护理(内科护理学第七版)
- JGT302-2022卷帘门窗规范
- 基础构成设计全套教学课件
- 10t龙门吊安拆施工验收要求
- 慢性化脓性骨髓炎分子病理机制研究
- 商品混凝土公司安全生产标准化管理体系方案资料汇编(2019-2020新标准实施模板)
- 2024年四川省公务员录用考试《行测》试题(网友回忆版)(题目及答案解析)
评论
0/150
提交评论