Chinaunix首页 | 论坛 | 博客
  • 博客访问: 80518
  • 博文数量: 19
  • 博客积分: 575
  • 博客等级: 中士
  • 技术积分: 203
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-03 20:06
个人简介

好好学习,天天向上

文章分类

全部博文(19)

分类: LINUX

2011-04-08 12:13:57

 

驱动提供read,write是为了和应用程序进行数据的交流,应用程序也可以简单地发送相关命令给驱动执行,如LED驱动点亮LED的命令。一般而言,这些是通过IOCTL实现的。

用户空间的ioctl:

#include

int ioctl(int fildes, int request, ... /* arg */);

 

驱动使用不同的版本:

linux/fs.h

int (*ioctl) (struct inode* inode,struct file* filp,unsigned int cmd,unsigned long param);

当接到不正确的cmd时,应当返回-ENOTTY

 

做个最简单的ioctl

base_char.c(添加ioctl的实现,并将ioctl添加到file_operations)

int base_char_ioctl(struct inode* inode,struct file* filp,unsigned int cmd,unsigned long param)

{

  printk("base char: ioctl : cmd : %d\n",cmd);

  switch(cmd)

  {

    case 0:

      /*do some thing*/

      break;

    case 1:

      /*do some thing*/

      break;

    default:

      /*do some thing*/

      return -NOTTY;

  }

  return 0;

}

 

struct file_operations fop=

{

  .owner=THIS_MODULE,

  .open=base_char_open,

  .release=base_char_release,

  .ioctl=base_char_ioctl,

};

 

test.c

#include

#include

#include

#include

#include

#include

 

 

int main()

{

  int fd=open("/dev/base_char",O_RDWR);

  int count=0;

  if(fd<0)

  {

    perror("");

    return -1;

  }

  ioctl(fd,0,0);

  close(fd);

  return 0;

}

 

测试结果如下(系统日志中):

Apr  8 10:39:03 localhost kernel: base char register successful!

Apr  8 10:39:05 localhost kernel: base char open!

Apr  8 10:39:05 localhost kernel: base char: ioctl : cmd : 0

Apr  8 10:39:05 localhost kernel: base char close!

 

我无法想像向错误的设备发出正确的命令这种情形的实现,但是内核开发者既然提出了,那这样的事情是可能存在的。避免造成损失,内核提供了让我们的cmd在系统中唯一的方法,使用魔数(也有叫幻数的).

下面介绍怎么构造一个唯一的cmd.

linux/ioctl.h

type:number: direction: size

type是魔数,8位,在参考Documentation/ioctl-number.txt后选择一个唯一没有使用的。

number命令序号,8

direction:数据传输方向,可以是_IOC_NONE,_IOC_READ,_IOC_WRITE

size:数据大小,1314位,可以忽略,好处是可以检测应用程序的错误

开始建立cmd:

_IO(type,number)(给没有参数的命令)

_IOR(type, number, size)(给从驱动中读数据的)

_IOW(type, number,size) (给写数据)

_IOWR(type, number,size)(给双向传送)

 

我选择的魔数是 ‘o’,那么我的cmd这样来建立

#define BASE_CHAR_TYPE  ‘o’

#define BASE_CHAR_CMD_READ _IOR(BASE_CHAR_TYPE,0,1)

#define BASE_CHAR_CMD_WRITE _IOW(BASE_CHAR_TYPE,1,1)

 

把这些宏定义放到驱动和应用程序中就可以使用了。

 

不要以为每个命令都可以使用,事实上在调用ioctl之前内核会自己处理下,它留了一些自己使用的cmd,如果你的正好和它预留的一样,那就悲剧了,你不会看到任何的给那个命令的请求, 并且应用程序获得某些不期望的东西。

FIOCLEX

设置 close-on-exec 标志(File IOctl Close on EXec) 设置这个标志使文件描述符被关闭。

FIONCLEX

清除 close-no-exec 标志(File IOctl Not CLose on EXec)

FIOQSIZE

这个命令返回一个文件或者目录的大小; 当用作一个设备文件,它返回一个 ENOTTY 错误.

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