2013-04-04 177 views

回答

59

ioctl,这意味着“输入输出控制”是一种设备特定的系统调用。在Linux(300-400)中只有少数系统调用,它们不足以表达设备可能具有的所有独特功能。因此,驱动程序可以定义允许用户空间应用程序发送订单的ioctl。然而,ioctl不是很灵活,并且往往会有点混乱(数十个“魔术数字”只能起作用或者不起作用),并且在将缓冲区传递到内核时也可能不安全 - 错误的处理可能会中断事情很容易。

另一种是sysfs界面,在这里建立了一个文件/sys/下,读/写,从和驱动器获取信息。如何设置这个了一个例子:

static ssize_t mydrvr_version_show(struct device *dev, 
     struct device_attribute *attr, char *buf) 
{ 
    return sprintf(buf, "%s\n", DRIVER_RELEASE); 
} 

static DEVICE_ATTR(version, S_IRUGO, mydrvr_version_show, NULL); 

和驱动程序安装过程中:

device_create_file(dev, &dev_attr_version); 

你将不得不为你的设备中的文件/sys/,例如,/sys/block/myblk/version块驱动程序。

另一种更重用的方法是netlink,它是一种通过BSD套接字接口与您的驱动程序通信的IPC(进程间通信)方法。例如,这由WiFi驱动程序使用。然后,您使用libnllibnl3库从用户空间与其通信。

+0

这个答案部分地回答了这个问题。 – 2016-11-29 03:44:00

100

ioctl功能在实现设备驱动程序以在设备上设置配置时非常有用。例如打印机具有配置选项来检查和设置字体,字体大小等。ioctl可用于获取当前字体以及将字体设置为另一个字体。在用户应用程序中,使用ioctl向打印机发送代码,告诉其返回当前字体或将字体设置为新字体。

int ioctl(int fd, int request, ...) 
  1. fd是文件描述符,由开启
  2. request返回的一个是请求代码。例如GETFONT将从打印机获取当前字体,SETFONT将在打印机上设置字体。
  3. 第三个参数是void *。根据第二个论点,第三个可能会或可能不存在。 例如如果第二个参数是SETFONT,则第三个参数可能会将字体名称设置为ARIAL。

因此,现在int请求不仅仅是一个宏,还需要一个生成请求代码,用于由用户应用程序和设备驱动程序模块使用,以确定设备上的哪个配置必须使用。一个用户应用程序使用ioctl发送请求代码,然后使用设备驱动程序模块中的请求代码确定要执行的操作。

的请求的代码具有4个主要部分

1. A Magic number - 8 bits 
    2. A sequence number - 8 bits 
    3. Argument type (typically 14 bits), if any. 
    4. Direction of data transfer (2 bits). 

如果请求代码是setfont程序设置在打印机上的字体,用于数据传输的方向是从用户的应用程序的设备驱动程序模块。用户将字体名称Arial发送到打印机。如果请求代码是GETFONT,则方向是从打印机到用户应用程序。

要生成请求码的Linux提供一些预定义的函数等的宏。

1. _IO(MAGIC, SEQ_NO)两者都是8位,0到255,例如让我们说我们想暂停打印机。 这不需要ADATA转移。所以,我们会生成请求代码如下

#define PRIN_MAGIC 'P' 
    #define NUM 0 
    #define PAUSE_PRIN __IO(PRIN_MAGIC, NUM) 

现在使用的驱动模块ioctl作为

ret_val = ioctl(fd, PAUSE_PRIN); 

对应的系统调用将收到的代码,并暂停打印机。

  • __IOW(MAGIC, SEQ_NO, TYPE)MAGICSEQ_NO同上,但第三部分对下一个参数的类型,回忆的ioctl第三个参数是void *。 W的__IOW指示数据的方向是从用户应用到驱动模块。让我们举个例子,假设 一个告诉打印机字体设置为宋体。

    #define PRIN_MAGIC 'S' 
    #define SEQ_NO 1 
    #define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long) 
    
  • 进一步,

    char *font = "Arial"; 
        ret_val = ioctl(fd, SETFONT, font); 
    

    现在font是一个指针,这意味着它是最好的表示为unsigned long的地址,因此的_IOW第三部分提到类型本身。此外,这个字体地址被传递给设备驱动模块中实现的相应系统调用,如unsigned long,我们需要在使用它之前将其转换为适当的类型。内核空间可以访问用户空间,因此可以工作。像宏这样的其他两个函数分别是__IOR(MAGIC, SEQ_NO, TYPE)__IORW(MAGIC, SEQ_NO, TYPE),其中数据流的方向将分别从内核空间到用户空间和两个方向。

    请让我知道,如果这有助于!

    +0

    我不知道上面的__IOW,__IOR和__IORW函数是否正确(在某些情况下,我的意思是双下划线,在某些情况下,我没有使用双下划线)......感谢您的明确解释! – jcoppens 2016-05-09 19:24:27