linux哪个文件定义io地址,Linux 文件IO

本系列文章节选自本人所著《Linux下C语言应用编程》。

本系列文章,所需代码请从以下地址下载:

http://download.csdn.net/download/scyangzhu/5129027

1.1.1   ioctl

ioctl 函数是I / O操作的杂物箱。不能用本章中其他函数表示的I / O操作通常都能用ioctl表示。终端I / O是ioctl 的最大使用方面,主要用于设备的I / O控制。例如:串口线上传送的数据通过read、write来操作,而串口的波特率、校验位、停止位可以通过ioctl来设置。再例如,使用ioctl来控制光驱的弹出操作等。

#include

int ioctl(int fd, int cmd, . . . ) ;

功能:要求设备完成某种操作

返回:若出错则为- 1,若成功则为其他值。

参数:

fd:要操控的设备的文件描述符

cmd:要求设备完成的操作。一般会是针对该设备的头文件中定义的宏

第3个参数:针对cmd操作的参数

使用范例(使用ioctl控制CDROM):

ioctl.c

1 #include

2 #include

3 #include

4 #include

5

6 int main(void)

7 {

8         int fd =open("/dev/cdrom", O_RDONLY | O_NONBLOCK);

14 //     ioctl(fd, CDROM_LOCKDOOR, 0);

15        if (!ioctl(fd, CDROMEJECT, NULL)) {

16                 printf("eject cdromsucceed\n");

17        } else {

18                 printf("eject cdromfailed\n");

19        }

20 /*

21        sleep(5);

22 //     ioctl(fd, CDROM_LOCKDOOR, 1);

23        if (!ioctl(fd, CDROMCLOSETRAY, NULL)) {

24                 printf("close cdromsucceed\n");

25        } else {

26                 printf("close cdromfailed\n");

27        }

28 */

29        return 0;

30 }

运行结果:

[dennis@localhost chap02]$ sudo./ioctl

eject cdrom succeed

代码分析:

1行包含的头文件linux/cdrom.h中,定义了光驱这种设备所支持的操作的宏

8行调用open打开光驱,得到对应光驱的文件描述符。由于open光驱时,可能光驱中没有光盘,因此需要使用O_NONBLOCK选项,否则open会失败

15行调用ioctl,向光驱发出CDROMEJECT命令(弹出光盘命令)。用户可看到光盘被成功弹出

1.1.2   select

read函数可以监控1个文件描述符(例如:键盘)是否有输入,当键盘没有输入时,read将阻塞,直到用户从键盘输入数据,read成功返回。用相同的方法可以监控鼠标是否有输入。但要同时监控鼠标和键盘是否有输入,这个方法就无能为力了。如下面程序所示:

1 fd = open(“/dev/input/mice”,O_RDONLY);  // /dev/input/mice是鼠标的设备文件

2 read(0, buf, 100);

3 read(fd, buf, 100);

这是因为,当read 键盘时若无输入,则程序阻塞在第2行,此时即使鼠标有输入,程序也没有机会执行第3行去获得鼠标的输入。

这种情况下,需要使用select同时监控多个文件描述符

#include

intselect(int maxfd, fd_set *readset, fd_set *writeset, fd_set *exceptset, conststruct timeval *timeout)

功能:同时监控多个文件描述符上是否有输入、输出、错误

参数:

maxfd:表示要检测的描述符个数,因此其值应为最大描述符+1

readset:被监控是否有输入的文件描述符集。不监控时,设为NULL

writeset:被监控是否可以输出的文件描述符集。不监控时,设为NULL

exceptset:被监控是否有错误产生的文件描述符集。不监控时,设为NULL

timeval:监控超时时间。设置为NULL,表示一直阻塞到有文件描述符被监控到有指定变化

返回值:失败,返回-1;成功,返回readset 、writeset、exceptset集中所有有指定变化的文件描述符的数目(若是因超时而返回,返回值为0)。

注:readset 、writeset 、exceptset3 个描述符集指针均是值- 结果参数。调用时,被监控描述字相应位需置1;返回时未就绪描述字相应位会被清0,而就绪描述字相应位会被置1

以下几个系统定义的宏,会与select配套使用

FD_ZERO(&rset):清0文件描述符集rset所有位

FD_SET(4,&rset):设置文件描述符集rset的bit4

FD_CLR(fileno(stdin),&rset):清0文件描述符集rset的bit0

FD_ISSET(socketfd,&rset):若文件描述符集rset中对应socketfd的位置1,返回真;反之,返回假

使用范例(同时监控键盘和鼠标是否有输入):

select.c

1 #include

3 #include

4 #include

5 #include

6

7 #define MAXNUM 100

8

9 int main(void)

10 {

11        fd_set rfds;

12        struct timeval tv;

13        int retval, fd;

14        char buf[MAXNUM];

15

16        fd = open("/dev/input/mice", O_RDONLY);

21        while (1) {

22                 FD_ZERO(&rfds);

23                 FD_SET(0, &rfds);

24                 FD_SET(fd,&rfds);

25                 tv.tv_sec = 5;

26                 tv.tv_usec = 0;

27

28                 retval = select(fd + 1,&rfds, NULL, NULL, &tv);

29                 if (retval < 0)

30                        printf("error\n");

31                 if (retval == 0)

32                         printf("No datawithin 5 seconds\n");

33                 if (retval > 0) {

34                         if (FD_ISSET(0,&rfds)) {

35                               printf("Data is available from keyboard now\n");

36                                read(0, buf,MAXNUM);

37                         }

38                         if (FD_ISSET(fd,&rfds)) {

39                                printf("Data is available from mouse now\n");

40                                 read(fd, buf,MAXNUM);

41                         }

42                 }

43        }

44        return 0;

45 }

执行结果:

1 [dennis@localhost chap02]$  sudo ./select

2 a  (此处,从键盘输入a和回车)

3 Data is available from keyboard now

4 Data is available from mouse now  (此处单击鼠标左键)

5 Data is available from mouse now

6 No data within 5 seconds    (此处一直没有任何操作)

结果分析:

16行打开鼠标对应的文件描述符

22行清空文件描述符集rfds

23-24行将rfds中对应键盘和鼠标的位置1

25-26行设置超时时间

28行调用select同时监控键盘和鼠标是否可读,并设置超时时间为5秒

当用户从键盘输入时,34行结果为真,执行35行打印结果(见执行结果第3行)

当用户单击鼠标时,38行结果为真,执行39行打印结果(见执行结果第4、5行)

当用户在5秒内没有任何操作,将导致28行返回0,从而执行32行打印结果(见执行结果第6行)

特别说明:select以相同方式对待以非阻塞方式和以阻塞方式打开的文件描述符。即:被select监控的文件描述符即使是以非阻塞方式打开的,如果没有实际数据可读,select也将阻塞,而不是返回。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值