Timeline
Timeline
2025-12-02
init
This article introduces the basic concepts, application scenarios, and underlying implementation mechanisms of hotplug in Linux systems. It discusses in detail the interaction process between the kernel and user space through uevent events, including the characteristics of device management tools such as devfs, mdev, and udev, as well as the kernel's use of the kobject_uevent() function to send events and a brief application of the udevadm command.
Linux Driver Notes
| Table of Contents | Links |
|---|---|
| 1. Linux Driver Framework | |
| 2. Linux Driver Loading Logic | |
| 3. Character Device Basics | |
| 4. Concurrency and Race Conditions | |
| 5. Advanced Character Device Progression | |
| 6. Interrupts | |
| 7. Platform Bus | |
| 8. Device Tree | |
| 9. Device Model | |
| 10. Hot Plug | |
| 11. pinctrl Subsystem | |
| 12. GPIO Subsystem | |
| 13. Input Subsystem | |
| 14. Single Bus | |
| 15. I2C | |
| 16. SPI | |
| 17. UART | |
| 18. PWM | |
| 19. RTC | |
| 20. Watchdog | |
| 21. CAN | |
| 22. Network Device | |
| 23. ADC | |
| 24. IIO | |
| 25. USB | |
| 26. LCD |
Hot Swap
**Hot swap refers to the ability to safely insert or remove hardware devices while the equipment is running, without shutting down or restarting the system.**This means you can insert or remove hardware components (such as USB devices, expansion cards, hard drives, etc.) on a computer or other electronic device without shutting down or interrupting ongoing operations.
The main purpose of hot swap is to provide convenience and flexibility. With hot swap, you can quickly replace or add hardware devices without stopping ongoing tasks. This is very useful in many scenarios, such as:
- USB devices: You can insert or remove USB devices such as mice, keyboards, printers, storage devices, etc., at any time without restarting the system.
- Hard drives: In some servers or storage systems, you can add or replace hard drives while running to expand storage capacity or replace faulty drives.
- Expansion cards: You can insert or remove expansion cards such as graphics cards, network cards, or sound cards on a computer to meet different needs or upgrade hardware performance.
To support hot-plug functionality, both hardware devices and the system must have the corresponding support. On the hardware side, device interfaces must be designed to allow insertion and removal without damaging the device or system. The system needs to provide appropriate drivers and management functions to correctly configure and recognize devices during insertion and removal.
The mechanism of hot-plug
Hot-plug is an interaction between the kernel and user space, achieved by calling user space programs (such ashotplug、udevandmdev). When the kernel needs to notify user space that a hot-plug event has occurred, it calls this user space program to implement the interaction.
In the Linux kernel, the hot-plug mechanism supports the dynamic insertion and removal of components such as USB devices, PCI devices, and even CPUs. This mechanism connects underlying hardware, kernel space, and user space programs, and has been continuously evolving and improving. The device file system is a mechanism for managing device files. In Linux, there are three common device file systems: devfs, mdev, and udev.
devfs: devfs is a kernel-based dynamic device file system that first appeared in Linux kernel 2.3.46. It handles device files by dynamically creating and managing device nodes. However, devfs had some limitations and performance issues, and was removed starting from Linux kernel 2.6.13.mdev: mdev is alightweight hot-plug device user space program, commonly used in embedded Linux systems. It is a simplified version of udev, using theuevent_helpermechanism to handle device insertion and removal events. mdev calls the corresponding user program to create device nodes when a device is inserted.udev: udev is currentlya widely used hot-plug device user space program on PCs. It is based on thenetlinkmechanism, listening to uevents sent by the kernel to handle device insertion and removal. udev can dynamically create and manage device nodes, and load appropriate drivers when a device is inserted. It provides rich configuration options, allowing users to flexibly manage device files.
Kernel sends events to user space
kobject_uevent()
kobject_ueventis a function in the Linux kernel used to generate and send uevent events. It is a way for udev and other device management tools to communicate with the kernel.
1 | // lib/kboject_uevent.c |
Parameter description:
kobj: The kernel object (kobject) to send the uevent eventaction: Indicates the action that triggers the uevent, which can be device insertion, removal, attribute change, etc. Below are some common action parameter values. These action types are used to describe different events occurring on the device. By passing the corresponding action type as the action parameter to thekobject_ueventfunction, the corresponding uevent event can be triggered to notify user-space udev to perform the corresponding operation.KOBJ_ADD: Indicatesdevice addition or insertion operation, indicating adding an object to the kernel object system.KOBJ_REMOVE: Indicatesdevice removal or extraction operation, indicating deleting an object from the kernel object system.KOBJ_CHANGE: Indicatesdevice attribute modification operation, indicating changes to the kernel object, such as attribute modification, etc.KOBJ_MOVE: Indicatesdevice movement operation, i.e., the device moves from one location to another.KOBJ_ONLINE: indicatesdevice online operation, i.e., the device transitions from offline to online state, making it accessible.KOBJ_OFFLINE: indicatesdevice offline operation, i.e., the device transitions from online to offline state, making it inaccessible.KOBJ_BIND: indicatesattaching a device to a kernel objectKOBJ_UNBIND: indicatesdetaching a device from a kernel objectKOBJ_MAX: indicates the maximum value of an enumeration type, typically used to represent no operation.
kobject_ueventThe main function of this function is to generate a uevent event in the kernel and send it to user-space udev via the netlink mechanism. When this function is called, the kernel encapsulates the relevant device information and event type into a uevent message and sends it to user space through a netlink socket.
User-space udev receives these uevent messages and performs corresponding actions based on the device information and event type in the messages, such as creating or deleting device nodes, loading or unloading drivers, etc.
Example
1 |
|
udevadm command
udevadmis a command-line tool for interacting with the udev device manager. It provides a series of subcommands for querying and managing devices, triggering uevent events, and performing other udev-related operations. Some commonudevadmsubcommands and their functions are as follows:
udevadm info: Used to obtain detailed information about a device, including device path, attributes, drivers, etc.udevadm monitor: Used to monitor and display uevent events in the current system. It shows device insertion, removal, and other related events in real time.udevadm trigger: Used to manually trigger uevent events for a device. This command can simulate device insertion, removal, etc., to trigger corresponding event handling.udevadm settle: Used to wait for udev to process all queued uevent events. It blocks until udev completes all current device processing operations.udevadm control: Used to interact with the udev daemon and control its behavior. For example, this command can reload udev rules, set log levels, etc.udevadm test: Used to test the matching and execution process of udev rules. This command can test whether a specific device correctly triggers the corresponding rules.
Test:
1 | root@topeet:/root# udevadm monitor & |
uevent is implemented based on kset
In the above driver code, ifRemoved the step of creating kset, user space cannot receive uevent events, analysis as follows:
kobject_uevent_env()
1 | /** |
Because uevent is sent to user-space applications vianetlink socket, andnetlink socketis based on kset.
kobject_uevent_net_broadcastis a kernel function used to send a uevent event to all network namespaces in the system. Its parameters include:
kobjis the kernel object associated with the uevent eventenvis a list containing uevent environment variablesaction_stringis a string representing the type of the uevent eventdevpathis a string representing the device path associated with the uevent event.
This function iterates through all network namespaces in the system and sends the uevent event to each network namespace. The main purpose of this function is to broadcast a uevent event within the kernel, so that user-space applications can receive and process these events.
Call the user-spaceuevent_helperprogram in the kernel to handle uevent events.uevent_helperis a user-space program that can be called when a uevent is generated in kernel space. IfCONFIG_UEVENT_HELPERmacro is defined, the kernel will call theuevent_helperprogram to handle these events in user space. In the above code, if theuevent_helpervariable is not empty and thekobj_usermode_filterfunction returns false, then thecall_usermodehelper_setupfunction is called to start a user-space process and pass the parameters in env to it. In this process, the parameters in env are converted into environment variables and passed to the user-space process.
In the function that creates a kset and adds it to the system, the second parameter is the passed uevent-related ops
1
2
3 extern struct kset * __must_check kset_create_and_add(const char *name,
const struct kset_uevent_ops *u,
struct kobject *parent_kobj);
struct kset_uevent_ops
Andstruct kset_uevent_opsis defined as follows
1 | struct kset_uevent_ops { |
1.filterevent filter
Function: Determines whether toblocksending the
kobjectuevent to user space.Return value:
0:Filter out(do not send uevent)- Non-
0:Allow sending
Typical use:
- Some internal devices do not require user space intervention;
- Avoid triggering uevents for virtual devices (e.g., debugfs entries).
Example:
1 | static int my_filter(struct kset *kset, struct kobject *kobj) |
2.nameSubsystem name provider
- Function: Returns the
kobjectto which the**“subsystem” name**, as in the ueventSUBSYSTEM=field. - Return value: string (e.g.,
"usb","block","mybus")。 - Importance: User space (e.g., udev rules) often matches rules based on
SUBSYSTEM. - Example:
1 | static const char *my_name(struct kset *kset, struct kobject *kobj) |
The corresponding uevent message will contain
1 | ACTION=add |
Note: If not providednamecallback, the kernel defaults to usingkset->uevent_opstheksetname (usually the parent directory name).
3.ueventCustom environment variable injector
Function: Add custom key-value pairs to the uevent environment variable buffer (
env)Add custom key-value pairs。Parameters:
env: Type isstruct kobj_uevent_env, internally a string array (max 32 items, each 2048 bytes).
Call method: Use
add_uevent_var(env, "KEY=%s", value)。Typical use:
- Pass device attributes (e.g., vendor ID, serial number);
- Trigger specific user-space logic.
Example
1 | static int my_uevent(struct kset *kset, struct kobject *kobj, |
The corresponding uevent will contain
1 | MYBUS_VERSION=1.0 |
Example: Improve kset_uevent_ops structure
1 |
|
Test:
1 | root@topeet:/root# udevadm monitor & |
netlink
Netlink listens to broadcast messages
Netlink is a mechanism in the Linux kernelused for duplex communication between the kernel and user space. Itis based on the socket communication mechanism, and provides a reliable, asynchronous, multicast, and ordered communication method.
The main features of the Netlink mechanism include:
- Duplex communication: Netlink allows bidirectional communication between the kernel and user space, enabling the kernel to send messages to user space and also receive messages from user space.
- Reliability: Netlink provides a reliable message delivery mechanism, ensuring message integrity and reliability. It uses acknowledgment and retransmission mechanisms to guarantee reliable transmission.
- Asynchronous Communication: Netlink supports asynchronous communication, meaning the kernel and user space can send and receive messages independently without synchronously waiting for each other’s response.
- Multicast Support: Netlink allows broadcasting messages to multiple processes or sockets to achieve one-to-many communication.
- Ordered Transmission: Netlink guarantees ordered transmission of messages, meaning messages are received at the receiving end in the order they were sent.
Netlink has a wide range of applications, common ones include:
- System administration tools: Tools such as ifconfig and ip use Netlink to communicate with the kernel to obtain and configure network interface information.
- Inter-process communication: Processes can use Netlink for cross-process communication to achieve data exchange and coordination between processes.
- Communication between kernel modules and user-space applications: Kernel modules can send notifications to or receive instructions from user-space applications via Netlink.
Using Netlink
Creating a Socket
In Linux socket programming, creating a socket is the first step in building a network application. A socket can be understood as a bridge between the application and the network, used for sending, receiving, and processing data over the network. The prototype of this system call and the required header files are as follows:
| Header files | Function prototype |
|---|---|
#include<sys/types.h>#include<sys/socket.h> | int socket(int domain, int type, int protocol); |
domainThe parameter specifies the protocol family of the socket
The protocol family specifies the type of protocol used by the socket. Common protocol families includeAF_INET、AF_INET6、AF_UNIXetc. Among them:
AF_INETIndicates the IPv4 protocol familyAF_INET6Indicates the IPv6 protocol familyAF_UNIXIndicates the Unix domain protocol familyAF_NETLINKIndicates the Netlink protocol family.
typeThe parameter specifies the type of the socket
The socket type specifies the data transmission method of the socket. Common socket types includeSOCK_STREAM、SOCK_DGRAM、SOCK_RAWetc. Among them:
SOCK_STREAMIndicates a connection-oriented stream socket, mainly used for reliable data transmission, such as the TCP protocol.SOCK_DGRAMIndicates a connectionless datagram socket, mainly used for unreliable data transmission, such as the UDP protocol.SOCK_RAWIndicates a raw socket, which can directly access the underlying network protocol.
protocolThe parameter specifies the specific protocol used by the socket. The meanings of these three parameters are introduced below:
The protocol type specifies the specific protocol type used by the socket. Common protocol types includeIPPROTO_TCP、IPPROTO_UDP、IPPROTO_ICMPetc. Among them:
IPPROTO_TCPIndicates the TCP protocolIPPROTO_UDPIndicates the UDP protocolIPPROTO_ICMPIndicates the ICMP protocolNETLINK_KOBJECT_UEVENTIndicates the NETLINK_KOBJECT protocol
The following code will be used to create a new socket
1 | int socket_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_KOBJECT_UEVENT); |
AF_NETLINK: Specifies the use of the Netlink protocol family. The Netlink protocol family is a Linux-specific protocol family used for communication between the kernel and user space.SOCK_RAW: Specifies the creation of a raw socket. This socket type can directly access the underlying protocol without protocol stack processing. In this case, we can directly use the Netlink protocol for communication.NETLINK_KOBJECT_UEVENT: Specifies a type of Netlink protocol, namely the kobject uevent type. kobject uevent is used for event notifications related to kernel objects. When a kobject object in the kernel changes, user space is notified via this type of Netlink message.
Binding the socket
| Required header files | Function prototype |
|---|---|
#include<sys/types.h>#include<sys/socket.h> | int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen); |
sockfdParameter: specifies the socket descriptor to be bound,
addrParameter: specifies the address information to be bound, here using
struct sockaddr_nlstructure,struct sockaddr_nlThe definition of the structure is as follows:1
2
3
4
5
6struct sockaddr_nl {
sa_family_t nl_family; // AF_NETLINK
unsigned short nl_pad; // zero
uint32_t nl_pid; // port ID
uint32_t nl_groups;// multicast groups mask
};nl_family: indicates the address family, here fixed toAF_NETLINK, indicating the use of the Netlink protocol family.nl_pad: padding field, set to 0. Used for byte alignment within the structure.nl_pid: Port ID, set to 0 to indicate allocation by the kernel.nl_groups: multicast group mask, used to specify the multicast groups of interest. When set to 1, it indicates that the user-space process will only receive kernel events from the basic group of kernel events. This means the user-space process will only receive kernel events belonging to the basic group and not events from other multicast groups.
addrlenParameter: the addrlen parameter is an integer specifying the byte length of the structure pointed to by addr. It is used to ensure correct parsing of the size of the structure passed to the addr parameter.
Example
1 | { |
Receive data
Netlink sockets do not need to call the listen function when receiving data; instead, they can directly use the recv function for reception.
| Required header files | Function prototype |
|---|---|
#include<sys/types.h>#include<sys/socket.h> | ssize_t recv(int sockfd, void *buf, size_t len, int flags); |
Function parameters:
sockfd: Specifies the socket descriptor, i.e., the Netlink socket from which to receive data.buf: Pointer to the data reception buffer, used to store the received data.len: Specifies the byte size of the data to be read.flags: Specifies some flags to control the data reception method. Typically, it can be set to 0.
Return value:
- On success, returns the actual number of bytes read.
- If the return value is 0, it indicates that the other party has closed the connection.
- If the return value is -1, it indicates an error occurred. You can check the errno variable to obtain the specific error code.
Using the recv function, data can be received from the specified Netlink socket and stored in the provided buffer. The return value of the function indicates the actual number of bytes read, which can be used to determine whether data was successfully received.
Example code:
1 | while (1) { |
Example code
1 |
|
Test:
1 | root@topeet:/root# ./netlink_test.o & |
uevent_helper
Inkobject_uevent_env()the function:
1 |
|
Line 3 is an if expression that checksuevent_helperwhether the first element of the array is true. And calls thekobj_usermode_filterfunction for user-mode filtering,uevent_helperdefined as follows:
1 | char uevent_helper[UEVENT_HELPER_PATH_LEN] = CONFIG_UEVENT_HELPER_PATH; |
CONFIG_UEVENT_HELPER_PATHis a macro defined in the kernel source code’sinclude/generated/autoconf.hfile, as shown below:
1 |
This macro is empty, so to enable theuevent_helperfunction, you need to enable it in the graphical configuration interfaceCONFIG_UEVENT_HELPERmacro to enableuevent_helperandCONFIG_UEVENT_HELPER_PATHmacro to set the defaultuevent_helperpath (such as/sbin/mdev);
uevent_helper configuration method 1
1 | Device Drivers |
Save configuration:
1 | cp .config arch/arm64/configs/rockchip_linux_defconfig |
In configuration 1 above, setuevent helperand the corresponding path. This is configuration method 1, but this method requires recompiling the kernel, which is cumbersome to use. Besides method 1, there are faster methods 2 and 3:
uevent_helper configuration method 2
Regardless of whetherCONFIG_UEVENT_HELPER_PATHis configured, after system startup, you can use the following command to setuevent_helper:
1 | echo /sbin/mdev > /sys/kernel/uevent_helper |
This will setuevent_helperto/sbin/mdev。
uevent_helper configuration method 3
Regardless of whetherCONFIG_UEVENT_HELPER_PATHis configured, after system startup, you can use the following command to setuevent_helper:
1 | echo /sbin/mdev > /proc/sys/kernel/hotplug |
This will setuevent_helperset to/sbin/mdev。
It should be noted that configuration method 2 and configuration method 3 depend on the above configurationSupport for uevent helper,File systemsandNetworkingoptions, and the values already written in configuration method 1 can be modified through configuration method 2 and configuration method 3. For/proc/sys/kernel/hotplugand/sys/kernel/uevent_helperreading and writing are both for performing read and write operations on the uevent_helper attribute.
/sys/kernel/uevent_helperis a file in the sysfs filesystem, which is theuevent_helperinterface of the attribute. By performing read and write operations on this file, the value of the uevent_helper attribute can be read or modified. In the kernel source code’skernel/ksysfs.cdirectory, the definition and related implementation of theuevent_helperattribute can be found, and the specific content is as follows:
1 | // kernel/ksysfs.c |
uevent_helper_showfunction is used to write the value ofuevent_helperinto buf and return the number of characters written.uevent_helper_storefunction is used to copy the value in buf touevent_helperand process it as needed, then return the number of characters written.
/proc/sys/kernel/hotplugis a virtual file used to configure the hotplug event handler in the kernel. By performing write operations on this file, theuevent_helpervalue of the attribute. In the kernel source code’skernel/sysctl.cfile, you can see that thehotplugoperation is actually performed onuevent_helper.
1 | // kernel/sysctl.c` |
This code defines a file namedhotplugfor handling uevent events. It is associated with theuevent_helperattribute.
.procnamerepresents the file name, i.e.,/proc/hotplug。.datais a pointer to theuevent_helperstructure, used to store data related to the file. This pointer points to theuevent_helperstructure for handling uevent events..maxlenrepresents the maximum length of the file, i.e., the maximum length of the file content. This value isUEVENT_HELPER_PATH_LEN, indicating the maximum length of the file content..moderepresents the file access permissions. This value is 0644, meaning the file’s permissions are-rw-r--r--, i.e., all users can read the file, but only the root user can write to it.
Example
Calling user-spaceuevent_helperprogram to handle uevent events.
uevent_helperis a user-space program that can be called when a uevent event is generated in kernel space. IfCONFIG_UEVENT_HELPERthe macro is defined, the kernel will calluevent_helperprogram to handle these events in user space.
Inkobject_uevent_env()the function, ifuevent_helpervariable is not null andkobj_usermode_filterfunction returns false, thencall_usermodehelper_setupfunction is called to start a user-space process and pass the parameters in env to it. In this process, the parameters in env are converted into environment variables and passed to the user-space process.
1 |
|
Method 2:
1 | root@topeet:/root# echo /root/uevent_helper_test.o > /sys/kernel/uevent_helper |
Method 3:
1 | root@topeet:/root# echo /root/uevent_helper_test.o > /proc/sys/kernel/hotplug |
It can be seen that both of the above configurations can print theSUBSYSTEMenvironment variable passed during kernel loading.
Mount USB flash drives and TF cards using udev
Configure buildroot to support udev
1 | System configuration |
Mount USB flash drive
To use udev for automatic mounting of USB flash drives, you also need to/etc/udev/rules.dcreate corresponding rule files in the directory
1 | KERNEL=="sd[a-z][0-9]", SUBSYSTEM=="block", ACTION=="add", RUN+="/etc/udev/rules.d/usb/usb-add.sh %k" |
KERNEL=="sd[a-z][0-9]KERNEL: indicates matching the kernel name of the device.sd[a-z][0-9]: is a regular expression pattern,sd: indicates the device name starts with “sd”[a-z]: indicates the third character of the device name is a lowercase letter[0-9]: indicates the fourth character of the device name is a digit.
This pattern is used to match block device nodes of USB storage devices, such as/dev/sda1、/dev/sdb2etc.
SUBSYSTEM=="block"SUBSYSTEM: indicates matching the subsystem name of the device.block: indicates the device’s subsystem is the block device subsystem, i.e., devices related to disks, partitions, etc. This part of the rule ensures that only devices under the block device subsystem are matched.
ACTION=="add"andACTION=="remove"ACTION: Indicates the action of matching the device.add: Indicates that the device is added.remove: Indicates that the device is removed.
This part of the rules is for handling events where devices are added and removed.
RUN+="/etc/udev/rules.d/usb/usb-add.sh %kRUN+="...": Indicates executing the specified command on the matched device."/etc/udev/rules.d/usb/usb-add.sh": Is the path of the command to be executed, i.e., execute when the device is added/etc/udev/rules.d/usb/usb-add.shscript file.%k: Is a variable provided by udev, representing the kernel name of the matched device
When a block device is added, execute/etc/udev/rules.d/usb/usb-add.shscript, when a block device is removed, execute/etc/udev/rules.d/usb/usb-remove.shscript
/etc/udev/rules.d/usb/usb-add.shThe content is as follows1
2
/bin/mount -t vfat /dev/$1 /mnt/bin/mount: Calls the mount command (explicitly specifying the full path).-t vfat: Specifies the file system type to be mounted as VFAT (i.e., FAT32 or FAT16, commonly used for USB drives, SD cards, etc.)./dev/ $ 1: Represents the device file, where$ 1is the first argument passed to the script or command line.
/etc/udev/rules.d/usb/usb-remove.shThe content is as follows1
2
3
sync
/bin/umount -l /mnt-l: Indicates “lazy unmount”. It immediately removes the mount point from the filesystem namespace, but actual cleanup (such as releasing the device) is deferred until the device is no longer busy (no processes are using it). Commonly used when a device is “busy” and cannot be unmounted normally (for example, when a shell is currently in the/mntdirectory).
Then grant execute permissions to these two scripts
1 | chmod a+x /etc/udev/rules.d/usb/usb-add.sh /etc/udev/rules.d/usb/usb-remove.sh |
Mount the TF card
/etc/udev/rules.d/In the directory, create a file named002.rulesfile
1 | KERNEL=="mmcblk[0-9]p[0-9]", SUBSYSTEM=="block", ACTION=="add", RUN+="/etc/udev/rules.d/tf/tf-add.sh %k" |
KERNEL=="mmcblk[0-9]p[0-9]"KERNEL: Indicates matching the kernel name of the device."mmcblk[a-z][0-9]": Is a regular expression patternmmcblk: Indicates that the device name starts with"mmcblk"at the beginning[0-9]: Indicates that the 7th and 9th characters of the device name are digits.
This pattern is used to match block device nodes of TF card storage devices, such as/dev/mmcblk1p1, etc.
SUBSYSTEM=="block"SUBSYSTEM: Indicates the subsystem name of the matching device."block": Indicates that the device’s subsystem is the block device subsystem, i.e., devices related to disks, partitions, etc.
This part of the rule is to ensure that only devices under the block device subsystem are matched.
ACTION=="add"andACTION=="remove"ACTION: Indicates the action of the matching device."add": Indicates that the device is added."remove": Indicates that the device is removed.
This part of the rule is to handle events of device addition and removal.
RUN+="/etc/udev/rules.d/tf/tf-add.sh %k"RUN+="...": Indicates executing the specified command on the matching device."/etc/udev/rules.d/tf/tf-add.sh": Is the path of the command to be executed, i.e., execute when the device is added/etc/udev/rules.d/tf/tf-add.shscript file.%k: Is a variable provided by udev, representing the kernel name of the matching device.
When the TF card block device is added, it will execute/etc/udev/rules.d/usb/tf-add.shscript, and when the TF card block device is removed, it will execute/etc/udev/rules.d/tf/tf-remove.shscript
In/etc/udev/rules.d/usb/tf-add.shwrite the following content to the file:
1 |
|
In/etc/udev/rules.d/usb/tf-remove.shwrite the following content to the file
1 |
|
Then grant execute permissions to these two scripts
1 | chmod a+x /etc/udev/rules.d/usb/tf-add.sh /etc/udev/rules.d/usb/tf-remove.sh` |
Use mdev to mount USB drives and TF cards
Configure buildroot to support mdev
1 | make rockchip_rk3568_defconfig |
The configuration is as follows:
1 | System configuration |
In addition to configuring buildroot, you also need to configure the relevant options of busybox, because buildroot uses busybox
1 | make busybox-menuconfig |
The configuration is as follows:
1 | Linux System Utilities |
Mount USB drive
Similar to udev, mdev also needs to add corresponding rules. The difference is that mdev uses/etc/mdev.conffile to configure the rules and behavior of the mdev tool. To use mdev to automatically mount USB drives, you need to add to the/etc/mdev.conffile the following two rules
1 | sd[a-z][0-9] 0:0 666 @/etc/mdev/usb_insert.sh |
These two rules are used to handle hotplug events of USB drives and execute corresponding actions. In/etc/mdev.confIn the file, each line is a rule with the following format:
1 | <设备节点正则表达式> <设备的所有者:设备的所属组> <设备的权限> <设备插入或移除时需要执行的命令> |
Below is a detailed introduction to the above two rules:
sd[a-z][0-9]is a regular expression pattern used to match device nodes starting with “sd”, followed by a lowercase letter and a digit, for example/dev/sda1etc.0:0 666indicates setting the owner and permissions of the device node. 0:0 means the user ID and group ID of the owner and group are both 0, i.e., root user. 666 means the permissions are readable and writable.@/etc/mdev/usb_insert.shindicates that when a device matching the rule is inserted, mdev will execute/etc/mdev/usb_insert.shscript.@symbol indicates that a shell command is executed.$/etc/mdev/usb_remove.shindicates that when a device matching the rule is removed, mdev will execute/etc/mdev/usb_remove.shscript.$symbol indicates that an internal command is executed.
/etc/mdev/usb_insert.shand/etc/mdev/usb_remove.shThe two files are shown in the following figure:
/etc/mdev/usb_insert.sh
1 |
|
/etc/mdev/usb_remove.sh
1 |
|
Then grant execution permissions to these two scripts
1 | chmod a+x /etc/mdev/usb_insert.sh /etc/mdev/usb_remove.sh |
Mount TF card
to/etc/mdev.confadd the following two rules to the file
1 | mmcblk[0-9]p[0-9] 0:0 666 @/etc/mdev/tf_insert.sh |
mmcblk[0-9]p[0-9]is a regular expression pattern used to match TF card block devices starting with"mmcblk", such as/dev/mmcblk1p1etc.0:0 666indicates setting the owner and permissions of the device node.0:0indicates that the user ID and group ID of the owner and group are both 0, i.e., the root user.666indicates that the permissions are readable and writable.@/etc/mdev/tf_insert.shindicates that when a device matching the rule is inserted, mdev will execute the/etc/mdev/tf_insert.shscript.@symbol indicates that a shell command is being executed.$/etc/mdev/tf_remove.shindicates that when a device matching the rule is removed, mdev will execute the/etc/mdev/tf_remove.shscript.$symbol indicates that an internal command is being executed.
/etc/mdev/tf_insert.shand/etc/mdev/tf_remove.shas shown below
/etc/mdev/tf_insert.sh
1 |
|
/etc/mdev/tf_remove.sh
1 |
|
Then grant execution permissions to these two scripts
1 | chmod a+x /etc/mdev/tf_insert.sh /etc/mdev/tf_remove.sh |
Fix the device node of USB devices
Requirement
In Linux systems, when using multiple USB-to-serial devices, it is common to encounter unstable device nodes due to changes in the order of plugging and unplugging USB-to-serial devices. To solve this problem, we can use udev to fix the device nodes, ensuring that the device nodes are not affected by the order of plugging and unplugging USB-to-serial devices
Solution
Insert USB device:
1 | udevadm info -a -n /dev/ttyUSB0 |
udevadm info -a -n /dev/ttyUSB0is a command used to obtain detailed information about a specific device node, including device attributes, drivers, device paths, etc. The meanings of the parameters of these commands are as follows:
-a: Display all attributes associated with the specified device node.-n: Specify the path or name of the device node.

The output of this command may include the following information:
- Device path (DEVPATH): The path of the device in the system, for example
/devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.2/2-1.2:1.0/ttyUSB0/tty/ttyUSB0。 - Device node (DEVNAME): The node of the device in the file system, i.e.
/dev/ttyUSB0。 - Device attributes: Including the device’s vendor ID, product ID, serial number, etc.
- Device driver: The name and path of the driver used by the device.
- Device type (SUBSYSTEM):
usb
Next, in the development board’setc/udev/rules.d/directory, create a rule file named 001.rules:
1 | KERNELS==”5-1:1.0”,SUBSYSTEMS==”usb”,MODE:=”0777”,SYMLINK+=”myusb” |
KERNELS=="5-1:1.0"Match the device’skernel device name
5-1:1.0is the path identifier of the USB device in the kernel:5: USB bus number1: USB device number1.0: Interface number, indicating the 0th endpoint of the 1st interface- This value comes from the
udevadm infooutput’sKERNELSfield
SUBSYSTEMS=="usb"Match the device’ssubsystem
indicates that this is a USB type device
Can be used to filter all USB devices
MODE:="0777"- Set thepermissions (mode)
0777means:- All users (root, regular users, and others) have read, write, and execute permissions
- That is:
rwxrwxrwx, so any program can directly access the device (e.g.,/dev/ttyUSB0)
⚠️ Note:
MODEbefore is:=, not==。:=means “assignment”, while==is “matching”.
SYMLINK+="myusb"Create asymbolic link
For example, the original device is
/dev/ttyUSB0, now there will be an additional soft link:/dev/myusb -> /dev/ttyUSB0You can use
myusbto replacettyUSB0, making naming and script invocation more convenient


