读写I/O内存资源

由于在某些平台上,对I/O内存和系统内存有不同的访问处理,因此为了确保跨平台的兼容性,Linux实现了一系列读写I/O内存资源的函数,这些函数在不同的平台上有不同的实现。但在x86平台上,读写I/O内存与读写RAM无任何差别。如下所示(include/asm-i386/io.h):

#define readb(addr) (*(volatile unsigned char *) __io_virt(addr�

#define readw(addr) (*(volatile unsigned short *) __io_virt(addr�

#define readl(addr) (*(volatile unsigned int *) __io_virt(addr�

#define writeb(b,addr) (*(volatile unsigned char *) __io_virt(addr) = (b�

#define writew(b,addr) (*(volatile unsigned short *) __io_virt(addr) = (b�

#define writel(b,addr) (*(volatile unsigned int *) __io_virt(addr) = (b�

#define memset_io(a,b,c)memset(__io_virt(a),(b),(c�

#define memcpy_fromio(a,b,c) memcpy

#define memcpy_toio(a,b,c)memcpy(__io_virt(a),(b),(c�

上述定义中的宏__io_virt()仅仅检查虚地址addr是否是核心空间中的虚地址。具体的实现函数在arch/i386/lib/iodebug.c文件。

显然,在x86平台上访问I/O内存资源与访问系统主存RAM是无差别的。但是为了保证驱动程序的跨平台的可移植性,我们应该使用上面的函数来访问I/O内存资源,而不应该通过指向核心虚地址的指针来访问。

大多数平台都区分8位、16位和32位宽度的I/O端口的。Linux在include/asm/io.h头文件(对于i386平台就是include/asm-i386/io.h)中定义了一系列读写不同宽度I/O端口的宏函数。如下所示:

(1)读写8位宽的I/O端口

unsigned char inb(unsigned port);

void outb(unsigned char value,unsigned port);

其中,port参数指定I/O端口空间中的端口地址。在大多数平台上(如x86)它都是unsigned short类型的,其它的一些平台上则是unsigned int类型的。显然,端口地址的类型是由I/O端口空间的大小来决定的。

(2)读写16位宽的I/O端口

unsigned short inw(unsigned port);

void outw(unsigned short value,unsigned port);

(3)读写32位宽的I/O端口

unsigned int inl(unsigned port);

void outl(unsigned int value,unsigned port);

Linux同样在io.h文件中定义了字符串I/O读写函数:

(1)8位宽的字符串I/O操作

void insb(unsigned port,void * addr,unsigned long count);

void outsb(unsigned port ,void * addr,unsigned long count);

(2)16位宽的字符串I/O操作

void insw(unsigned port,void * addr,unsigned long count);

void outsw(unsigned port ,void * addr,unsigned long count);

(3)32位宽的字符串I/O操作

void insl(unsigned port,void * addr,unsigned long count);

void outsl(unsigned port ,void * addr,unsigned long count);

在一些平台上(典型地如X86),对于慢速外设来说,如果CPU读写其I/O端口的速度太快,可能会发生丢失数据。这就要在两次连续的I/O操作之间插入时延。Linux在io.h头文件中定义了带延迟的I/O读写函数,以XXX_p命名,如:inb_p()、outb_p()等。下面以out_p()为例进行分析。

将io.h中的宏定义__OUT(b,"b"char)展开后可得如下定义:

extern inline void outb(unsigned char value, unsigned short port) {

__asm__ __volatile__ ("outb %" "b " "0,%" "w" "1"

: : "a" (value), "Nd" (port));

}

extern inline void outb_p(unsigned char value, unsigned short port) {

__asm__ __volatile__ ("outb %" "b " "0,%" "w" "1"

__FULL_SLOW_DOWN_IO

: : "a" (value), "Nd" (port));

}

可以看出,outb_p()函数的实现中被插入了宏__FULL_SLOWN_DOWN_IO,以实现微小的延时。宏__FULL_SLOWN_DOWN_IO在头文件io.h中一开始就被定义:

#ifdef SLOW_IO_BY_JUMPING

#define __SLOW_DOWN_IO "

jmp 1f

1:jmp 1f

1:"

#else

#define __SLOW_DOWN_IO "

outb %%al,$0x80"

#endif

#ifdef REALLY_SLOW_IO

#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO

__SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO

#else

#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO

#endif

显然,__FULL_SLOW_DOWN_IO就是一个或四个__SLOW_DOWN_IO(根据是否定义了宏REALLY_SLOW_IO来决定),而宏__SLOW_DOWN_IO则被定义成毫无意义的跳转语句或写端口0x80的操作(根据是否定义了宏SLOW_IO_BY_JUMPING来决定)。

