STDOUT和STDERR,以及它们的重定向

它们都是Linux系统的标准文件

在Linux系统中,有3个标准的文件,它们分别占据了文件编号:

  1. 0,STDIN,标准输入文件。
  2. 1,STDOUT,标准输出文件。
  3. 2,STDERR,标准错误文件。

它们仨在Linux系统中,都会有着具体的文件描述符限定着它们的特性,都对应着特定的输入输出设备:
img

其中,STDOUT与STDERR都会对应着输出设备,而且如果不重定向的话,它们的输出都会输出到屏幕(在Linux系统中,就是一种FrameBuffer的设备),所以有不少人容易把它们搞混。

STDOUT与STDERR的区别

我们应看到,它俩主要有两份点不同:

  1. 如果指定了输出是某个文件,则STDOUT的输出会到这个文件,而STDERR仍然继续输出到屏幕。
  2. STDOUT是行缓冲的,也就是只有有换行符时,其上的内容才会到指定的文件(不管是屏幕这个设备文件,还是其它的一般文件);而STDERR则不会有缓冲,所以有字节内容,它就会输出。

下面一段C的代码,大家可以试Run一下,来感受STDOUT缺省输出与重定向后的区别:


                
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是一个基于 Qt 的 WiFi Mesh 自组网示例代码: ```cpp #include <QCoreApplication> #include <QNetworkConfigurationManager> #include <QNetworkSession> #include <QProcess> #include <QTimer> #include <QSocketNotifier> #include <QDebug> // WiFi Mesh 自组网示例代码 #define CONFIG_FILE "/etc/wpa_supplicant.conf" #define CONFIG_TEMPLATE "ctrl_interface=/var/run/wpa_supplicant\n\ update_config=1\n\ \n\ network={\n\ ssid=\"%1\"\n\ mode=1\n\ frequency=2412\n\ proto=RSN\n\ key_mgmt=WPA-PSK\n\ pairwise=CCMP\n\ group=CCMP\n\ psk=\"%2\"\n\ }" class Node : public QObject { Q_OBJECT public: Node(const QString& name, const QString& ssid, const QString& password); public slots: void start(); void stop(); private slots: void readStdout(); void readStderr(); void processError(QProcess::ProcessError error); void processFinished(int exitCode, QProcess::ExitStatus exitStatus); void networkSessionOpened(); void networkSessionClosed(); void socketActivated(int fd); private: QString m_name; QString m_ssid; QString m_password; QString m_configFilePath; QProcess m_process; QNetworkConfigurationManager m_networkConfigManager; QNetworkSession* m_networkSession; QTimer m_timer; QSocketNotifier* m_socketNotifier; }; Node::Node(const QString& name, const QString& ssid, const QString& password) : QObject(nullptr) , m_name(name) , m_ssid(ssid) , m_password(password) , m_configFilePath(QString("/etc/wpa_supplicant-%1.conf").arg(name)) , m_process(this) , m_networkConfigManager(this) , m_networkSession(nullptr) , m_timer(this) , m_socketNotifier(nullptr) { connect(&m_process, &QProcess::readyReadStandardOutput, this, &Node::readStdout); connect(&m_process, &QProcess::readyReadStandardError, this, &Node::readStderr); connect(&m_process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished), this, &Node::processFinished); connect(&m_process, &QProcess::errorOccurred, this, &Node::processError); connect(&m_networkConfigManager, &QNetworkConfigurationManager::onlineStateChanged, this, &Node::networkSessionClosed); connect(&m_timer, &QTimer::timeout, this, &Node::start); } void Node::start() { if (m_networkSession && m_networkSession->isOpen()) { qDebug() << "Node" << m_name << "is already connected to the network"; return; } qDebug() << "Starting node" << m_name << "..."; // Write the configuration file for this node QFile configFile(m_configFilePath); if (configFile.open(QIODevice::WriteOnly | QIODevice::Text)) { QTextStream out(&configFile); out << QString(CONFIG_TEMPLATE).arg(m_ssid).arg(m_password); configFile.close(); } else { qCritical() << "Error writing configuration file for node" << m_name; return; } // Start the wpa_supplicant process QStringList arguments; arguments << "-Dnl80211" << "-c" << m_configFilePath; m_process.start("wpa_supplicant", arguments); // Wait for the process to start and create the control socket if (m_process.waitForStarted()) { m_socketNotifier = new QSocketNotifier(m_process.handle(), QSocketNotifier::Read, this); connect(m_socketNotifier, &QSocketNotifier::activated, this, &Node::socketActivated); } else { qCritical() << "Error starting wpa_supplicant for node" << m_name; } // Wait for the network session to be opened if (!m_networkSession) { m_networkSession = new QNetworkSession(m_networkConfigManager.defaultConfiguration(), this); connect(m_networkSession, &QNetworkSession::opened, this, &Node::networkSessionOpened); connect(m_networkSession, &QNetworkSession::closed, this, &Node::networkSessionClosed); } else { networkSessionOpened(); } } void Node::stop() { qDebug() << "Stopping node" << m_name << "..."; // Stop the wpa_supplicant process m_process.terminate(); if (!m_process.waitForFinished(5000)) { m_process.kill(); } // Delete the configuration file for this node QFile::remove(m_configFilePath); // Close the network session if (m_networkSession) { m_networkSession->close(); } } void Node::readStdout() { qDebug() << "Node" << m_name << "stdout:" << m_process.readAllStandardOutput(); } void Node::readStderr() { qWarning() << "Node" << m_name << "stderr:" << m_process.readAllStandardError(); } void Node::processError(QProcess::ProcessError error) { qCritical() << "Node" << m_name << "process error:" << error << m_process.errorString(); } void Node::processFinished(int exitCode, QProcess::ExitStatus exitStatus) { qDebug() << "Node" << m_name << "process finished with exit code" << exitCode << "and exit status" << exitStatus; } void Node::networkSessionOpened() { qDebug() << "Node" << m_name << "network session opened:" << m_networkSession->isOpen(); } void Node::networkSessionClosed() { qDebug() << "Node" << m_name << "network session closed:" << !m_networkSession->isOpen(); m_networkSession = nullptr; m_socketNotifier = nullptr; m_timer.start(1000); } void Node::socketActivated(int fd) { char buffer[1024]; int length = read(fd, buffer, sizeof(buffer)); if (length > 0) { qDebug() << "Node" << m_name << "control socket message:" << QString::fromUtf8(buffer, length); } } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // Start the nodes Node node1("node1", "mesh", "password"); Node node2("node2", "mesh", "password"); Node node3("node3", "mesh", "password"); node1.start(); node2.start(); node3.start(); // Stop the nodes after 10 seconds QTimer::singleShot(10000, &node1, &Node::stop); QTimer::singleShot(10000, &node2, &Node::stop); QTimer::singleShot(10000, &node3, &Node::stop); return a.exec(); } #include "main.moc" ``` 在上面的示例代码中,我们定义了一个 Node 类,它代表一个 WiFi Mesh 网络中的节点。在 Node 类的构造函数中,我们传入了节点的名称、SSID 和密码,同时生成了一个节点专用的 wpa_supplicant 配置文件。在 Node 类的 start() 方法中,我们启动了 wpa_supplicant 进程,并且等待它创建控制套接字。我们还创建了一个 QNetworkSession 对象,用于连接到 WiFi 网络,等待连接成功后,我们就可以使用这个节点了。在 Node 类的 stop() 方法中,我们停止了 wpa_supplicant 进程,并且删除了节点专用的 wpa_supplicant 配置文件。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DongAoTony

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值