通过信号实现在应用层检测TF卡的拔插

xiaoxiao2021-02-28  105

     本文描述如何在应用中通过不轮询的方式对TF卡热拔插的检测。文中根据实际项目实现所写,部分内容有摘抄其它博文,如有侵权,请在评论中与我联系!

    在项目中要实现对TF卡热拔插的检测,最初是采用轮询的方式帧测/dev目录下的结点来实现。但这种方式有两个缺点:一是在应用层一直要占用CPU,二是要放在一个循环中,不利于代码模块化。所以后来让系统帧测卡热拔插事件,再给指定的应用进程发信号的方式来实现。这样就不用在应用层去轮询检测,只要注册相应的信号函数,再在函数中判断卡的插入和拔出状态就可以了。

     在这里要用到内核mdev机制,如下为其简单介绍:

      mdev是busybox自带的一个简化版的udev,功能类似。都是帧测内核的uevent事件来感知系统的热拔插事件。   作用是在系统启动和热插拔 或动态加载驱动程序时,自动产生驱动程序所需的节点文件。文件系统中的/dev目录下的设备节点都是由mdev创建的。使用mdev时不加参数就是用hotplug机制来决定创建什么样的设备文件。而用mdev -s命令是表示用sys文件系统提供的信息来创建设备文件的.   mdev -s扫描/sys/class和/sys/block中所有的类设备目录,如果在目录中含有名为"dev"的文件,且文件中包含的是设备号,则mdev就利用这些信息为这个设备在/dev下创建设备节点。

     在这里就要用到其热插拔时自动生成/dev下文件节点的功能。当有此事件时,发送一个信号到应用进程,再在注册的信号函数中判断/dev目录下对应的卡设备节点是否存在来识别卡插入或排出。具体实现方法如下:

     1.在buildroot配置menuconfig中打开对mdev的支持。我当前使用的BusyBox 1.18.x版本,未查到mdev的选项,只有udev选项。所以我就打开了udev选项,也是可行的。这部分还有待澄清。具体打开方式读者可以自行查找,在此就不作说明了。

     2.因mdev依赖于sys文件系统下的节点信息,所以在内核启动的时候要挂载sys文件系统。并还要做相关的配置。可以在启动脚本中执行如下命令

  mount -t devfs none /dev mount -t sysfs sysfs /sys echo /sbin/mdev > /proc/sys/kernel/hotplug /* 系统感知到热拔插事件时执行/sbin/mdev程序 */ mdev -s /* 根据/sys/目录下的结节信息创建/dev/目录下的设备节点 */

     3.配置/etc/mdev.conf文件,该文件作用是mdev帧到热拔插事件时,会执行里面的操作。这样我们就可以根据需求自定义一些操作。

mmcblk0 0:0 777 * kill -s SIGUSR2 `pidof car_video`

      上述意思是当发现mmcblk0这个设备时,给用户空间card_video这个进程发送SIGUSR2信号。

     4.在card_video这个进程中,使用signal(SIGUSR2, card_detection);注册信号函数,在函数中就可以通过判断/dev下的卡结点是否存在来识别卡插入还是拔出状态。进而做进一步操作。

    关于mdev.conf文件格式,将busybox中的说明摘抄如下:

------------- MDEV Config (/etc/mdev.conf) ------------- Mdev has an optional config file for controlling ownership/permissions of device nodes if your system needs something more than the default root/root 660 permissions. The file has the format: <device regex> <uid>:<gid> <octal permissions> or @<maj[,min1[-min2]]> <uid>:<gid> <octal permissions> For example: hd[a-z][0-9]* 0:3 660 The config file parsing stops at the first matching line. If no line is matched, then the default of 0:0 660 is used. To set your own default, simply create your own total match like so: .* 1:1 777 You can rename/move device nodes by using the next optional field. <device regex> <uid>:<gid> <octal permissions> [=path] So if you want to place the device node into a subdirectory, make sure the path has a trailing /. If you want to rename the device node, just place the name. hda 0:3 660 =drives/ This will move "hda" into the drives/ subdirectory. hdb 0:3 660 =cdrom This will rename "hdb" to "cdrom". Similarly, ">path" renames/moves the device but it also creates a direct symlink /dev/DEVNAME to the renamed/moved device. If you also enable support for executing your own commands, then the file has the format: <device regex> <uid>:<gid> <octal permissions> [=path] [@|$|*<command>] or <device regex> <uid>:<gid> <octal permissions> [>path] [@|$|*<command>] 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. The command is executed via the system() function (which means you're giving a command to the shell), so make sure you have a shell installed at /bin/sh. You should also keep in mind that the kernel executes hotplug helpers with stdin, stdout, and stderr connected to /dev/null. For your convenience, the shell env var $MDEV is set to the device name. So if the device "hdc" was matched, MDEV would be set to "hdc".

 

 

   

转载请注明原文地址: https://www.6miu.com/read-39628.html

最新回复(0)