1. Function of the ioctl Function
A function for device control is provided in the kernel source code, and device control is implemented through the ioctl function, while data transmission is achieved through read/write.
Example: For instance, the control of the camera’s operating mode is implemented through ioctl, while the reading and writing of camera data is done through the read/write functions.
The kernel standardizes the control protocol.
2. Analysis of the ioctl Function
2.1 Application Layer ioctl Function
#include <sys/ioctl.h>
int ioctl(int fd, unsigned long request, ...);
Function: Device control function Parameters: @ fd : Opened file descriptor @ request : Request code/command code Detailed analysis of the request code is below @ ... : Variable parameters If a third parameter is passed, it is an address Return value: Returns 0 on success, -1 on failure, and errno is set
2.2 Kernel Layer ioctl Function
.unlocked_ioctl = myled_ioctl,
long myled_ioctl(struct file *file, unsigned int cmd , unsigned long arg); Function: Kernel layer ioctl function Parameters: @ cmd : Request code @ arg : Value passed as a variable parameter
2.3 Detailed Analysis of Request Codes
The kernel standardizes the control-related protocols. ====== ================================== bits meaning ====== ================================== 31-30 -----> Direction bits 00 - no parameters: uses _IO macro 10 - read: _IOR 01 - write: _IOW 11 - read/write: _IOWR
29-16 -----> Specifies the size of the third parameter of the ioctl function size of arguments
15-8 -----> Each driver has a unique ASCII character for identification ascii character supposedly unique to each driver
7-0 -----> Function, for example: the LED has two functions 0 means off 1 means on function # ====== ==================================
How to Encapsulate Command Codes:
#define _IO(type,nr) _IOC(0,(type),(nr),0)
#define _IOR(type,nr,size) _IOC(2,(type),(nr),(sizeof(size)))
#define _IOW(type,nr,size) _IOC(1,(type),(nr),(sizeof(size)))
#define _IOWR(type,nr,size) _IOC(3,(type),(nr),(sizeof(size)))
#define _IOC(dir,type,nr,size) (((dir) << 30) | ((type) << 8) | ((nr) << 0) | ((size) << 16)) | | | | Direction Type (unique character) Function code Size of the third parameter [31:30] [15:8] [7:0] [29:16]

// Example
#define LED_ON _IOW('L',1,int) // 01 00_0000_0000_0100 0100_1100 0000_0001
#define LED_OFF _IOW('L',0,int) // 01 00_0000_0000_0100 0100_1100 0000_0000
3. ioctl Example
ioctl_example.h File
#ifndef IOCTL_EXAMPLE_H
#define IOCTL_EXAMPLE_H
#include <linux/ioctl.h>
// Define magic number to distinguish different devices
#define IOCTL_MAGIC 'k'
// Define ioctl commands
#define IOCTL_SET_VALUE _IOW(IOCTL_MAGIC, 0, int)
#define IOCTL_GET_VALUE _IOR(IOCTL_MAGIC, 1, int)
#define IOCTL_MAX_NR 1
// Device name
#define DEVICE_NAME "ioctl_example"
#endif
ioctl_module.c File
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/uaccess.h>
#include "ioctl_example.h"
struct ioctl_device { int value; struct cdev cdev;} dev;
static dev_t dev_num;
static int ioctl_open(struct inode *inode, struct file *file) { file->private_data = &dev; printk(KERN_INFO "ioctl device opened\n"); return 0;}
static int ioctl_release(struct inode *inode, struct file *file) { printk(KERN_INFO "ioctl device closed\n"); return 0;}
// ioctl handler function
static long ioctl_unlocked(struct file *file, unsigned int cmd, unsigned long arg) { struct ioctl_device *dev = file->private_data; int ret = 0; int val; // Check command validity if (_IOC_TYPE(cmd) != IOCTL_MAGIC) return -ENOTTY; if (_IOC_NR(cmd) > IOCTL_MAX_NR) return -ENOTTY; // Handle based on command type switch (cmd) { case IOCTL_SET_VALUE: // Get data from user space if (copy_from_user(&val, (int __user *)arg, sizeof(val))) { return -EFAULT; } dev->value = val; printk(KERN_INFO "Set value to %d\n", dev->value); break; case IOCTL_GET_VALUE: // Send data to user space val = dev->value; if (copy_to_user((int __user *)arg, &val, sizeof(val))) { return -EFAULT; } printk(KERN_INFO "Get value %d\n", dev->value); break; default: return -ENOTTY; } return ret;}
static const struct file_operations fops = { .owner = THIS_MODULE, .open = ioctl_open, .release = ioctl_release, .unlocked_ioctl = ioctl_unlocked,};
static int __init ioctl_init(void) { int ret; // Allocate device number ret = alloc_chrdev_region(&dev_num, 0, 1, DEVICE_NAME); if (ret < 0) { printk(KERN_ERR "Failed to allocate device number\n"); return ret; } // Initialize character device cdev_init(&dev.cdev, &fops); dev.cdev.owner = THIS_MODULE; // Add character device to system ret = cdev_add(&dev.cdev, dev_num, 1); if (ret < 0) { printk(KERN_ERR "Failed to add cdev\n"); unregister_chrdev_region(dev_num, 1); return ret; } dev.value = 0; printk(KERN_INFO "ioctl example module loaded\n"); return 0;}
static void __exit ioctl_exit(void) { cdev_del(&dev.cdev); unregister_chrdev_region(dev_num, 1); printk(KERN_INFO "ioctl example module unloaded\n");}
module_init(ioctl_init);
module_exit(ioctl_exit);
ioctl_user.c File
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "ioctl_example.h"
int main() { int fd; int value, ret;
// Open device fd = open("/dev/" DEVICE_NAME, O_RDWR); if (fd < 0) { perror("Failed to open device"); return EXIT_FAILURE; } // Set value value = 123; ret = ioctl(fd, IOCTL_SET_VALUE, &value); if (ret < 0) { perror("IOCTL_SET_VALUE failed"); close(fd); return EXIT_FAILURE; } printf("Set value to %d\n", value); // Get value ret = ioctl(fd, IOCTL_GET_VALUE, &value); if (ret < 0) { perror("IOCTL_GET_VALUE failed"); close(fd); return EXIT_FAILURE; } printf("Got value: %d\n", value); // Set a different value again value = 456; ret = ioctl(fd, IOCTL_SET_VALUE, &value); if (ret < 0) { perror("IOCTL_SET_VALUE failed"); close(fd); return EXIT_FAILURE; } printf("Set value to %d\n", value); // Get value again ret = ioctl(fd, IOCTL_GET_VALUE, &value); if (ret < 0) { perror("IOCTL_GET_VALUE failed"); close(fd); return EXIT_FAILURE; }
printf("Got value: %d\n", value); // Close device close(fd); return EXIT_SUCCESS;}
Please open in the WeChat client