新闻中心

EEPW首页 > 嵌入式系统 > 业界动态 > [ARM笔记]设备驱动概述

[ARM笔记]设备驱动概述

作者:时间:2016-11-24来源:网络收藏

  2.2.3 网络设备驱动

本文引用地址:http://www.eepw.com.cn/article/201611/340660.htm

  网络设备和字符设备、块设备不同,系统对其有专门的处理函数和机制。所有的网络驱动程序都遵循通用的接口,设计时采用的是面向对象的方法。把所有网络设备都抽象为一个接口对象。由数据结构struct device来表示网络设备在内核中的运行情况,即网络设备接口,该结构提供了对所有网络设备的操作集合。它由以dev_base为头指针的设备链表来集中管理所有网络设备。该设备链表中的每个元素代表一个网络设备接口。数据结构device中有很多提供给系统访问和协议层调用的设备方法,包括提供给设备初始化和向系统注册用的init函数、打开和关闭网络设备的open和stop函数、处理数据包发送的函数hard_start_xmit,以及中断处理函数等。一般来讲,一个网络设备最基本的方法有初始化(initialize)、发送和接收。初始化,当把驱动程序载入系统的时候会调用此程序,主要完成检测设备、配置和初始化硬件、初始化device结构中的变量等。设备驱动各函数是网络设备接口层net_device数据结构的具体成员,它通过hard_start_xmit()函数启动发送操作,并通过网络设备上的中断触发接收操作。

  下编写网络设备驱动的主体工作是完成net_device结构体的填充以及成员函数的实现,底层最核心的工作是:发送数据包和接收数据包,接收数据包是由中断触发的。发送数据包函数的典型结构如下——网络设备驱动发送数据包的典型结构。

  int xxx_tx(struct sk_buff *skb, struct net_device *dev)

  {

  int len;

  char *data, shortpkt[ETH_ZLEN];

  /* 获得有效数据指针和长度 */

  data = skb->data;

  len = skb->len;

  if (len < ETH_ZLEN)

  {

  /* 如果帧长小于以太帧最小长度,补0 */

  memset(shortpkt, 0, ETH_ZLEN);

  memcpy(shortpkt, skb->data, skb->len);

  len = ETH_ZLEN;

  data = shortpkt;

  }

  dev->trans_start = jiffies; /* 记录发送时间戳 */

  /* 设置硬件寄存器让硬件把数据包发送出去 */

  xxx_hw_tx(data, len, dev);

  //...

  }

  接收数据包的典型结构如下——网络设备驱动接受数据包的典型结构。

  static void xxx_interrupt(int irq, void *dev_id, struct pt_regs *regs)

  {

  //...

  switch (status &ISQ_EVENT_MASK)

  {

  case ISQ_RECEIVER_EVENT:

  /* 获取数据包 */

  xxx_rx(dev);

  break;

  /* 其他类型的中断 */

  }

  }

  static void xxx_rx(struct xxx_device *dev)

  {

  //...

  length = get_rev_len (...);

  /* 分配新的套接字缓冲区 */

  skb = dev_alloc_skb(length + 2);

  skb_reserve(skb, 2); /* 对齐 */

  skb->dev = dev;

  /* 读取硬件上接收到的数据 */

  insw(ioaddr + RX_FRAME_PORT, skb_put(skb, length), length >> 1);

  if (length &1)

  skb->data[length - 1] = inw(ioaddr + RX_FRAME_PORT);

  /* 获取上层协议类型 */

  skb->protocol = eth_type_trans(skb, dev);

  /*把数据包交给上层 */

  netif_rx(skb);

  /* 记录接收时间戳 */

  dev->last_rx = jiffies;

  //...

  }

  2.3 Linux设备文件的创建

  Linux是一种类Unix系统,Unix的一个基本特点是“一切皆为文件”,它抽象了设备的处理,将所有的硬件设备都像普通文件一样看待,也就是说硬件可以跟普通文件一样打开、关闭和读写。系统中的设备都用一个特殊文件代表,叫做设备文件。在 Linux2.4以后的内核版本中引入了设备文件系统(devfs),所有的设备文件作为一个可以挂装的文件系统,这样就可以被文件系统进行统一管理,从而设备文件就可以挂装到任何需要的地方。

  在前面也讲过,字符设备和块设备都可以通过文件节点来存取,而与字符设备和块设备不同,网络设备的访问是通过Socket而不是设备节点,在系统里根本就不存在网络设备节点,所以在此我们仅讨论块设备和字符设备。

  那么如何在内核中创建设备文件的挂载节点呢?简单的说,设备文件是由系统调用创建的,在命令行中,mknod命令会调用同名的程序来创建文件节点。rename和unlink系统调用可以用于移动和删除节点,相应的命令是mv和rm。在使用cp命令时加上-R或-a参数,可以创建一个与原设备节点具有同样属性的节点。mknod命令,该命令形式如下:

  #mknod [OPTION] NAME TYPE [MAJOR MINOR]

  说明:option选项设置,最常用的就是-m,基本上可以不用;name自定义设备名称;type设备类型,有b和c还有p;MAJOR主设备号;MINOR次设备号。

  mknod命令建立一个目录项和一个特殊文件的对应索引节点。第一个参数Name项是设备的名称,选择一个描述性的设备名称。



关键词: ARM Linux

评论


相关推荐

技术专区

关闭