字符设备控制技术

Posted on 2015-02-16 18:23  Bumble_Bee  阅读(179)  评论(0编辑  收藏  举报

引入:
  有时对设备不仅仅是进行一些读写操作,还需要进行一些对设备的控制,比如LED的点燃与熄灭,电机的转速等。那就需要使用到ioctl这个系统调用。先来看看他的函数原型:
  int    ioctl(int fd,unsigned int cmd, ...);
  参数:

    fd:字符设备文件的文件描述符
    cmd:要对设备执行的命令
    ...:当命令需要参数时填写,不需要则不填写
  主要讲一下cmd这个参数。命令从实质上来讲就是一个32位整数,通常这个数会被分为几段分别为类型(也叫幻数,8位)、序号、参数传递方向、参数长度。Linux提供了一些宏来拼接这些数字,规范命令的合理性。例如:
    不带参数的命令:_IO(type,nr);
    从设备中读:_IOR(type,nr,datatype);
    从设备中写:_IOW(type,nr,datatype);
  type(幻数)为设备类型,用来区分不同设备;nr为设备序号,区分同种设备的不同个体;datatype读或写数据的类型。
  例:

    #define     MEM_MAGIC    ‘m’    //定义幻数
    #define    MEM_RESTART    _IO(MEM_MAGIC,0)
    #define    MEM_SET    _IOW(MEM_MAGIC,0,int)
  一般驱动里的ioctl函数通过switch语句实现,范例代码:

 1 long mem_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 2 {
 3     switch(cmd)
 4     {
 5         case MEM_RESTART:
 6             printk("restart device\n");
 7             return 0;
 8         case MEM_SET:
 9             printk("arg is %d\n",arg);
10             return 0;
11         default:
12             return -EINVAL;
13     }
14 }

  用户应用程序调用ioctl的实现方法:

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "memdev.h"

int main()
{
    int fd;
    fd = open("/dev/memdev0", O_RDWR);

    ioctl(fd, MEM_SET,2048);
    
    ioctl(fd, MEM_RESTART);

    return 0;

}

memdev.h

#define MEM_MAGIC 'm'
#define MEM_RESTART _IO(MEM_MAGIC,0)
#define MEM_SET _IOW(MEM_MAGIC,1,int)