IOCTL Linux 设备驱动程序
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15807846/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
IOCTL Linux device driver
提问by flashdisk
Can anyone explain me,
谁能给我解释一下
- What is
IOCTL
? - What is it used for?
- How can I use it?
- Why can't I define new function that does the same work as
IOCTL
?
- 什么是
IOCTL
? - 它是干什么用的?
- 我怎样才能使用它?
- 为什么我不能定义与 做相同工作的新函数
IOCTL
?
采纳答案by Inductiveload
An ioctl
, which means "input-output control" is a kind of device-specific system call. There are only a few system calls in Linux (300-400), which are not enough to express all the unique functions devices may have. So a driver can define an ioctl which allows a userspace application to send it orders. However, ioctls are not very flexible and tend to get a bit cluttered (dozens of "magic numbers" which just work... or not), and can also be insecure, as you pass a buffer into the kernel - bad handling can break things easily.
An ioctl
,意思是“输入-输出控制”是一种特定于设备的系统调用。Linux 中只有少数系统调用(300-400),不足以表达设备可能具有的所有独特功能。因此,驱动程序可以定义一个 ioctl,它允许用户空间应用程序向它发送命令。然而,ioctl 不是很灵活,而且往往会变得有点混乱(几十个“神奇数字”不管用……还是不行),而且也可能不安全,因为您将缓冲区传递到内核中 - 处理不当可能会破坏事情容易。
An alternative is the sysfs
interface, where you set up a file under /sys/
and read/write that to get information from and to the driver. An example of how to set this up:
另一种选择是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);
And during driver setup:
在驱动程序设置期间:
device_create_file(dev, &dev_attr_version);
You would then have a file for your device in /sys/
, for example, /sys/block/myblk/version
for a block driver.
然后,您将在 中为您的设备创建一个文件/sys/
,例如,/sys/block/myblk/version
用于块驱动程序。
Another method for heavier use is netlink, which is an IPC (inter-process communication) method to talk to your driver over a BSD socket interface. This is used, for example, by the WiFi drivers. You then communicate with it from userspace using the libnl
or libnl3
libraries.
另一种更频繁使用的方法是 netlink,它是一种 IPC(进程间通信)方法,可通过 BSD 套接字接口与驱动程序通信。例如,这由 WiFi 驱动程序使用。然后,您可以使用libnl
或libnl3
库从用户空间与它通信。
回答by anukalp
The ioctl
function is useful for implementing a device driver to set the configuration on the device. e.g. a printer that has configuration options to check and set the font family, font size etc. ioctl
could be used to get the current font as well as set the font to a new one. A user application uses ioctl
to send a code to a printer telling it to return the current font or to set the font to a new one.
该ioctl
函数对于实现设备驱动程序以在设备上设置配置很有用。例如,具有检查和设置字体系列、字体大小等配置选项的打印机ioctl
可用于获取当前字体以及将字体设置为新字体。用户应用程序用于ioctl
向打印机发送代码,告诉它返回当前字体或将字体设置为新字体。
int ioctl(int fd, int request, ...)
fd
is file descriptor, the one returned byopen
;request
is request code. e.gGETFONT
will get the current font from the printer,SETFONT
will set the font on the printer;- the third argument is
void *
. Depending on the second argument, the third may or may not be present, e.g. if the second argument isSETFONT
, the third argument can be the font name such as"Arial"
;
fd
是文件描述符,由open
;返回的那个request
是请求代码。例如GETFONT
将从打印机获取当前字体,在打印机上SETFONT
设置字体;- 第三个参数是
void *
。根据第二个参数,第三个可能存在也可能不存在,例如,如果第二个参数是SETFONT
,则第三个参数可以是字体名称,例如"Arial"
;
int request
is not just a macro. A user application is required to generate a request code and the device driver module to determine which configuration on device must be played with. The application sends the request code using ioctl
and then uses the request code in the device driver module to determine which action to perform.
int request
不仅仅是一个宏。用户应用程序需要生成请求代码和设备驱动程序模块,以确定必须使用设备上的哪个配置。应用程序使用发送请求代码ioctl
,然后使用设备驱动程序模块中的请求代码来确定要执行的操作。
A request code has 4 main parts
请求代码有 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).
If the request code is SETFONT
to set font on a printer, the direction for data transfer will be from user application to device driver module (The user application sends the font name "Arial"
to the printer).
If the request code is GETFONT
, direction is from printer to the user application.
如果请求代码是SETFONT
在打印机上设置字体,则数据传输的方向将是从用户应用程序到设备驱动程序模块(用户应用程序将字体名称发送"Arial"
到打印机)。如果请求代码是GETFONT
,则方向是从打印机到用户应用程序。
In order to generate a request code, Linux provides some predefined function-like macros.
为了生成请求代码,Linux 提供了一些预定义的类似函数的宏。
1._IO(MAGIC, SEQ_NO)
both are 8 bits, 0 to 255, e.g. let us say we want to pause printer.
This does not require a data transfer. So we would generate the request code as below
1._IO(MAGIC, SEQ_NO)
两者都是 8 位,0 到 255,例如让我们说我们要暂停打印机。这不需要数据传输。所以我们将生成如下请求代码
#define PRIN_MAGIC 'P'
#define NUM 0
#define PAUSE_PRIN __IO(PRIN_MAGIC, NUM)
and now use ioctl
as
现在ioctl
用作
ret_val = ioctl(fd, PAUSE_PRIN);
The corresponding system call in the driver module will receive the code and pause the printer.
驱动模块中相应的系统调用将接收代码并暂停打印机。
__IOW(MAGIC, SEQ_NO, TYPE)
MAGIC
andSEQ_NO
are the same as above, andTYPE
gives the type of the next argument, recall the third argument ofioctl
isvoid *
. W in__IOW
indicates that the data flow is from user application to driver module. As an example, suppose we want to set the printer font to"Arial"
.
__IOW(MAGIC, SEQ_NO, TYPE)
MAGIC
and 和SEQ_NO
上面一样,并且TYPE
给出了下一个参数的类型,回忆ioctl
is的第三个参数void *
。W in__IOW
表示数据流是从用户应用程序到驱动程序模块。例如,假设我们要将打印机字体设置为"Arial"
.
#define PRIN_MAGIC 'S'
#define SEQ_NO 1
#define SETFONT __IOW(PRIN_MAGIC, SEQ_NO, unsigned long)
further,
更远,
char *font = "Arial";
ret_val = ioctl(fd, SETFONT, font);
Now font
is a pointer, which means it is an address best represented as unsigned long
, hence the third part of _IOW
mentions type as such. Also, this address of font is passed to corresponding system call implemented in device driver module as unsigned long
and we need to cast it to proper type before using it. Kernel space can access user space and hence this works. other two function-like macros are __IOR(MAGIC, SEQ_NO, TYPE)
and __IORW(MAGIC, SEQ_NO, TYPE)
where the data flow will be from kernel space to user space and both ways respectively.
Nowfont
是一个指针,这意味着它是一个地址,最好表示为unsigned long
,因此第三部分_IOW
提到了类型。此外,这个字体地址被传递给设备驱动模块中实现的相应系统调用unsigned long
,我们需要在使用之前将其转换为正确的类型。内核空间可以访问用户空间,因此这是有效的。其他两个类似函数的宏是__IOR(MAGIC, SEQ_NO, TYPE)
,__IORW(MAGIC, SEQ_NO, TYPE)
数据流将分别从内核空间到用户空间以及双向。
Please let me know if this helps!
请让我知道这可不可以帮你!