Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2317832
  • 博文数量: 145
  • 博客积分: 8668
  • 博客等级: 中将
  • 技术积分: 3922
  • 用 户 组: 普通用户
  • 注册时间: 2007-03-09 21:21
个人简介

work hard

文章分类

全部博文(145)

文章存档

2016年(1)

2015年(1)

2014年(1)

2013年(12)

2012年(3)

2011年(9)

2010年(34)

2009年(55)

2008年(20)

2007年(9)

分类: LINUX

2008-12-18 13:18:49

Linux下设置端口权限的系统调用有两个:iopermiopl

 

一、iopermiopl介绍。

1.ioperm

该系统调用的介绍参考了以下链接中的内容:

http://blog.chinaunix.net/u2/76419/showart_1404294.html

 

功能描述:

为调用进程设置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:端口的新权能位。1为开启,0为关闭。


返回说明:

成功执行时,返回0。失败返回-1errno被设为以下的某个值

EINVAL:参数无效
EIO
:这一调用不被支持
EPERM
:调用进程权能不足。

 

2. iopl

功能描述:该调用用于修改当前进程的操作端口的权限。可以用于所有65536个端口的权限。因此,ioperm相当于该调用的子集。和ioperm一样,这一调用仅适用于i386平台。

 

用法:

#include

   int iopl(int level);

参数:

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

返回说明:成功执行时,返回0。失败返回-1errno被设为以下的某个值

EINVALlevel值大于3
ENOSYS
:未实现该调用

EPERM:调用进程权能不足。

 

二、程序示例

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.4RH9)的内核上,当端口值大于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);

      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翻转。

注:这里再次使用0x3FF端口,主要个人对端口的理解还不很深入,其他高于0x3FF的端口进行测试的时候,没有得到既定的结果。这里权且还使用这个端口,借此对iopl的用法熟悉一下即可。至于在真正使用中,如果系统的某个端口是可以进行配置的,那么执行这个程序应该是可以得到既定结果的。

阅读(7319) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

Godbach2009-04-08 10:55:03

其实这些接口本身内核态编程时也在用。同时也导出来给用户态用,让应用程序就可以进行端口的读写。

chinaunix网友2009-04-08 04:24:54

INTERESTING, THX