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

     本文描述如何在应用中通过不轮询的方式对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:
:
or @ :

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.
: [=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:
: [=path] [@|$|*]
or
: [>path] [@|$|*]
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".


 

   

你可能感兴趣的:(linux/unix)