///////////////////////////QSocketNotifier文档翻译/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
QSocketNotifier 类提供了对文件的监控活动的支持。
QSocketNotifier 类使Qt的事件循环和文件描述器的事件循环结合起来成为可能。文件描述器的动作可以被Qt的主事件循环( QCoreApplication::exec() )检测到。
一旦你打开了一个设备使用低级的api(通常基于特定平台), 你可以创建一个socket notifier 来监控文件描述器。这个socket notifier可能是默认的,也就是说不管基于何种平台发生了一个socket event 他都会发出activated()信号。连接这个activated()信号到你槽,你可以据此来处理你的socket notifier根据不同的事件类型的相对应的反应。
这有三种类型的socket notifies: 读,写,和异常。这个类型描述是由Type的枚举类型定义的,而且这个类型在构造socket notifier的时候必须指定。在构造之后它可以通过使用这个type()函数来决定。
注意:如果你需要监控包括同已文件描述器的读和写的行为,你就必须创建两个socket notifiers。同样注意,不能在同一socket上面安装两个相同类型(读,写,异常)的socket notifiers。
setEnabled()函数可以允许你禁用或者启用这个socket notifier. 一般的建议是显示的启用或者禁用socket notifier,尤其是write notifiers。 如果禁用的notifier, 则会忽略socket events(也就是同样的效果不会创建socket notifier)。使用isEnable()可以决定notifier当前的状态。
最终,如果你使用socket()函数将会获取到socket的标识符。当然这个类也被叫做QSocketNotifier, 用来获取设备类型的socket的通知通常是使用他,而不是使用socket. QTcpSocket和QUdpSocket通过信号来提供通知,因此没有必要在他们使用时再使用QSocketNotifer来获取通知。
QSocketNotifier::QSocketNotifier(qintptr socket, Type type, QObject *parent = Q_NULLPTR)、
通过给定父类就可以构造一个socket notifier。他就可以使用socket, watches对给定类型进行监控。
通常建议显示的使用enable或者disable来启用或者禁用socket notifier,尤其是写的notifier。
Windows上的用户注意:这个socket传递给QSocketNotifier就会成为非阻塞的,即使创建的是一个阻塞的socket.
void QSocketNotifier::activated(int socket)
当socket监控的对应的socket事件发生时,就会发送这个信号。
这个socket的标识符就是传递的socket的参数。
注意:这是一个私有的信号,他可能被信号连接,但是不能由用户自己发出。
///////////////////////////QSocketNotifier文档翻译/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
以监控:/proc/mounts 文件变化为demo
volumemonitor.h
#ifndef VOLUMEMONITOR_H #define VOLUMEMONITOR_H #include <QObject> #include <QSet> #include <QSocketNotifier> class VolumeMonitor : public QObject { Q_OBJECT public: VolumeMonitor(QObject *parent = 0); ~VolumeMonitor(); signals: void deviceAdded(const QString& addDev); void deviceRemoved(const QString& removeDe); public slots: bool start(); bool stop(); bool isRunning(); void onFileChanged(); private: int m_fileKde = -1; QSocketNotifier* m_socketNotifier; QSet<QString> m_fileContentSet; }; #endif // VOLUMEMONITOR_H
volumemonitor.cpp
#include "volumemonitor.h"
#include <fcntl.h>
#include <unistd.h>
#include <QFile>
#include <QSet>
#include <QTextStream>
#include <QDebug>
namespace {
const char mountFile[] = "/proc/mounts";
QSet <QString> getMountFileContent() {
QFile file(mountFile);
QSet <QString> fileContentSet;
if (file.exists()) {
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QTextStream textStream(&file);
QString fileContent = textStream.readAll();
QStringList items = fileContent.split("\n");
foreach (QString item, items) {
fileContentSet << item;
}
file.close();
}
}
return fileContentSet;
}
QString getMountPoint(const QString& record) {
const QStringList items = record.split(" ");
if (items.length() > 4) {
return items.at(1);
} else {
return "";
}
}
}
VolumeMonitor::VolumeMonitor(QObject *parent)
: QObject(parent)
{
}
bool VolumeMonitor::start() {
//get the set of mounted device's info;
m_fileContentSet = getMountFileContent();
m_fileKde = open(mountFile, O_RDONLY);
if (m_fileKde == -1) {
qWarning() << "open /proc/mounts failed!";
return false;
}
m_socketNotifier = new QSocketNotifier(m_fileKde,
QSocketNotifier::Write, this);
connect(m_socketNotifier, &QSocketNotifier::activated,
this, &VolumeMonitor::onFileChanged);
return true;
}
bool VolumeMonitor::isRunning() {
if (m_fileKde!= -1 && m_socketNotifier) {
return true;
} else {
return false;
}
}
bool VolumeMonitor::stop() {
if (this->isRunning()) {
close(m_fileKde);
m_fileKde = -1;
delete m_socketNotifier;
m_socketNotifier = nullptr;
return true;
} else {
return false;
}
}
void VolumeMonitor::onFileChanged() {
QSet <QString> changedItemSet = getMountFileContent();
for(const QString& item: changedItemSet - m_fileContentSet)
emit deviceAdded(getMountPoint(item));
for(const QString& item: m_fileContentSet - changedItemSet)
emit deviceRemoved(getMountPoint(item));
m_fileContentSet = changedItemSet;
}
VolumeMonitor::~VolumeMonitor()
{
this->stop();
}
本文档介绍了QSocketNotifier如何实现对文件描述符的监控,特别是用于Linux系统中U盘等设备的插拔检测。QSocketNotifier提供读、写、异常三种类型的监控,并通过activated()信号触发相应处理。在实际应用中,如监控/proc/mounts文件变化,以实现文件系统变化的跟踪。
906

被折叠的 条评论
为什么被折叠?



