目录

  • 正点原子开发板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盘插拔并寻找特定文件相关推荐

  1. VB中简便的检测U盘插拔的方法(DriveListBox)

    我在网上找了很多资料,实现检测U盘插拔的方法基本上都是监测WM_DEVICECHANGE.这种方法不但臃肿,而且效率不高,很容易出错.于是我摸索出了一种新的方法,以下就是实现过程. 首先在窗体中添加一 ...

  2. 正点原子Linux移植Qt,正点原子I.MX6U Qt综合例程源码

    I.MX6U Qt综合例程源码 介绍 正点原子I.MX6U Qt综合例程源码 使用说明 1.Windows下编译,安装Qt 5.12.9,可以在Windows编译,打开工程,编译完成后把src文件夹放 ...

  3. linux qt检测u盘热插拔,【QT】动态监测U盘插拔

    前言 在项目中,遇到一个需求:需要动态监测U盘插入,自动读取U盘文件并打开.为了实现这个功能,我们可以使用RegisterDeviceNotification注册设备事件的通知, 然后在程序中处理WM ...

  4. 【正点原子Linux连载】第十八章 Camera 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 3)全套实验源码+手册+视频下载地址: ...

  5. 【正点原子Linux连载】第二十二章 AP3216C 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 3)全套实验源码+手册+视频下载地址: ...

  6. 【正点原子Linux连载】 第十九章 CAN Bus 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 3)全套实验源码+手册+视频下载地址: ...

  7. 【正点原子Linux连载】第十一章 网络编程 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

  8. 【正点原子Linux连载】第六章 Qt Creator的使用技巧 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

  9. 【正点原子Linux连载】第十四章 Qt控制LED 摘自【正点原子】I.MX6U嵌入式Qt开发指南V1.0.2

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

  10. 【正点原子Linux连载】第六十七章 Linux USB驱动实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0

    1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...

最新文章

  1. Linux crontab 命令基本说明
  2. python if条件判断_python if not in 多条件判断代码
  3. Python+Anaconda+PyCharm的安装和基本使用
  4. 对EditText右边的图片进行监听
  5. openstack租户管理_openstack 租户、用户管理
  6. Eclipse 报java.lang.OutOfMemoryError: PermGen space错
  7. ORB-SLAM2中的Loop Closinng中DetectLoopCandidates函数解析
  8. java编写科赫曲线_matlab绘制peano(皮亚诺)曲线和koch(科赫曲线,雪花曲线)分形曲线...
  9. Django访问java建立的数据库
  10. hype-v的磁盘管理(转换)
  11. Kerberos的基本命令操作
  12. mysql自动化巡检_mysql自动化巡检脚本生成html报告
  13. JavaScrip节点属性-访问子节点
  14. type(img).__module__ == np.__name__
  15. Oracle Ravello的学习资料
  16. 计算机网络自顶向下方法第七版第六章答案,《计算机网络 自顶向下方法》(第7版)答案(第六章)(一)...
  17. 传:九大前缀,三大后缀
  18. 更改laravel的默认端口8000
  19. Android学习之——操作SIM卡联系人
  20. TCP短连接与长连接

热门文章

  1. Win10电脑系统恢复出厂设置教程
  2. 【深度学习】深度学习检测小目标常用方法
  3. 集群建设真的只是简单地搭几个设备柜子而已吗?
  4. 刚刚,马化腾在深圳说了,别慌!产业互联网春天刚开始,创新红利还有!
  5. 烧录系统后,SD卡内存变小的解决
  6. python讲师面试题_多测师讲解 ---面试题之python基础面试题---高级讲师肖sir
  7. 我的VIM配置--工欲善其事必先利其器
  8. 干货|开卷有益,大神级程序猿都在看的17本书
  9. 北京大学郭炜-生理周期 思路细讲
  10. 备战秋招,17年春招面经整理合集(170篇)