1.3、从用户空间访问I/O端口
1.2节介绍的函数主要是提供给驱动使用,但它们也可在用户空间使用,至少在PC机上可以。GNU C 库在 <sys/io.h> 中定义它们。如果在用户空间使用这些函数,必须满足下列条件:
1)、程序必须使用-O选项编译来强制扩展内联函数
2)、必须使用ioperm和iopl系统调用(#include <sys/perm.h>) 来获得进行操作I/O端口的权限。ioperm 为获取单个端口的操作许可,iopl 为获取整个I/O空间许可。这2个函数都是x86特有的
3)、程序必须以root来调用ioperm或者iopl,或者其父进程(祖先)必须以root获得的端口操作权限
如果平台不支持ioperm和iopl系统调用,通过使用/dev/prot设备文件,用户空间仍然可以存取I/O 端口。但是要注意的是,这个文件的定义也是依赖平台的。
1.4、字串操作
除了一次传递一个数据的I/O操作,某些处理器实现了一次传递一序列数据(单位可以是字节、字和双字)的特殊指令。这些所谓的字串指令,它们完成任务比一个C语言循环更快。下列宏定义实现字串操作,在某些体系上,它们通过使用单个机器指令实现;但如果目标处理器没有进行字串I/O指令,则通过执行一个紧凑的循环实现。
字串函数的原型是:
/* insb:从I/O端口port读取count个数据(单位字节)到以内存地址addr为开始的内存空间 */ |
注意:使用字串函数时,它们直接将字节流从端口中读取或写入。当端口和主机系统有不同的字节序时,会导致不可预期的结果。使用 inw读取端口应在必要时自行转换字节序,以匹配主机字节序。
1.5、暂停式I/O操作函数
由于处理器的速率可能与外设(尤其是低速设备)的并不匹配,当处理器过快地传送数据到或自总线时,这时可能就会引起问题。解决方法是:如果在I/O 指令后面紧跟着另一个相似的I/O 指令,就必须插入一个小的延时。为此,Linux提供了暂停式I/O操作函数,这些函数的名子只是在非暂停式I/O操作函数(前面提到的那些I/O操作函数都是非暂停式的)名后加上_p ,如inb_p、outb_p等。大部分体系都支持这些函数,尽管它们常常被扩展为与非暂停 I/O 同样的代码,因为如果体系使用一个合理的现代外设总线,没有必要额外暂停。
以下是ARM体系暂停式I/O宏的定义:
#define outb_p(val,port) outb((val),(port)) |
因为ARM使用内部总线,就没有必要额外暂停,所以暂停式的I/O函数被扩展为与非暂停式I/O同样的代码。
1.6、平台依赖性
由于自身的特性,I/O指令高度依赖于处理器,非常难以隐藏各体系间的不同。因此,大部分的关于端口 I/O的源码是平台依赖的。以下是x86和ARM所使用函数的总结:
IA-32 (x86)
x86_64
这个体系支持本章介绍的所有函数;port参数的类型为unsigned short。
ARM
端口映射到内存,并且支持本章介绍的所有函数;port参数的类型为unsigned int;字串函数用C语言实现。
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) | Powered by Discuz! 7.0.0 |