嵌入式技术
大家好,我是ST。
今天主要聊一聊,如何使用Linux系统下的mdev实现动态更新设备节点及动态挂载U盘。
第一:mdev基本简介
Linux传统上使用静态设备创建的方法,在dev/下创建了大量的节点,而不管这些节点相应的硬件设备是否存在。Linux2.6内核是开始引入可在用户空间执行的udev,允许用户不必再关心主,次设备号,在系统检测到设备的热拔插(hotplug)事件才动态的在/dev下建立和删除相应的设备节点文件。简言之,udev的主要功能是实时的创建和删除设备节点。如果希望像Windows系统一样,在设备插入时系统能够识别设备并自动挂载,可以通过在用户空间创建udev规则并编写脚本文件来实现。mdev实际上是嵌入式应用开发中udev的简化版,其作用与udev相同,即在系统启动时或发生热拔插事件时,自动产生驱动程序所需要的节点文件。
第二:使能mdev功能
要使用mdev需要内核支持sysfs文件系统,为了减少对flash的读写,还要支持tmpfs文件系统。对于动态更新来说,你也需要开启内核的热插拔功能。配置内核支持选项如下:
CONFIG_EMIBEDDED=y
CONFIG_SYSFS=y
CONFIG_TMPFS=y
在启动脚本如/etc/init.d/rcS中添加如下内容:
mount -t tmpfs tmpfs /dev -o size=64k,mode=0755
mkdir /dev/pts /dev/shm
chmod 777 /dev/shm
mount -t devpts devpts /dev/pts
touch /dev/mdev.seq
echo "/sbin/mdev" > /proc/sys/kernel/hotplug
mdev -s
mdev扫描/sys/class和/sys/block中所有的类设备目录,如果在目录中含有名为"dev"的文件,且文件中包含的是设备号,则mdev就利用这些信息为这个设备在/dev下创建设备节点文件。一般只在启动时才执行一次"mdev -s"。
第三:mdev配置方法
这样,系统启动时执行了命令echo /sbin/mdev > /proc/sys/kernel/hotplug,当那么当有热插拔事件产生时,内核就会调用位于/sbin目录的mdev。这时mdev通过环境变量中的 ACTION和DEVPATH(这两个变量是系统自带的)来确定此次热插拔事件的动作以及影响了/sys 中的那个目录。接着会看看这个目录中是否有" dev "的属性文件,如果有就利用这些信息为这个设备在/dev下创建设备节点文件。
mdev有一个可以操作的配置文件:/etc /mdev .cfg
<device regex> <uid>:<gid> <octal permissions> [<@|$|*> <command>]
特殊字符的意义如下:
@:在创建设备节点后运行命令。
$:在删除设备节点前运行命令。
*:在创建设备节点和删除设备节点前都运行命令。
Command :对应的shell—般位于letc/mdev目录
为了利用脚本(如Shell脚本automout.sh)实现u盘在嵌入式系统上的自动挂载,在mdev规则文件/sbin/automount.sh中加入以下一行匹配规则使mdev在找到匹配行时可以执行用户自定义的命令( shell脚本中的内容):
sd[a-z][0-9]* 0:0 0600 */sbin/automount.sh $MDEV
第四:自动挂载Shell脚本
shell是 Linux系统中一个重要的层次,它是用户与系统交互的界面,如我们使用Linux最常用的终端其实就是一种shell。shell最常见的使用方式是作为命令解释程序出现,以特定的前导符(如s)接收用户输入的命令并进行分析,然后创建子进程来实现命令所规定的功能。在子进程终止工作后,shell 则再次向用户发出命令输入提示符。此外,Shell作为一种高级的编程语言,具有变量、关键字、各种控制语句及自己的语法结构,通过编写shell脚本程序可以直接在Linux系统中解释执行而无须编译。通过mdev规则实现u盘自动挂载的 shell脚本automount主要内容如下:
destdir=/mnt/sdcard/
umount_partition()
{
if grep -qs "^/dev/$1 " /proc/mounts ; then
umount -lf "${destdir}";
fi
}
mount_partition()
{
if [ ! -d "${destdir}" ]; then
mkdir "${destdir}"
fi
if ! mount -t auto "/dev/$1" "${destdir}" -o nodev,noexec,nosuid; then
# failed to mount
exit 1
fi
}
check_if_boot_dev()
{
ret_val=`cat /proc/cmdline | grep "androidboot.bootdevice" |wc -l`
if [ $ret_val -eq 1 ]; then
boot_dev=`cat /proc/cmdline | awk '{ for ( n=1; n<=NF; n++ ) if($n ~ "androidboot.bootdevice") print $n }' | awk '{split($0,a, "=");print a[2]
real_sysfs_path=`realpath /sys/class/block/$1`
ret_val=`echo $real_sysfs_path | grep /sys/devices/ | grep $boot_dev | wc -l`
fi
echo $ret_val
}
create_symlink()
{
real_sysfs_path=`realpath /sys/class/block/$1`
partition_name=`cat $real_sysfs_path/uevent | awk '{ for ( n=1; n<=NF; n++ ) if($n ~ "PARTNAME") print $n }' | awk '{split($0,a, "=");print a[2]}'
mkdir -p /dev/block/bootdevice/by-name/
partition_name=/dev/block/bootdevice/by-name/$partition_name
target_dev=/dev/$1
ln -s $target_dev $partition_name
}
case "${ACTION}" in
add|"")
result=`check_if_boot_dev $1`
if [ $result -eq 1 ]; then
create_symlink $1 &
else
umount_partition ${1}
mount_partition ${1}
fi
;;
remove)
umount_partition ${1}
;;
esac
总结:Linux系统中,mdev设备节点动态加载的过程,在实际开发中应用非常广发。
全部0条评论
快来发表一下你的评论吧 !