一、协议栈层次对比

设备无关层到驱动层的体系结构

1)、网络协议接口层向网络层协议提供提供统一的数据包收发接口,不论上层协议为ARP还是IP,都通过dev_queue_xmit()函数发送数据,并通过netif_rx()函数接受数据。这一层的存在使得上层协议独立于具体的设备。
2)、网络设备接口层向协议接口层提供统一的用于描述具体网络设备属性和操作的结构体net_device,该结构体是设备驱动功能层中各函数的容器。实际上,网络设备接口层从宏观上规划了具体操作硬件的设备驱动功能层的结构。
3)、设备驱动功能层各函数是网络设备接口层net_device数据结构的具体成员,是驱使网络设备硬件完成相应动作的程序,他通过hard_start_xmit()函数启动发送操作,并通过网络设备上的中断触发接受操作。
4)、网络设备与媒介层是完成数据包发送和接受的物理实体,包括网络适配器和具体的传输媒介,网络适配器被驱动功能层中的函数物理上驱动。对于Linux系统而言,网络设备和媒介都可以是虚拟的。

网络协议接口层:主要进行数据包的收发。

驱动程序代码:

/*************************************************************************
> File Name: s3c_virnet.c
> Author:
> Mail:
> Created Time: 2016年11月09日 星期三 13时27分51秒
************************************************************************/
#include <linux/module.h>
#include <linux/errno.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/in.h>
#include <linux/skbuff.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/init.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/ip.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/irq.h> static struct net_device *vnet_dev; static void virnet_tx_packet(struct sk_buff *skb, struct net_device *dev)
{
unsigned char *type;
struct iphdr *ih;
__be32 *saddr, *daddr, tmp;
unsigned char tmp_dev_addr[ETH_ALEN];
struct ethhdr *ethhdr; struct sk_buff *rx_skb; /* 对调MAC地址 */
ethhdr = (struct ethhdr *)skb->data;
memcpy(tmp_dev_addr,ethhdr->h_dest,ETH_ALEN);
memcpy(ethhdr->h_dest,ethhdr->h_source,ETH_ALEN);
memcpy(ethhdr->h_source,tmp_dev_addr,ETH_ALEN); /* */
ih = (struct iphdr *)(skb->data+sizeof(struct ethhdr));
saddr = &ih->saddr;
daddr = &ih->daddr; tmp = *saddr;
*saddr = *daddr;
*daddr = tmp; type = skb->data + sizeof(struct ethhdr)+sizeof(struct iphdr); *type = ; ih->check = ;
ih->check = ip_fast_csum((unsigned char*)ih,ih->ihl); rx_skb = dev_alloc_skb(skb->len + );
skb_reserve(rx_skb,);
memcpy(skb_put(rx_skb,skb->len),skb->data,skb->len); rx_skb->dev = dev;
rx_skb->protocol = eth_type_trans(rx_skb,dev);
rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
dev->stats.rx_bytes += skb->len;
dev->stats.rx_packets++;
netif_rx(rx_skb); }
static int virnet_send_packet(struct sk_buff *skb, struct net_device *dev)
{
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len; netif_stop_queue(dev); //停止该网卡的队列
/*把skb的数据写入网卡*/
//dev_kfree_skb(skb); //释放skb
netif_wake_queue(dev); //数据发送成功后唤醒队列
/* 构造出一个假的sk_buff */ virnet_tx_packet(skb,dev); return ;
} static int s3c_virnet_init(void)
{ /* 分配一个net_device结构体 */
vnet_dev = alloc_netdev(, "vnet%d", ether_setup); /* 设置 */
vnet_dev->hard_start_xmit = virnet_send_packet; /* MAC地址设置 */
vnet_dev->dev_addr[] = 0x07;
vnet_dev->dev_addr[] = 0x05;
vnet_dev->dev_addr[] = 0x06;
vnet_dev->dev_addr[] = 0x07;
vnet_dev->dev_addr[] = 0x08;
vnet_dev->dev_addr[] = 0x09; /* 添加下面的配置后才能ping通 */
vnet_dev->flags |= IFF_NOARP;
vnet_dev->features |= NETIF_F_NO_CSUM; /* 注册 */
register_netdev(vnet_dev); return ;
} static void s3c_virnet_exit(void)
{
unregister_netdev(vnet_dev); free_netdev(vnet_dev);
} module_init(s3c_virnet_init);
module_exit(s3c_virnet_exit);
MODULE_LICENSE("GPL");

sd

