zl程序教程

您现在的位置是:首页 >  系统

当前栏目

Linux下用户空间访问I/O端口的相关函数

Linux 函数 用户 访问 相关 空间 端口
2023-09-14 09:15:40 时间

Linux下设置端口权限的系统调用有两个:ioperm和iopl函数。

ioperm

功能描述

为调用进程设置I/O端口访问权限,从端口地址from起始,共设置num个值为turn_on。ioperm的使用需要具有超级用户的权限,只有低端的[0-0x3ff] I/O端口可被设置,要想指定更多端口的权能,可使用iopl函数。

此系统调用只适用于i386体系结构,在许多其它体系结构不存在或将总是返回一个错误。i386是32位版,x86-64是64位版,PPC是苹果电脑版。

函数原型

#include <unistd.h> /* for libc5 */ 
#include <sys/io.h> /* for glibc */

int ioperm(unsigned long from, unsigned long num, int turn_on);

参数说明

from:起始端口地址
num:需要修改权能的端口数
turn_on:端口的新权能位。1为开启,0为关闭

返回值

成功返回0;失败返回-1,并且errno被设为以下的某个值:

EINVALInvalid values for from or num.(参数错误)

EIO:(on ppc) This call is not supported.(不支持此调用)

EPERM:The calling process has insufficient privilege to call ioperm(); the CAP_SYS_RAWIO capability is required.(调用进程没有权限)
 

iopl

功能描述

用于修改当前进程的操作端口的权限。可以用于所有65536个端口的权限。因此,ioperm相当于该调用的子集。

和ioperm一样,这一调用仅适用于i386平台。

iopl()是特定于linux的,不能移植到其他系统中去使用。

函数原型

#include <sys/io.h>

int iopl(int level);

参数说明

level:端口的权限级别。为3时可以读写端口。默认权能级别为0,用户空间不可读写。

返回值

成功返回0;失败返回-1,并且errno被设为以下的某个值:

EINVALlevel is greater than 3.(参数错误,level值大于3)

ENOSYS:This call is unimplemented.(未实现该调用)

EPERM:The calling process has insufficient privilege to call iopl(); the CAP_SYS_RAWIO capability is required.(调用进程没有权限)

outb, outw, outl, outsb, outsw, outsl, inb, inw, inl, insb, insw, insl, outb_p, outw_p, outl_p, inb_p, inw_p, inl_p -  端口I / O

功能描述

  • outb() :I/O 上写入8位数据 (1字节)
  • outw() :I/O 上写入16位数据 (2字节 )
  • outl() :I/O 上写入32位数据 (4字节)
  • inb() :I/O 上读取 8 位数据 (1字节)
  • inw() :I/O 上读取16位数据 (2字节)
  • inl () :I/O 上读取32位数据 (4字节)

这一函数族用于执行低层次的端口输入和输出。out*功能进行端口输出,in*功能进行端口输入;b后缀函数为字节宽度,w后缀函数为字宽;_p后缀函数暂停直到I/O完成。


在申请了I/O端口区域之后,就可以放心地访问,Linux使用inb(p)、inw(p)、insb(p,d,l)、insw(p,d,l)、outb(v,p)、outw(v,p)、outl(v,p)、outsb(p,d,l)、outsl(p,d,l)等宏来访问I/O端口,他们在include/asm/io.h中进行定义。

宏中in表示从端口输入,out表示从输出到端口。

b表示访问字节,w表示访问字,l表示访问长整数,s表示流数据。

参数p表示要访问的I/O端口号,v表示要输出的数值,d表示内存缓存起始地址,l表示输出输入的量。

它们主要是为内核使用而设计的,但是可以从用户空间使用。

必须使用-O或-O2或类似的语言进行编译。这些函数被定义为内联宏,在没有启用优化的情况下不会被替换,这会在链接时导致未解析的引用。

可以使用ioperm(2)或iopl(2)告诉内核允许用户空间应用程序访问相关的I/O端口。如果不这样做,应用程序将收到一个 seg‐mentation 的错。

函数原型(部分)

#include <asm/io.h>

void outb (unsigned char data, unsigned short int port);

void outw (unsigned short data, unsigned short int port);

void outl (unsigned int data, unsigned short int port);

static __iniine unsigned char inb(unsigned short int port);

static __iniine unsigned short inw(unsigned short int port);

static __iniine unsigned int inl(unsigned short int port);