linux内核 端口,Linux内核中IO端口资源管理相关推荐

  1. gulp修改服务器端口,在gulp-nodemon中设置端口有什么用处?

    我使用gulp-nodemon,因为它最明显的实用程序.在gulp-nodemon中设置端口有什么用处? Nodemon是一个实用程序,它将监视源中的所有更改 并自动重新启动服务器. 但是我不理解一种 ...

  2. cmd查看某个服务器端口状态,cmd中检测端口是否处于监听状态 | IT博客

    1.查看本地端口监听状态命令:netstat -an Local Address:本地地址 Foreign Address :外地的地址 State:LISTENING该端口在监听外部连接,estab ...

  3. CC2530学习笔记(2)—— IO端口基本操作实验(按键控制亮灯)

    CC2530学习笔记(2)-- IO端口基本操作(按键控制亮灯) 关于CC2530的IO端口基本知识.IO端口有关寄存器的介绍和描述请参照:CC2530学习笔记(1)--  IO端口 电路原理图如图1 ...

  4. Linux内核网络协议栈7-socket端口管理

    一.前情回顾 上一节<socket 地址绑定 >中提到,应用程序传递过来的端口在内核中需要检查端口是否可用: if (sk->sk_prot->get_port(sk, snu ...

  5. 【linux开发】IO端口和IO内存的区别及分别使用的函数接口

    IO端口和IO内存的区别及分别使用的函数接口 每个外设都是通过读写其寄存器来控制的.外设寄存器也称为I/O端口,通常包括:控制寄存器.状态寄存器和数据寄存器三大类.根据访问外设寄存器的不同方式,可以把 ...

  6. Linux系统IO端口,Linux系统对IO端口和IO内存的管理

    五.Linux下访问IO端口 对于某一既定的系统,它要么是独立编址.要么是统一编址,具体采用哪一种则取决于CPU的体系结构. 如,PowerPC.m68k等采用统一编址,而X86等则采用独立编址,存在 ...

  7. linux mips 时钟中断,Linux内核中地时钟中断.pdf

    Linux内核中地时钟中断 Linux 内核中的时钟中断 第七章 Linux 内核的时钟中断 (By 詹荣开,NUDT) Copyright © 2003 by 詹荣开 E-mail:zhanrk@ ...

  8. Linux中不同进程同一个端口,linux系统实现多个进程监听同一个端口

    通过 fork 创建子进程的方式可以实现父子进程监听相同的端口. 方法:在绑定端口号(bind函数)之后,监听端口号之前(listen函数),用fork()函数生成子进程,这样子进程就可以克隆父进程, ...

  9. linux 内核 虚拟地址,linux内核中的虚拟到物理地址转换

    以下用于将Linux内核中的虚拟地址转换为物理地址.但是这是什么意思? 我对装配知识非常有限 163 #define __pv_stub(from,to,instr,type) 164 __asm__ ...

最新文章

  1. 一致 先验分布 后验分布_浅谈Loki分布式架构中的一致性哈希
  2. 获取子页面iframe的点击事件及iframe跨域的交互
  3. How can I generate database tables from C# classes?
  4. BufferFsStream
  5. 洛谷 P1136 迎接仪式 解题报告
  6. [PAT乙级]1036 跟奥巴马一起编程
  7. 来了!汇总数据库行业最新招聘、热门资讯、精选文章...
  8. laravel application 容器app
  9. java 图形化技术 哪个好_纳滤和反渗透技术哪个好?
  10. specification java_Java Specification类代码示例
  11. vue m3u8格式 实现监控直播
  12. 联想一体机计算机桌面不显示,联想一体机关闭屏幕_联想一体机怎么关屏幕
  13. 漫步微积分二十九——微积分基本定理
  14. 计算机基础1模拟题,计算机基础模拟题1(有答案)
  15. 宁波银行金融科技面试
  16. AAAI2021:面向交通流预测的时空融合图神经网络
  17. D35 876. Middle of the Linked List
  18. 第六次:收集分析40个游戏广告(宣传图、落地页等)
  19. DEBUG 使用RELEASE文件的 DLL
  20. 哈佛凌晨4点半【收藏】

热门文章

  1. 使用U盘引导安装CentOS操作系统
  2. bug in MicrosoftAjax.debug.js
  3. 滤镜应用——拼图效果
  4. 用java完成一个模块_Java 9 揭秘(3. 创建你的第一个模块)
  5. fluent 命令流_FLUENT混合流体中颗粒运动模拟
  6. mysql更新索引不影响业务_mysql 索引是否能提高UPDATE,DELETE,INSERT 处理速度
  7. python2.7安装教程win7_win7 64位环境下,为python2.7 安装pip
  8. php sql 长字符串 查找被包含的短字符串_PHP字符串
  9. 人工智能导论 王万良教授_FCES2019 panel4:人工智能的第一堂课究竟讲什么?
  10. wrong elf class: elfclass32_薇娅倾情推荐亿健ELF跑步机,价格优惠大还为粉丝争取福利! - 消费...