Linux下设置端口权限的系统调用—ioperm和iopl

Linux下设置端口权限的系统调用—ioperm和iopl

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


一、ioperm和iopl介绍。

1.ioperm

【ioperm系统调用】

功能描述:
为调用进程设置I/O端口访问权能。ioperm的使用需要具有超级用户的权限,只有低端的[0-0x3ff] I/O端口可被设置,要想指定更多端口的权能,可使用iopl函数。这一调用只可用于i386平台。


用法:
#include /* for libc5 */
#include /* for glibc */

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


参数:
from:起始端口地址。
num:需要修改权能的端口数。
turn_on:端口的新权能位。


返回说明:
成功执行时,返回0。失败返回-1,errno被设为以下的某个值
EINVAL:参数无效
EIO:这一调用不被支持
EPERM:调用进程权能不足


2. iopl

【iopl系统调用】

功能描述:
改变当前进程I/O端口的权能级别。对于允许8514兼容的X服务器在Linux上运行,这一系统调用必不可少。X服务器要求访问所有 65536个I/O端口,ioperm调用不能满足这种需求。另外,为了获取不受限制的I/O端口访问权,以较高级别的I/O权能级运行将允许进程禁止中断。这可能导致系统的崩毁,不推荐那样做。一般用户的I/O访问级是0。本系统调用只应用于i386平台。


用法:
#include

int iopl(int level);


参数:
level:新的I/O访问级,范围是[0~3]。


返回说明:
成功执行时,返回0。失败返回-1,errno被设为以下的某个值
EINVAL:参数无效,level大于3
ENOSYS:平台不支持这个系统调用
EPERM:调用进程没有权限使用iopl,要求CAP_SYS_RAWIO权能



二、程序示例

1. ioperm.c

操作低于0x3FF的端口

该程序首先设置0x3FF端口的读写权限,然后读出原先的值,然后将原值的LSB翻转并写回端口,并在此读取端口值。

/*Godbach. Dec 18, 2008

Description:This function is used to test ioperm()*/

#include

#include

#include


#define PORT_ADDR 0x3FF


int main(void)

{

int ret;

char port_val;


/*set r/w permission of port_addr on, only one port*/

ret = ioperm(PORT_ADDR, 1, 1);

if(ret < 0){

perror("ioperm set error");

return 0;

}

port_val = inb(PORT_ADDR);

printf("Original value of port 0x%x is : %.2x\n", PORT_ADDR, port_val);



/*reverse the least significant bit */

outb(port_val^0x01, PORT_ADDR);

port_val = inb(PORT_ADDR);

printf("Current value of port 0x%x is : %.2x\n", PORT_ADDR, port_val);



/*set r/w permission of PORT_ADDR off, only one port*/

ret = ioperm(PORT_ADDR, 1, 0);

if(ret <

0){

perror("ioperm set error");

return 0;

}

return 0;

}


程序执行的结果是:

[root@localhost misc-progs]# ./a.out

Original value of port 0x3ff is : 00

Current value of port 0x3ff is : 01

[root@localhost misc-progs]# ./a.out

Original value of port 0x3ff is : 01

Current value of port 0x3ff is : 00

该程序执行几次,将进行几次的LSB翻转。

这里有一个问题值得注意:在2.4(RH9)的内核上,当端口值大于0x3FF时,执行该程序则会报错:ioperm set error: Invalid argument。即IO端口的值设置有问题,超出了限制。但是在2.6内核下并没有报错,而且执行结果也符合程序既定的结果。但是man ioperm中仍然说明了0x3FF的限制。暂且存疑。


2. iopl.c

该程序可以操作所有65536个端口。

该程序首先设置0x3FF端口的读写权限,然后读出原先的值,然后将原值的LSB翻转并写回端口,并在此读取端口值。

代码如下:

/*Godbach. Dec 18, 2008

Description:This function is used to test iopl()*/

#include

#include

#include


#define PORT_ADDR 0x3FF


int main(void)

{

int ret;

char port_val;


/*set r/w permission of all 65536 ports*/

ret = iopl(3);/*打开linux读写端口的服务*/

if(ret < 0){

perror("iopl set error");

return 0;

}

port_val = inb(PORT_ADDR);

printf("Original value of port 0x%x is : %.2x\n", PORT_ADDR, port_val);



/*reverse the least significant bit */

outb(port_val^0x01, PORT_ADDR);

port_val = inb(PORT_ADDR);

printf("Current value of port 0x%x is : %.2x\n", PORT_ADDR, port_val);



/*set r/w permission of all 65536 ports*/

ret = iopl(0);

if(ret < 0){

perror("iopl set error");

return 0;

}

return 0;

}

程序执行结果:

[root@linux misc-progs]# ./a.out

Original value of port 0x3ff is : 01

Current value of port 0x3ff is : 00

[root@linux misc-progs]# ./a.out

Original value of port 0x3ff is : 00

Current value of port 0x3ff is : 01

该程序执行几次,将进行几次的LSB翻转。

相关文档
最新文档