linux驱动程序之虚拟以太网设备vmeth

Posted on 2006-10-05 15:05 倚槛追风 阅读(197) 评论(0)   编辑  收藏 引用 所属分类: 嵌入式linux,驱动程序
       在《linux驱动程序之hello world》中我们编写了一个简单的能运行与linux内核态的模块,虽然它没有打印“Hello World”,我们还是称之为“hello模块”。Hello模块仅仅是一个演示,它除了打印两个字符串之外,什么也不能做了,但它具有所有可加载模块的 共性。
      今天我们对它进行扩充,使之进化为vmeth模块- 虚拟的以太网设备 , 这个vmeth模块向linux内核注册成为一个以太网设备,通过ifconfig命令来查看,它和其他的以太网设备如eth0没有什么区别。但这个 vmeth模块依然什么功能也没有,它仅仅将linux的TCP/IP协议栈送来的数据包打印出来(通过dmesg查看),然后将数据包free。
    为了区分这个以太网设备和普通的以太网设备,我将vmeth设备的名字命名为vmeth。当你将vmeth.ko加载到内核后,执行ifconfig -a 你将看到一个vmeth0设备,它就是vmeth模块注册的设备。OK,依次执行ifconfig vmeth0 192.168.12.12和ping 192.168.12.1,然后dmesg看看是否出现类似字样
ifconfig vmeth0 输出如下:
vmeth0    Link encap:Ethernet  HWaddr 00:00:00:00:00:00
          inet addr:192.168.12.12  Bcast:192.168.12.255  Mask:255.255.255.0
          inet6 addr: fe80::200:ff:fe00:0/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 b)  TX bytes:0 (0.0 b)

ping包后dmesg输出如下:
[ 6350.708587] vmeth receive a skb
[ 6350.708601] skb->length = 42
[ 6350.708604] [0000]ff ff ff ff ff ff 00 00 00 00 00 00 08 06 00 01
[ 6350.708617] [0010]08 00 06 04 00 01 00 00 00 00 00 00 c0 a8 0c 17
[ 6350.708629] [0020]00 00 00 00 00 00 c0 a8 0c 01

vmeth0接收到了协议栈发来的arp包,
  1  #include  < linux / init.h >
  2  #include  < linux / kernel.h >
  3  #include  < linux / module.h >
  4  #include  < linux / if .h >
  5  #include  < linux / version.h >
  6  #include  " vmeth.h "
  7 
  8  extern   struct  net_device *  alloc_etherdev( int  sizeof_priv);
  9  struct  net_device  * g_dev  =  NULL;
 10 
 11  /* vmeth模块初始化 */
 12  static   int  __init vmeth_module_init( void )
 13  {
 14      printk(KERN_DEBUG  " init module/n " );
 15      
 16      g_dev  =  alloc_etherdev( sizeof ( struct  vmeth_priv));
 17       if ( ! g_dev)
 18           goto  failed;
 19      
 20      memset(( struct  vmeth_priv * )g_dev -> priv,  0 sizeof ( struct  vmeth_priv));
 21      strncpy(g_dev -> name, VMETH_NAME, IFNAMSIZ);
 22 
 23      g_dev -> init  =  vmeth_dev_init;
 24  #if  (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0))
 25      g_dev -> destructor  =  free_netdev;
 26  #else
 27      g_dev -> features  |=  NETIF_F_DYNALLOC;
 28  #endif
 29       /* 向内核注册网络设备 */
 30       if (register_netdev(g_dev))
 31           goto  register_err;
 32      
 33       return  OK;
 34  register_err:
 35      kfree(g_dev);    
 36  failed:
 37       return  NOK;
 38  }
 39 
 40  static   void  __exit vmeth_module_exit( void )
 41  {
 42       if (g_dev)
 43      {
 44           /* unregister 网络设备 */
 45          unregister_netdev(g_dev);
 46          g_dev  =  NULL;
 47          printk( " unregister netdev/n " );
 48      }
 49      printk(KERN_DEBUG  " exit modules/n " );
 50  }
 51 
 52  /* 网络设备初始化 */
 53  static   int  vmeth_dev_init( struct  net_device  * dev)
 54  {
 55      printk(KERN_DEBUG  " init net_dev/n " );
 56      dev -> hard_start_xmit  =  vmeth_send;
 57      dev -> open  =  vmeth_open;
 58      dev -> stop  =  vmeth_stop;
 59       return  OK;
 60  }
 61 
 62  /* 打开网络设备 ifconfig vmeth0 up */
 63  static   int  vmeth_open( struct  net_device  * dev)
 64  {
 65      netif_start_queue(dev);
 66      printk(KERN_DEBUG  " net device %s opened/n " , dev -> name);
 67      
 68       return  OK;
 69  }
 70  /* 关闭网络设备 ifconfig vmeth0 down */
 71  static   int  vmeth_stop( struct  net_device  * dev)
 72  {
 73      netif_stop_queue(dev);
 74      printk(KERN_DEBUG  " net device %s stopped/n " , dev -> name);
 75 
 76       return  OK;
 77  }
 78  /* 从内核接收到一个数据包 */
 79  static   int  vmeth_send( struct  sk_buff  * skb,  struct  net_device  * dev)
 80  {
 81      printk( " vmeth receive a skb/n " );
 82 
 83  #ifdef DEBUG_SKB
 84      print_skb(skb);
 85  #endif     
 86      kfree_skb(skb);
 87       return   0 ;
 88  }
 89 
 90  #ifdef DEBUG_SKB
 91  void  print_skb( struct  sk_buff  * skb)
 92  {
 93       int  i;
 94      
 95      printk(KERN_DEBUG  " skb->length = %d " , skb -> len);
 96       for ( i  =   0 ; i  <  skb -> len; i ++  )
 97      {
 98           if ( (i & 0x0f ==   0 )
 99          {
100              printk( " /n[%04x] " , i);
101          }
102          printk( " %2.2x  " , skb -> data[i]);
103      }
104      printk( " /n " );
105  }
106  #endif
107 
108  module_init(vmeth_module_init);
109  module_exit(vmeth_module_exit);
110 
目前vmeth0设备的物理地址还是全零,我将在后续版本中继续补充,增加vmeth的功能。
      我要下载代码vmeth.tgz(注意下载后将压缩包重命名为vmeth.tgz,使用tar -zxf vmeth.tgz命令解压),
另外一定要注意修改Makefile中的KERNEL_SRC,使其指向你的内核源码。
 
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值