科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道Linux内核对I/O端口的管理实现(上) (1)

Linux内核对I/O端口的管理实现(上) (1)

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本文主要从内核实现的角度分析Linux 2.4.0内核IO子系统中对IO端口资源的管理的实现原理。本文是为那些想要深入分析Linux的IO子系统的读者和设备驱动程序开发人员而写的。

作者:linuxaid.com 来源:linuxaid.com 2007年10月19日

关键字: 管理 I/O 内核 Linux

  • 评论
  • 分享微博
  • 分享邮件

本文主要从内核实现的角度分析Linux 2.4.0内核IO子系统中对IO端口资源的管理的实现原理。本文是为那些想要深入分析Linux的IO子系统的读者和设备驱动程序开发人员而写的。

几乎每一种外设都是通过读写设备上的寄存器来进行的。外设寄存器也称为“I/O端口”,通常包括:控制寄存器、状态寄存器和数据寄存器三大类,而且一个外设的寄存器通常被连续地编址。CPU对外设IO端口物理地址的编址方式有两种:一种是I/O映射方式(I/O-mapped),另一种是内存映射方式(Memory-mapped)。而具体采用哪一种则取决于CPU的体系结构。

有些体系结构的CPU(如,PowerPC、m68k等)通常只实现一个物理地址空间(RAM)。在这种情况下,外设I/O端口的物理地址就被映射到CPU的单一物理地址空间中,而成为内存的一部分。此时,CPU可象访问一个内存单元那样访问外设I/O端口,而不需要设立专门的外设I/O指令。这就是所谓的“内存映射方式”(Memory-mapped)。

而另外一些体系结构的CPU(典型地如X86)则为外设专门实现了一个单独地地址空间,称为“I/O地址空间”或者“I/O端口空间”。这是一个与CPU地RAM物理地址空间不同的地址空间,所有外设的I/O端口均在这一空间中进行编址。CPU通过设立专门的I/O指令(如X86的IN和OUT指令)来访问这一空间中的地址单元(也即I/O端口)。这就是所谓的“I/O映射方式”(I/O-mapped)。与RAM物理地址空间相比,I/O地址空间通常都比较小,如x86 CPU的I/O空间就只有64KB(0-0xffff)。这是“I/O映射方式”的一个主要缺点。

Linux将基于I/O映射方式的或内存映射方式的I/O端口通称为“I/O区域”(I/O region)。在讨论对I/O区域的管理之前,我们首先来分析一下Linux是如何实现“I/O资源”这一抽象概念的。

Linux对I/O资源的描述

Linux设计了一个通用的数据结构resource来描述各种I/O资源(如:I/O端口、外设内存、DMA和IRQ等)。该结构定义在include/linux/ioport.h头文件中:

  struct resource {
	const char *name;
	unsigned long start, end;
	unsigned long flags;
	struct resource *parent, *sibling, *child;
  };

各成员的含义如下:

1. name指针:指向此资源的名称。

2. start和end:表示资源的起始物理地址和终止物理地址。它们确定了资源的范围,也即是一个闭区间[start,end]。

3. flags:描述此资源属性的标志(见下面)。

4. 指针parent、sibling和child:分别为指向父亲、兄弟和子资源的指针。

属性flags是一个unsigned long类型的32位标志值,用以描述资源的属性。比如:资源的类型、是否只读、是否可缓存,以及是否已被占用等。下面是一部分常用属性标志位的定义(ioport.h):

/*
 * IO resources have these defined flags.
 */
#define IORESOURCE_BITS		0x000000ff	/* Bus-specific bits */

#define IORESOURCE_IO		0x00000100	/* Resource type */
#define IORESOURCE_MEM		0x00000200
#define IORESOURCE_IRQ		0x00000400
#define IORESOURCE_DMA		0x00000800

#define IORESOURCE_PREFETCH	0x00001000	/* No side effects */
#define IORESOURCE_READONLY	0x00002000
#define IORESOURCE_CACHEABLE	0x00004000
#define IORESOURCE_RANGELENGTH	0x00008000
#define IORESOURCE_SHADOWABLE	0x00010000
#define IORESOURCE_BUS_HAS_VGA	0x00080000

#define IORESOURCE_UNSET	0x20000000
#define IORESOURCE_AUTO		0x40000000
#define IORESOURCE_BUSY		0x80000000
	/* Driver has marked this resource busy */

指针parent、sibling和child的设置是为了以一种树的形式来管理各种I/O资源。

Linux对I/O资源的管理

Linux是以一种倒置的树形结构来管理每一类I/O资源(如:I/O端口、外设内存、DMA和IRQ)的。每一类I/O资源都对应有一颗倒置的资源树,树中的每一个节点都是一个resource结构,而树的根结点root则描述了该类资源的整个资源空间。

基于上述这个思想,Linux在kernel/Resource.c文件中实现了对资源的申请、释放及查找等操作。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章