正点原子linux 使用QT 自动检测u盘插拔并寻找特定文件
目录
- 正点原子开发板Alpha配置环境需求
- linux自动挂载u盘
- 使用udev自动挂载u盘
- mount.sh代码解析
- 查看u盘挂载情况
- 使用QT检测u盘插入
- 1.增加头文件libudev.h
- 2.在.pro增加QT application对libudev库的链接
- 3.在头文件.h里新建udev结构体指针并在构造函数里初始化udev
- 4.创建udev监视器并用QT槽连接处理函数
- 5.在析构函数里增加对udev的释放
- 6.编写u盘插入处理函数
- 已插入U盘检测
笔者刚解决完这个问题,前期有些忘了,一点一点回忆。会慢慢更新。
正点原子开发板Alpha配置环境需求
笔者使用的是Alpha出厂系统,也就是用Yocto做的根文件系统。这个系统里包含了QT和很多其他必要的库,可以不用在开发板上再安装了。
linux自动挂载u盘
使用udev自动挂载u盘
正点原子提供的出厂系统中已经内置了用udev自动挂载u盘的脚本,在/etc/udev 文件夹下有个脚本文件夹scripts,里面有个自动挂载的脚本mount.sh,部分内容如下:
...automount() { name="`basename "$DEVNAME"`"! test -d "/mnt/$name" && mkdir -p "/mnt/$name"# Silent util-linux's version of mounting autoif [ "x`readlink $MOUNT`" = "x/bin/mount.util-linux" ] ;thenMOUNT="$MOUNT -o silent"fi# If filesystem type is vfat, change the ownership group to 'disk', and# grant it with w/r/x permissions.case $ID_FS_TYPE invfat|fat)MOUNT="$MOUNT -o umask=007,gid=`awk -F':' '/^disk/{print $3}' /etc/group`";;# TODO*);;esacif ! $MOUNT -t auto $DEVNAME "/mnt/$name"thenlogger "mount.sh/automount" "$MOUNT -t auto $DEVNAME \"/mnt/$name\" failed!"rm_dir "/mnt/$name"elselogger "mount.sh/automount" "Auto-mount of [/mnt/$name] successful"touch "/tmp/.automount-$name"fi
}
...
mount.sh代码解析
basename 是是去掉文件明前面的目录并打印出来,比如/dev/sda1 打印出来就是sda1。
$DEVNAME是由udev提供的系统环境变量,表示正在处理的块设备的名称。这个系统环境变量可以通过输入命令udevadm test /sys/class/block/sda查看。
DEVLINKS=/dev/disk/by-id/usb-USB_Disk_3727637990721561-0:0 /dev/disk/by-path/platform-ci_hdrc.1-usb-0:1.4:1.0-scsi-0:0:0:0
DEVNAME=/dev/sda
DEVPATH=/devices/platform/soc/2100000.aips-bus/2184200.usb/ci_hdrc.1/usb1/1-1/1-1.4/1-1.4:1.0/host2/target2:0:0/2:0:0:0/block/sda
DEVTYPE=disk
脚本里用到了这些命令:
test -d 文件名: 如果文件存在且为目录则为真。
mkdir -p 文件夹名: 确保目录名称存在,不存在的就建一个。
mount -o auto、-o noauto:打开/关闭自动挂上模式。
开机后会自动执行这个脚本,u盘插入就会挂上,挂载到/mnt下
查看u盘挂载情况
使用df -h命令或者mount能查看
root@ATK-IMX6U:~# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 120M 1.7M 119M 2% /mnt/sda1
root@ATK-IMX6U:~# mount
/dev/sda1 on /mnt/sda1 type vfat (rw,relatime,gid=6,fmask=0007,dmask=0007,allow_utime=0020,codepage=437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro)
使用QT检测u盘插入
在QT工程中做如下改动
1.增加头文件libudev.h
#include <libudev.h>
确保系统上安装了libudev库。如果尚未安装,使用 Linux 发行版的包管理器进行安装。在Ubuntu 的系统上,使用以下命令进行安装:
sudo apt-get install libudev-dev
2.在.pro增加QT application对libudev库的链接
在.pro文件中增加一行 LIBS += -ludev
udev = udev_new();if (!udev) {qFatal("Failed to initialize libudev.");}monitor = udev_monitor_new_from_netlink(udev, "udev");udev_monitor_filter_add_match_subsystem_devtype(monitor, "block", NULL);udev_monitor_enable_receiving(monitor);int fd = udev_monitor_get_fd(monitor);QSocketNotifier *notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);connect(notifier, &QSocketNotifier::activated, this, &viva::usbDiskInserted);
通过添加-ludev到LIBS变量,编译程序将在链接过程中搜索库并解析对函数udev_new和其他libudev函数的引用。
确保系统上安装了libudev库。如果尚未安装,使用 Linux 发行版的包管理器进行安装。在Ubuntu 的系统上,使用以下命令进行安装:
sudo apt-get install libudev-dev
3.在头文件.h里新建udev结构体指针并在构造函数里初始化udev
struct udev *udev;
udev = udev_new();
if (!udev) {qFatal("初始化libudev失败");
}
4.创建udev监视器并用QT槽连接处理函数
struct udev_monitor *monitor = udev_monitor_new_from_netlink(udev, "udev"); //创建一个udev对象来监听设备事件
udev_monitor_filter_add_match_subsystem_devtype(monitor, "block", NULL); //指定设备子系统(如块设备的block)
udev_monitor_enable_receiving(monitor); //将监视器添加到事件循环中
int fd = udev_monitor_get_fd(monitor);
QSocketNotifier *notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
connect(notifier, &QSocketNotifier::activated, this, &MyClass::usbDiskInserted); //连接信号槽
上面代码设置了一个监视器来过滤块设备并将其接收QSocketNotifier发来的通知并转发到usbDiskInserted
5.在析构函数里增加对udev的释放
养成良好习惯,避免内存泄漏
udev_monitor_unref(monitor);
udev_unref(udev);
6.编写u盘插入处理函数
这里设置成只要有u盘插入,查找并读取里面的target.txt文件
void mainwindow::usbDiskInserted()
{struct udev_device *dev = udev_monitor_receive_device(monitor);if (dev) {const char *action = udev_device_get_action(dev);if (action && strcmp(action, "add") == 0) { //如果是插入u盘执行下面const char *devpath = udev_device_get_devpath(dev);const char *devname = udev_device_get_devnode(dev);qDebug() << "u盘路径:" << devpath << "节点名称:" << devname;QString mountPoint = getUsbDiskMountPoint(devname); //返回设备节点名称获取挂载路径// 在u盘中寻找target.txtQString targetFile = searchFileInUsbDisk(mountPoint, "target.txt");if (!targetFile.isEmpty()) {qDebug() << "目标文件路径: " << targetFile;// 此处可以写对target.txt的处理} else {qDebug() << "未找到文件";}}else if(action && strcmp(action, "remove") == 0) //如果是拔出u盘执行下面qDebug() << "u盘已经拔出";udev_device_unref(dev); //用于释放对特定udev_device对象的引用}
}
其中获取挂载路径函数getUsbDiskMountPoint
QString mainwindow::getUsbDiskMountPoint(const QString &usbDiskPath)
{// 相当于在命令行输入mount命令获取u盘挂载路径QProcess process;process.start("mount");process.waitForFinished(-1);QByteArray output = process.readAllStandardOutput();QString mountOutput = QString::fromUtf8(output);// 读取mount on 后的字段,也就是挂载路径的文本QString searchString = usbDiskPath + " on "; //相当于找这段文本/dev/sda1 on /mnt/sda1int index = mountOutput.indexOf(searchString);if (index != -1) {// 如果找到把on后面的文本/mnt/sda1提取出来QString mountPath = mountOutput.mid(index + searchString.length());mountPath = mountPath.left(mountPath.indexOf(' '));qDebug() << "挂载路径:" << mountPath;return mountPath;} else {qDebug() << "未找到路径";return QString();}
}
另一种获取挂载路径函数getUsbDiskMountPoint2,这个函数不用输入参数,更为简单,但有失败的可能
QString mainwindow::getUsbDiskMountPoint2()
{QString mountPath;foreach (const QStorageInfo &storage, QStorageInfo::mountedVolumes()){if (storage.isValid() && storage.isReady()){if (storage.rootPath().contains("sd")) {mountPath = storage.rootPath();qDebug() << "挂载路径:" << mountPath;return mountPath;}else {qDebug() << "未找到路径";return QString();}} else {qDebug() << "未找到路径";return QString();}}}
其中查找特定文件函数searchFileInUsbDisk
QString mainwindow::searchFileInUsbDisk(const QString &usbDiskPath, const QString &fileName)
{//使用QT遍历器,遍历读取u盘中的所有文件QDirIterator it(usbDiskPath, QDir::Files | QDir::NoSymLinks, QDirIterator::Subdirectories);while (it.hasNext()) {QString filePath = it.next();QFileInfo fileInfo(filePath);if (fileInfo.fileName() == fileName) {return fileInfo.filePath(); //找到返回文件路径}}return QString(); // 文件未找到
}
已插入U盘检测
上述情况是在进入App后插入u盘,触发QSocketNotifier找到u盘。
如果在进入App前就有u盘插入,可以使用上面的getUsbDiskMountPoint2()
正点原子linux 使用QT 自动检测u盘插拔并寻找特定文件相关推荐
- VB中简便的检测U盘插拔的方法(DriveListBox)
我在网上找了很多资料,实现检测U盘插拔的方法基本上都是监测WM_DEVICECHANGE.这种方法不但臃肿,而且效率不高,很容易出错.于是我摸索出了一种新的方法,以下就是实现过程. 首先在窗体中添加一 ...
- 正点原子Linux移植Qt,正点原子I.MX6U Qt综合例程源码
I.MX6U Qt综合例程源码 介绍 正点原子I.MX6U Qt综合例程源码 使用说明 1.Windows下编译,安装Qt 5.12.9,可以在Windows编译,打开工程,编译完成后把src文件夹放 ...
- linux qt检测u盘热插拔,【QT】动态监测U盘插拔
前言 在项目中,遇到一个需求:需要动态监测U盘插入,自动读取U盘文件并打开.为了实现这个功能,我们可以使用RegisterDeviceNotification注册设备事件的通知, 然后在程序中处理WM ...
- 【正点原子Linux连载】第十八章 Camera 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2
1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 3)全套实验源码+手册+视频下载地址: ...
- 【正点原子Linux连载】第二十二章 AP3216C 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2
1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 3)全套实验源码+手册+视频下载地址: ...
- 【正点原子Linux连载】 第十九章 CAN Bus 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2
1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 3)全套实验源码+手册+视频下载地址: ...
- 【正点原子Linux连载】第十一章 网络编程 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2
1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...
- 【正点原子Linux连载】第六章 Qt Creator的使用技巧 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2
1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...
- 【正点原子Linux连载】第十四章 Qt控制LED 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2
1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...
- 【正点原子Linux连载】第六十七章 Linux USB驱动实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...
最新文章
- Linux crontab 命令基本说明
- python if条件判断_python if not in 多条件判断代码
- Python+Anaconda+PyCharm的安装和基本使用
- 对EditText右边的图片进行监听
- openstack租户管理_openstack 租户、用户管理
- Eclipse 报java.lang.OutOfMemoryError: PermGen space错
- ORB-SLAM2中的Loop Closinng中DetectLoopCandidates函数解析
- java编写科赫曲线_matlab绘制peano(皮亚诺)曲线和koch(科赫曲线,雪花曲线)分形曲线...
- Django访问java建立的数据库
- hype-v的磁盘管理(转换)
- Kerberos的基本命令操作
- mysql自动化巡检_mysql自动化巡检脚本生成html报告
- JavaScrip节点属性-访问子节点
- type(img).__module__ == np.__name__
- Oracle Ravello的学习资料
- 计算机网络自顶向下方法第七版第六章答案,《计算机网络 自顶向下方法》(第7版)答案(第六章)(一)...
- 传:九大前缀,三大后缀
- 更改laravel的默认端口8000
- Android学习之——操作SIM卡联系人
- TCP短连接与长连接