嵌入式Linux驱动学习之路(二十五)虚拟网卡驱动程序的更多相关文章

  1. 嵌入式Linux驱动学习之路(二十六)DM9000C网卡驱动程序

    基于DM9000C的原厂代码修改dm9000c的驱动程序. 首先确认内存的基地址 iobase. 确定中断号码. 打开模块的初始化函数定义. 配置内存控制器的相应时序(结合DM9000C.C的手册). ...

  2. 嵌入式Linux驱动学习之路(二十四)Nor Flash驱动程序

    Nor Flash和Nand Flash的不同: 类型 NOR Flash  Nand Flash  接口 RAM-like,引脚多 引脚少 容量 小(1M.2M...) 大(512M.1G) 读 简 ...

  3. 嵌入式Linux驱动学习之路(二十二)用内存模拟磁盘

    安装驱动后,可在/dev/目录下发现已经生成了相应的设备文件. 格式化设备:mkdosfs /dev/ramblock. 挂载设备. 读写设备 . 驱动程序代码: /***************** ...

  4. 嵌入式Linux驱动学习之路(二十)USB设备驱动

    USB在接入系统的时候,以0的设备ID和主机通信,然后由主机为其分配新的ID. 在主机端,D+和D-都是下拉接地的.而设备端的D-接上拉时,表明此设备为高速设备:12M/s. D+接上拉时则是全速设备 ...

  5. 嵌入式Linux驱动学习之路(二十三)NAND FLASH驱动程序

    NAND FLASH是一个存储芯片. 在芯片上的DATA0-DATA7上既能传输数据也能传输地址. 当ALE为高电平时传输的是地址. 当CLE为高电平时传输的是命令. 当ALE和CLE都为低电平时传输 ...

  6. 嵌入式Linux驱动学习之路(二十七)字符设备驱动的另一种写法

    之前讲的字符设备驱动程序,只要有一个主设备号,那么次设备号无论是什么都会和同一个 struct file_operations 结构体对应. 而本节课讲的是如何在设备号相同的情况下,让不同的次设备号对 ...

  7. 嵌入式Linux驱动学习之路(二十一)字符设备驱动程序总结和块设备驱动程序的引入

    字符设备驱动程序 应用程序是调用C库中的open read write等函数.而为了操作硬件,所以引入了驱动模块. 构建一个简单的驱动,有一下步骤. 1. 创建file_operations 2. 申 ...

  8. 嵌入式Linux驱动学习之路(二)u-boot体验

    u-boot工程简介 现在的u-boot支持PowerPC.ARM.X86.MIPS体系结构的上百种开发板,已经称为功能最多.灵活性最强,并且开发最积极的开源Bootloader.目前由DENX的Wo ...

  9. 嵌入式Linux驱动学习之路(十二)按键驱动-poll机制

    实现的功能是在读取按键信息的时候,如果没有产生按键,则程序休眠在read函数中,利用poll机制,可以在没有退出的情况下让程序自动退出. 下面的程序就是在读取按键信息的时候,如果5000ms内没有按键 ...

随机推荐

  1. 让我们山寨一张Windows Azure Global的壁纸

    用过国际版Azure的同学都见过一个显示了机器中主要信息的壁纸,而这个壁纸是通过Sysinternals的一款叫做bginfo来实现的,这款软件的好处是对于批量管理主(虚拟)机的管理员和使用方都很实用 ...

  2. MySQL实现两张表数据的同步

    有两张表A和B,要求往A里面插入一条记录的同时要向B里面也插入一条记录,向B里面插入一条记录的同时也向A插入一条记录.两张表的结构不同,需要将其中几个字段对应起来.可以用下面的触发器实现. 表A的触发 ...

  3. JAVA 日期格式工具类DateUtil.java

    DateUtil.java package pers.kangxu.datautils.utils; import java.text.SimpleDateFormat; import java.ut ...

  4. JAVA Thread线程异常监控

    一.场景描述:单线程程序可以用try...catch捕获程序的异常,而在多线程程序的时候是无法使用try...catch捕获. 示例1:多线程发生异常,无法使用try...catch捕获问题 publ ...

  5. hdu-2444-二分图判定+最大分配

    The Accomodation of Students Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K ( ...

  6. 《连载 | 物联网框架ServerSuperIO教程》1.4种通讯模式机制。附小文:招.NET开发,结果他转JAVA了,一切都是为了生活

    参考文章: 1.SuperIO通讯框架介绍,含通信本质 2.C#跨平台物联网通讯框架ServerSuperIO(SSIO) 一.感慨 上大学的时候,没有学过C#,花了5块钱在地坛书市买了一本教程,也就 ...

  7. 【JavaWeb】Spring+SpringMVC+MyBatis+SpringSecurity+EhCache+JCaptcha 完整Web基础框架(前言)

    一直希望能够搭建一个完整的,基础Web框架,方便日后接一些外快的时候,能够省时省力,终于花了一周的时间,把这个东西搞定了.特此写下此博客,一来是纪念,二来是希望能够为别人提供方便.顺带说一下,恩,组合 ...

  8. Css3新特性应用之形状

    一.自适应椭圆 * border-radius特性:    * 可以单独指定水平和垂直半径,并且值可以是百分比,用/(斜杠)分隔这两个值即可(可以实现自适应宽度椭圆).    * 还可以单独指定四个角 ...

  9. ReactNative中iOS和Android的style分开设置教程

    reactnative可以编辑iOS程序也可以编辑Android程序, 而且80%的代码都可以重用. 及有些文件是两个系统通用的, 相信大家也都清楚了. 但是也许大家会遇到一些屏幕布局的问题, 最常遇 ...

  10. React Native学习笔记

    React 是使用ES6 ,支持JSX语法, 开发组件化web或native的工具. 现阶段使用Babel工具转换成ES5 代码. 组件通过props属性传递不变化的内容,UI通过state属性变动来 ...