1. Every time we insert a USB flash drive, the device node /dev/sda%d of the USB flash drive will be automatically created.
This is because device_create() is called inside, and the mdev mechanism of busybox will create device nodes in the /dev directory according to information such as the primary and secondary device numbers, as shown in the following figure:
If you want to use the sda1 device node above, you need to use mount /dev/sda1 /mnt to mount it on the USB disk when reading and writing data, which is very troublesome, as shown in the following figure:
2. In fact, you can add a line of statement in the /etc/mdev.conf file to automatically load the USB disk, and you can also do other things related to the device node in it.
2.1 What is /etc/mdev.conf?
It is a configuration file belonging to mdev. As mentioned before, mdev's main function is to manage device nodes under the /dev directory.
When there is an automatic registration of device nodes in the system, mdev will /etc/mdev.conf once. This file can implement things related to device nodes, such as automatically loading USB, printing the created device node information, etc.
3. Let's first analyze how device_ceate() calls /etc/mdev.conf, and then we'll talk about how to use mdev.conf (you can also skip this and go directly to Section 4 below to see how to use it)
(ps: class_device_create(), which was used to create character device nodes before, is actually similar to device_create in function)
3.1 class_device_create() eventually calls: class_device_create()->class_device_register()->class_device_add():
The device_create()->device_register()->device_add() function is as follows:
int class_device_add(struct class_device *class_dev)
{
... ...
kobject_uevent(&class_dev->kobj, KOBJ_ADD); // KOBJ_ADD is an enumeration value
//Called kobject_uevent_env(kobj, action, NULL); // action=KOBJ_ADD
}
3.2 class_device_create()->class_device_register()->class_device_add()->kobject_uevent_env() function is as follows:
int kobject_uevent_env(struct kobject *kobj, enum kobject_action action, char *envp_ext[])
{
char **envp;
char *buffer;
char *scratch;
int i = 0;
... ...
/* Get the string "add" through KOBJ_ADD, so action_string="add" */
action_string = action_to_string(action); // action=KOBJ_ADD
/* environment index */
envp = kzalloc(NUM_ENVP * sizeof (char *), GFP_KERNEL); //Assign an environment variable index value
/* environment values */
buffer = kmalloc(BUFFER_SIZE, GFP_KERNEL); //Assign an environment variable buffer value
/* event environemnt for helper process only */
/*Set environment variables*/
envp[i++] = "HOME=/";
envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
scratch = buffer;
envp[i++] = scratch;
scratch += sprintf(scratch, "ACTION=%s", action_string) + 1; //"ACTION= add"
envp[i++] = scratch;
scratch += sprintf (scratch, "DEVPATH=%s", devpath) + 1;
envp[i++] = scratch;
scratch += sprintf(scratch, "SUBSYSTEM=%s", subsystem) + 1;
... ...
/*Call application, such as mdev*/
if (uevent_helper[0]) {
char *argv [3];
argv[0] = uevent_helper; // uevent_helper[] = "/sbin/hotplug";
argv[1] = (char *)subsystem;
argv[2] = NULL;
call_usermodehelper (argv[0], argv, envp, 0); //Call the application to create a device node based on the environment variable parameters passed in
}
}
From the above code and comments, we can see that the device node is finally created through the environment variable parameters stored in the two string arrays *argv[] and *envp[].
3.2 Next, add print information in the kobject_uevent_env() function and then re-burn uboot:
kobject_uevent_env() function in linux-2.6.22.6libkobject_uevent.c
3.3 Then let's take registering a case driver as an example:
Load the previous button driver, insmod buttons.ko prints the following statement:
class_device: argv[0]=/sbin/mdev //Call mdev
class_device: argv[1]=sixth_dev //class name
class_device: envp[0]=HOME=/
class_device: envp[1]=PATH=/sbin:/bin:/usr/sbin:/usr/bin
class_device: envp[2]=ACTION=add //add: means adding a device node, if =remove: means uninstalling a device node
class_device: envp[3]=DEVPATH=/class/sixth_dev/buttons //Device path
class_device: envp[4]=SUBSYSTEM=sixth_dev //class name
class_device: envp[5]=SEQNUM=745
class_device: envp[6]=MAJOR=252 //Major device number
class_device: envp[7]=MINOR=0
3.4 Finally, these parameters enter the mdev_main() function of busybox's mdev.c according to /sbin/mdev:
int mdev_main(int argc, char **argv)
{
... ...
action = getenv("ACTION"); //Get the execution parameters passed in. If it is equal to "add", it means creating a device node
env_path = getenv("DEVPATH"); //Get the device path "/class/sixth_dev/buttons"
sprintf(temp, "/sys%s", env_path); //Specify temp (real device path) as "/sys/class/sixth_dev/buttons"
if (!strcmp(action, "remove")) //Uninstall device node
make_device(temp, 1);
else if (!strcmp(action, "add")) { //Create device node
make_device(temp, 0);
... ...
}
3.5 Finally, the mdev_main()->make_device() function is called to create/uninstall the device node. The function is as follows:
static void make_device(char *path, int delete) //delete=0: create, delete=1: uninstall
{
/*Determine whether the created device node is a valid device*/
if (!delete) {
strcat(path, "/dev");
len = open_read_close(path, temp + 1, 64);
*temp++ = 0;
if (len < 1) return;
}
device_name = bb_basename(path); //Get the name of the device node to be created/uninstalled through the device path
//Example: path = "/sys /class/sixth_dev/buttons", then device_name = "buttons"
type = path[5]=='c' ? S_IFCHR : S_IFBLK; //If it is in the /sys/class/ directory, then it is a character device
//Because the block device exists in the /sys/block/ directory
/* If the mdev.conf option is configured to support it, then parse the content and execute */
if (ENABLE_FEATURE_MDEV_CONF) {
/* mmap the config file */
fd = open("/etc/mdev.conf", O_RDONLY); //Call the /etc/mdev.conf configuration file
... ... //Start operating the mdev.conf configuration file
}
if (!delete) { //If it is to create a device node
if (sscanf(temp, "%d:%d", &major, &minor) != 2) return; //Get the major and minor device numbers
/*Call mknod() to create a character device node*/
if (mknod(device_name, mode | type, makedev(major, minor)) && errno != EEXIST)
bb_perror_msg_and_die("mknod %s", device_name);
if (major == root_major && minor == root_minor)
symlink(device_name, "root");
/*If the mdev.conf option is configured to support it, call the chown command to change the owner, the default uid and gid = 0 */
if (ENABLE_FEATURE_MDEV_CONF) chown(device_name, uid, gid);
}
if (delete) unlink(device_name); //If it is to uninstall the device node
}
From the above code and comments, we can see that to use the mdev.conf configuration file, you also need to configure busybox's menuconfig so that mdev supports the mdev.conf option.
As shown below, enter the busybox directory and enter make menuconfig. We will find that we have already configured this option.
4. Next, let's take a look at how to use mdev.conf, refer to: busybox-1.7.0docsmdev.txt document
The usage is as follows:
the format: The special characters have the meaning: @ Run after creating the device. $ Run before removing the device. * Run both after creating and before removing the device. It's probably: Configuration file format: The meaning of each parameter is as follows: device regex: Regular expression to express which device, regular expression explanation link: https://deerchao.net/tutorials/regex/regex.htm uid: owner (uid, gid: when registering a device node, it will be called by the chown command to change the owner of the device. The default value is 0) gid: Group ID Octal permissions: The permission value expressed in octal will be called by the chmod command to change the access rights of the device. The default value is 660. @: Execute the command after creating the device node $: Execute command before deleting device node *: Execute commands after creating a device node and before deleting a device node command: The command to be executed 5. Next, use mdev.conf to realize automatic loading of USB disk vi /etc/mdev.conf Add the following sentence: sda[1-9]+ 0:0 660 * if [ $ACTION = "add" ]; then mount /dev/$MDEV /mnt; else umount /mnt; fi [1-9]: matches numbers from 1 to 9 + : Repeat the match one or more times $ACTION = "add": indicates registering the device node, otherwise it indicates unregistering the device node /dev/$MDEV: indicates the device node to be created/deregistered So when we plug in the USB drive and automatically create /dev/sda1, mdev will enter the /etc/mdev.conf configuration file, and then execute the mount /dev/ command to automatically mount the USB drive, as shown in the following figure: Enter ls /dev/sda1 -l, and you can see that all device nodes are created through the configuration information in mdev.conf, as shown in the following figure: When you take out the USB drive, umount /mnt will be automatically used to uninstall it.
Previous article:S3C2440 touch screen driver (Seventeen)
Next article:S3C2440 audio decoding chip WM8976 sound card driver transplantation (31)
Recommended ReadingLatest update time:2024-11-23 18:45
- Naxin Micro and Xinxian jointly launched the NS800RT series of real-time control MCUs
- How to learn embedded systems based on ARM platform
- Summary of jffs2_scan_eraseblock issues
- Application of SPCOMM Control in Serial Communication of Delphi7.0
- Using TComm component to realize serial communication in Delphi environment
- Bar chart code for embedded development practices
- Embedded Development Learning (10)
- Embedded Development Learning (8)
- Embedded Development Learning (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Intel promotes AI with multi-dimensional efforts in technology, application, and ecology
- ChinaJoy Qualcomm Snapdragon Theme Pavilion takes you to experience the new changes in digital entertainment in the 5G era
- Infineon's latest generation IGBT technology platform enables precise control of speed and position
- Two test methods for LED lighting life
- Don't Let Lightning Induced Surges Scare You
- Application of brushless motor controller ML4425/4426
- Easy identification of LED power supply quality
- World's first integrated photovoltaic solar system completed in Israel
- Sliding window mean filter for avr microcontroller AD conversion
- What does call mean in the detailed explanation of ABB robot programming instructions?
- STMicroelectronics discloses its 2027-2028 financial model and path to achieve its 2030 goals
- 2024 China Automotive Charging and Battery Swapping Ecosystem Conference held in Taiyuan
- State-owned enterprises team up to invest in solid-state battery giant
- The evolution of electronic and electrical architecture is accelerating
- The first! National Automotive Chip Quality Inspection Center established
- BYD releases self-developed automotive chip using 4nm process, with a running score of up to 1.15 million
- GEODNET launches GEO-PULSE, a car GPS navigation device
- Should Chinese car companies develop their own high-computing chips?
- Infineon and Siemens combine embedded automotive software platform with microcontrollers to provide the necessary functions for next-generation SDVs
- Continental launches invisible biometric sensor display to monitor passengers' vital signs
- MSP430 timer output PWM waveform example
- 【AD21】The mouse cannot be moved to the left and bottom of the PCB origin. What is the solution?
- 2021 ON Semiconductor Avnet RSL10 Bluetooth SoC Development and Design Competition Second Post (Initial Modification Routine)
- Improving efficiency is a universal requirement for power supplies and electronic transformers
- CC2531 Zlight2 Reference Design
- Fundamentals of Electronic Design (Huang Genchun)
- MSP430g2553 hardware UART (modification based on official routines)
- [TI recommended course] #Innovation of general-purpose op amp and comparator chips#
- Recently, I am doing an experiment on communication between DSP and AD5390. DSP controls AD5390 through SPI bus. I am not familiar with the core of AD5390.
- A new year and a new beginning. I wish you all a happy New Year!