QSocketNotifier 实现文件监控(demo Linux系统U盘插拔监控)

来源:互联网 发布:linux ll 命令 编辑:程序博客网 时间:2024/06/05 15:50

///////////////////////////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 socketType typeQObject *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_OBJECTpublic:    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();}

0 0