Using QSocketNotifier to select on a char device.

2019-02-09 12:41发布

问题:

I wrote a char device driver and am now writing a QT "wrapper" which part of it is to get a signal to fire when the device becomes readable via the poll mechanism. I had tried to do:

QFile file("/dev/testDriver");
if(file.open(QFile::ReadOnly)) {
  QSocketNotifier sn(file.handle(), , QSocketNotifier::Read);
  sn.setEnabled(true);
  connect(&sn, SIGNAL(activated(int)), &this, SLOT(readyRead()));
}

But readyRead was never called and my driver never reported having its poll method called.

I was able to get the following code to work so I know my driver is working

QFile file("/dev/testDriver");
if(file.open(QFile::ReadOnly)) {
    struct pollfd fd;
    fd.fd = file.handle();
    fd.events = POLLIN;

    struct pollfd fds[] = {fd};
    int ready;
    qDebug() << "Started poll";
    ready = poll(fds, 1, -1);
    qDebug() << "Poll returned: " << ready;

    QTextStream in(&file);
    QTextStream out(stdout);
    out << in.readAll();
}

This properly waits for my driver to call wake_up and I can see two poll calls from my driver. One for the initial poll registration and one for when the wake_up happens.

Doing it this way I would probably have to spawn a separate thread which all it did was poll on this device and throw a signal and loop.

Is it possible to use QSocketNotifier in this way? The documentation of QFile::handle() seems to indicate it should be.

回答1:

Your QSocketNotifer gets destroyed as soon as that if block ends. It doesn't stand a chance of reporting anything.

You must keep that socket notifier alive as long as you want that file to be monitored. The simplest way of doing that is probably keeping a QSocketNotifer* member in one of your classes.



回答2:

I'll also mention that QSocketNotifier can be used to watch stdin using the following

#include "ConsoleReader.h"
#include <QTextStream>

#include <unistd.h> //Provides STDIN_FILENO

ConsoleReader::ConsoleReader(QObject *parent) :
    QObject(parent),
    notifier(STDIN_FILENO, QSocketNotifier::Read)
{
    connect(&notifier, SIGNAL(activated(int)), this, SLOT(text()));
}

void ConsoleReader::text()
{
    QTextStream qin(stdin);
    QString line = qin.readLine();
    emit textReceived(line);
}

---Header

#pragma once

#include <QObject>
#include <QSocketNotifier>

class ConsoleReader : public QObject
{
    Q_OBJECT
public:
    explicit ConsoleReader(QObject *parent = 0);
signals:
    void textReceived(QString message);
public slots:
    void text();
private:
    QSocketNotifier notifier;
};


标签: c++ linux qt4