Qt进程间通信

2023-11-17

进程是操作系统的基础之一。一个进程可以认为是一个正在执行的程序。我们可以把进程当做计算机运行时的一个基础单位。关于进程的讨论已经超出了本章的范畴,现在我们假定你是了解这个概念的。

在 Qt 中,我们使用 QProcess 来表示一个进程。这个类可以允许我们的应用程序开启一个新的外部程序,并且与这个程序进行通讯。下面我们用一个非常简单的例子开始我们本章有关进程的阐述。

//!!! Qt5
QString program = "C:/Windows/System32/cmd.exe";
QStringList arguments;
arguments << "/c" << "dir" << "C:\\";
QProcess *cmdProcess = new QProcess;
QObject::connect(cmdProcess, &QProcess::readyRead, [=] () {
    QTextCodec *codec = QTextCodec::codecForName("GBK");
    QString dir = codec->toUnicode(cmdProcess->readAll());
    qDebug() << dir;
});
cmdProcess->start(program, arguments);

这是一段 Qt5 的程序,并且仅能运行于 Windows 平台。简单来说,这段程序通过 Qt 开启了一个新的进程,这个进程相当于执行了下面的命令:

C:\Windows\System32\cmd.exe /c dir C:\

注意,我们可以在上面的程序中找到这个命令的每一个字符。事实上,我们可以把一个进程看做执行了一段命令(在 Windows 平台就是控制台命令;在 Linux 平台(包括 Unix)则是执行一个普通的命令,比如 ls)。我们的程序相当于执行了 dir 命令,其参数是 C:\,这是由 arguments 数组决定的(至于为什么我们需要将 dir 命令作为参数传递给 cmd.exe,这是由于 Windows 平台的规定。在 Windows 中,dir 命令并不是一个独立的可执行程序,而是通过 cmd.exe 进行解释;这与 ls 在 Linux 中的地位不同,在 Linux 中,ls 就是一个可执行程序。因此如果你需要在 Linux 中执行 ls,那么 program 的值应该就是 ls )。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

上面程序的运行结果类似于:

驱动器 C 中的卷是 SYSTEM

卷的序列号是 EA62-24AB

 C:\ 的目录

2013/05/05  20:41             1,024 .rnd
2013/08/22  23:22    <DIR>          PerfLogs
2013/10/18  07:32    <DIR>          Program Files
2013/10/30  12:36    <DIR>          Program Files (x86)
2013/10/31  20:30            12,906 shared.log

2013/10/18  07:33    <DIR>          Users
2013/11/06  21:41    <DIR>          Windows
               2 个文件         13,930 字节
               5 个目录 22,723,440,640 可用字节

上面的输出会根据不同机器有所不同。豆子是在 Windows 8.1 64 位机器上测试的。

为了开启进程,我们将外部程序名字(program)和程序启动参数(arguments)作为参数传给 QProcess::start() 函数。当然,你也可以使用 setProgram() 和 setArguments() 进行设置。此时,QProcess 进入 Starting 状态;当程序开始执行之后,QProcess 进入 Running 状态,并且发出 started() 信号。当进程退出时,QProcess 进入 NotRunning 状态(也是初始状态),并且发出 finished() 信号。finished() 信号以参数的形式提供进程的退出代码和退出状态。如果发送错误,QProcess 会发出 error() 信号

QProcess 允许你将一个进程当做一个顺序访问的 I/O 设备。我们可以使用 write() 函数将数据提供给进程的标准输入;使用 read()、readLine() 或者 getChar() 函数获取其标准输出。由于 QProcess 继承自 QIODevice,因此 QProcess 也可以作为 QXmlReader 的输入或者直接使用 QNetworkAccessManager 将其生成的数据上传到网络。

进程通常有两个预定义的通道:标准输出通道(stdout)和标准错误通道(stderr)。前者就是常规控制台的输出,后者则是由进程输出的错误信息。这两个通道都是独立的数据流,我们可以通过使用 setReadChannel() 函数来切换这两个通道。当进程的当前通道可用时,QProcess 会发出 readReady() 信号。当有了新的标准输出数据时,QProcess 会发出 readyReadStandardOutput() 信号;当有了新的标准错误数据时,则会发出 readyReadStandardError() 信号。我们前面的示例程序就是使用了 readReady() 信号。注意,由于我们是运行在 Windows 平台,Windows 控制台的默认编码是 GBK,为了避免出现乱码,我们必须设置文本的编码方式。

通道的术语可能会引起误会。注意,进程的输出通道对应着 QProcess 的 通道,进程的输入通道对应着 QProcess 的 通道。这是因为我们使用 QProcess“读取” 进程的输出,而我们针对 QProcess 的 “写入” 则成为进程的输入。QProcess 还可以合并标准输出和标准错误通道,使用 setProcessChannelMode() 函数设置 MergedChannels 即可实现。

另外,QProcess 还允许我们使用 setEnvironment() 为进程设置环境变量,或者使用 setWorkingDirectory() 为进程设置工作目录。

前面我们所说的信号槽机制,类似于前面我们介绍的 QNetworkAccessManager,都是异步的。与 QNetworkAccessManager 不同在于,QProcess 提供了同步函数:

  • waitForStarted():阻塞到进程开始;
  • waitForReadyRead():阻塞到可以从进程的当前读通道读取新的数据;
  • waitForBytesWritten():阻塞到数据写入进程;
  • waitForFinished():阻塞到进程结束;

注意,在主线程(调用了 QApplication::exec() 的线程)调用上面几个函数会让界面失去响应。

上面我们了解了有关进程的基本知识。我们将进程理解为相互独立的正在运行的程序。由于二者是相互独立的,就存在交互的可能性,也就是我们所说的进程间通信(Inter-Process Communication,IPC)。不过也正因此,我们的一些简单的交互方式,比如普通的信号槽机制等,并不适用于进程间的相互通信。我们说过,进程是操作系统的基本调度单元,因此,进程间交互不可避免与操作系统的实现息息相关。

Qt 提供了四种进程间通信的方式:

  1. 使用共享内存(shared memory)交互:这是 Qt 提供的一种各个平台均有支持的进程间交互的方式。
  2. TCP/IP:其基本思想就是将同一机器上面的两个进程一个当做服务器,一个当做客户端,二者通过网络协议进行交互。除了两个进程是在同一台机器上,这种交互方式与普通的 C/S 程序没有本质区别。Qt 提供了 QNetworkAccessManager 对此进行支持。
  3. D-Bus:freedesktop 组织开发的一种低开销、低延迟的 IPC 实现。Qt 提供了 QtDBus 模块,把信号槽机制扩展到进程级别(因此我们前面强调是 “普通的” 信号槽机制无法实现 IPC),使得开发者可以在一个进程中发出信号,由其它进程的槽函数响应信号。
  4. QCOP(Qt COmmunication Protocol):QCOP 是 Qt 内部的一种通信协议,用于不同的客户端之间在同一地址空间内部或者不同的进程之间的通信。目前,这种机制只用于 Qt for Embedded Linux 版本。

从上面的介绍中可以看到,通用的 IPC 实现大致只有共享内存和 TCP/IP 两种。后者我们前面已经大致介绍过(应用程序级别的 QNetworkAccessManager 或者更底层的 QTcpSocket 等);本章我们主要介绍前者。

Qt 使用 QSharedMemory 类操作共享内存段。我们可以把 QSharedMemory 看做一种指针,这种指针指向分配出来的一个共享内存段。而这个共享内存段是由底层的操作系统提供,可以供多个线程或进程使用。因此,QSharedMemory 可以看做是专供 Qt 程序访问这个共享内存段的指针。同时,QSharedMemory 还提供了单一线程或进程互斥访问某一内存区域的能力。当我们创建了 QSharedMemory 实例后,可以使用其 create() 函数请求操作系统分配一个共享内存段。如果创建成功(函数返回 true),Qt 会自动将系统分配的共享内存段连接(attach)到本进程。

前面我们说过,IPC 离不开平台特性。作为 IPC 的实现之一的共享内存也遵循这一原则。有关共享内存段,各个平台的实现也有所不同:

  • Windows:QSharedMemory 不 “拥有” 共享内存段。当使用了共享内存段的所有线程或进程中的某一个销毁了 QSharedMemory 实例,或者所有的都退出,Windows 内核会自动释放共享内存段。
  • Unix:QSharedMemory“拥有” 共享内存段。当最后一个线程或进程同共享内存分离,并且调用了 QSharedMemory 的析构函数之后,Unix 内核会将共享内存段释放。注意,这里与 Windows 不同之处在于,如果使用了共享内存段的线程或进程没有调用 QSharedMemory 的析构函数,程序将会崩溃。
  • HP-UX:每个进程只允许连接到一个共享内存段。这意味着在 HP-UX 平台,QSharedMemory 不应被多个线程使用。

下面我们通过一段经典的代码来演示共享内存的使用。这段代码修改自 Qt 自带示例程序(注意这里直接使用了 Qt5,Qt4 与此类似,这里不再赘述)。程序有两个按钮,一个按钮用于加载一张图片,然后将该图片放在共享内存段;第二个按钮用于从共享内存段读取该图片并显示出来。

//!!! Qt5

class QSharedMemory;

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    QSharedMemory *sharedMemory;
};

头文件中,我们将 MainWindow 添加一个 sharedMemory 属性。这就是我们的共享内存段。接下来得实现文件中:

const char *KEY_SHARED_MEMORY = "Shared";

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      sharedMemory(new QSharedMemory(KEY_SHARED_MEMORY, this))
{
    QWidget *mainWidget = new QWidget(this);
    QVBoxLayout *mainLayout = new QVBoxLayout(mainWidget);
    setCentralWidget(mainWidget);

    QPushButton *saveButton = new QPushButton(tr("Save"), this);
    mainLayout->addWidget(saveButton);
    QLabel *picLabel = new QLabel(this);
    mainLayout->addWidget(picLabel);
    QPushButton *loadButton = new QPushButton(tr("Load"), this);
    mainLayout->addWidget(loadButton);

构造函数初始化列表中我们将 sharedMemory 成员变量进行初始化。注意我们给出一个键(Key),前面说过,我们可以把 QSharedMemory 看做是指向系统共享内存段的指针,而这个键就可以看做指针的名字。多个线程或进程使用同一个共享内存段时,该键值必须相同。接下来是两个按钮和一个标签用于界面显示,这里不再赘述。

下面来看加载图片按钮的实现:

    connect(saveButton, &QPushButton::clicked, [=]() {
        if (sharedMemory->isAttached()) {
            sharedMemory->detach();
        }
        QString filename = QFileDialog::getOpenFileName(this);
        QPixmap pixmap(filename);
        picLabel->setPixmap(pixmap);

        QBuffer buffer;
        QDataStream out(&buffer);
        buffer.open(QBuffer::ReadWrite);
        out << pixmap;

        int size = buffer.size();
        if (!sharedMemory->create(size)) {
            qDebug() << tr("Create Error: ") << sharedMemory->errorString();
        } else {
            sharedMemory->lock();
            char *to = static_cast<char *>(sharedMemory->data());
            const char *from = buffer.data().constData();
            memcpy(to, from, qMin(size, sharedMemory->size()));
            sharedMemory->unlock();
        }
    });

点击加载按钮之后,如果 sharedMemory 已经与某个线程或进程连接,则将其断开(因为我们就要向共享内存段写入内容了)。然后使用 QFileDialog 选择一张图片,利用 QBuffer 将图片数据作为 char * 格式。在即将写入共享内存之前,我们需要请求系统创建一个共享内存段(QSharedMemory::create() 函数),创建成功则开始写入共享内存段。需要注意的是,在读取或写入共享内存时,都需要使用 QSharedMemory::lock() 函数对共享内存段加锁。共享内存段就是一段普通内存,所以我们使用 C 语言标准函数 memcpy() 复制内存段。不要忘记之前我们对共享内存段加锁,在最后需要将其解锁。

接下来是加载按钮的代码:

    connect(loadButton, &QPushButton::clicked, [=]() {
        if (!sharedMemory->attach()) {
            qDebug() << tr("Attach Error: ") << sharedMemory->errorString();
        } else {
            QBuffer buffer;
            QDataStream in(&buffer);
            QPixmap pixmap;
            sharedMemory->lock();
            buffer.setData(static_cast<const char *>(sharedMemory->constData()), sharedMemory->size());
            buffer.open(QBuffer::ReadWrite);
            in >> pixmap;
            sharedMemory->unlock();
            sharedMemory->detach();
            picLabel->setPixmap(pixmap);
        }
    });

如果共享内存段已经连接,还是用 QBuffer 读取二进制数据,然后生成图片。注意我们在操作共享内存段时还是要先加锁再解锁。最后在读取完毕后,将共享内存段断开连接。

注意,如果某个共享内存段不是由 Qt 创建的,我们也是可以在 Qt 应用程序中使用。不过这种情况下我们必须使用 QSharedMemory::setNativeKey() 来设置共享内存段。使用原始键(native key)时,QSharedMemory::lock() 函数就会失效,我们必须自己保护共享内存段不会在多线程或进程访问时出现问题。

IPC 使用共享内存通信是一个很常用的开发方法。多个进程间得通信要比多线程间得通信少一些,不过在某一族的应用情形下,比如 QQ 与 QQ 音乐、QQ 影音等共享用户头像,还是非常有用的。

本文福利,费领取Qt开发学习资料包、技术视频,内容包括(C++语言基础,Qt编程入门,QT信号与槽机制,QT界面开发-图像绘制,QT网络,QT数据库编程,QT项目实战,QSS,OpenCV,Quick模块,面试题等等)↓↓↓↓↓↓见下面↓↓文章底部点击费领取↓↓

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt进程间通信 的相关文章

  • 如何在 Linux shell 中将十六进制转换为 ASCII 字符?

    假设我有一个字符串5a 这是 ASCII 字母的十六进制表示Z 我需要找到一个 Linux shell 命令 它将接受一个十六进制字符串并输出该十六进制字符串代表的 ASCII 字符 所以如果我这样做 echo 5a command im
  • Qt 5.3 无法使 QCompass (QSensor) 在 Windows 8.1 上工作

    我无法让传感器在我的 Asus Transformer T100 上工作 磁力计和指南针无法启动 并且我从加速度计获得假值 始终 x 0 y 9 8 z 0 即使使用我的笔记本电脑 我总是得到相同的结果 第一段文字编辑 Initialisa
  • PHP 从命令行启动 gui 程序,但 apache 不启动

    首先 我阅读了有类似问题的人的一些帖子 但所有答案都没有超出导出 DISPLAY 0 0 和 xauth cookies 这是我的问题 提前感谢您的宝贵时间 我开发了一个小库 它使用 OpenGL 和 GLSL 渲染货架 过去几天我将它包装
  • Git difftool 未启动外部 DiffMerge 程序

    我一直遵循 戴夫的博客条目 http www davesquared net 2009 05 setting up git difftool on windows html 链接在此answer https stackoverflow co
  • Qt - 获取互联网上托管的网页的源代码(HTML 代码)

    我想获取网页的源代码 HTML 例如StackOverflow的主页 这是我到目前为止编写的代码 QNetworkAccessManager manager QNetworkReply response manager get QNetwo
  • 如何向同一个 QMenu 添加多个 QAction?

    我正在尝试实现 Qt 菜单自定义 并且我提供了一个功能来添加相同的功能QAction在同一个人民币上下文菜单中多次 但是当我尝试这样做时 myMenu gt addAction myAction myMenu gt addAction my
  • os.Mkdir 和 os.MkdirAll 权限

    我正在尝试在程序开始时创建一个日志文件 我需要检查是否 log如果不创建目录 则目录存在 然后继续创建日志文件 好吧 我尝试使用os Mkdir 也os MkdirAll 但无论我在第二个参数中输入什么值 我都会得到一个没有权限的锁定文件夹
  • 静态变量中的 qt tr()

    我在 qt 中的翻译方面遇到问题 我的项目中的所有翻译都工作正常 但有一个翻译位于类的静态变量中 相应部分代码如下 头文件类似于这样 typedef struct int type QString problematicString inf
  • 如何在Windows中的Python 3.9下pip安装pickle?

    我需要pickle https docs python org 3 9 library pickle html module pickle包安装在我的下面Python 3 9在 Windows 10 下 我尝试过的 当尝试与pip inst
  • 如何捕获未发送到 stdout 的命令行文本?

    我在项目中使用 LAME 命令行 mp3 编码器 我希望能够看到某人正在使用什么版本 如果我只执行 LAME exe 而不带参数 我会得到 例如 C LAME gt LAME exe LAME 32 bits version 3 98 2
  • 通过 PowerShell 运行 .cmd 文件

    我正在尝试使用 PowerShell 在远程服务器上运行 cmd 文件 在我的 ps1 脚本中我尝试过 C MyDirectory MyCommand cmd 它会导致此错误 C MyDirectory MyCommand cmd is n
  • 是否可以在 Qt Creator 中将 Qt 样式表与升级的小部件一起使用?

    我正在尝试使用 Qt 样式表对标准小部件进行一些重大的重新设计 因此 在为不同的小部件手动完成大部分工作之后 objectName选择器 我决定以某种方式对类似的小部件进行分组 例如我有多个QFrames其作用类似于内部表单中的标题 我希望
  • 为什么 QGraphicsWidget 的选择边框在 QGraphicsScene 中不可见?

    我已经通过一个小部件添加到图形场景 QGraphicSscene QGraphicsProxyWidget 问题是 当我选择该项目时 它被选中 但选择边框不可见 这是代码 QDial dial new QDial Widget dial g
  • PHP 无法打开流:是一个目录

    非常简单的 PHP 脚本 我在我亲自设置的 Ubuntu Web 服务器上的 EE 模板中运行 我知道这与权限有关 并且我已经将我尝试写入的目录的所有者更改为 Apache 用户 我得到的错误是 遇到 PHP 错误 严重性 警告 消息 fi
  • Qt GUI 应用程序中的控制台输出?

    我有一个在 Windows 上运行的 Qt GUI 应用程序 它允许传递命令行选项 在某些情况下我想向控制台输出一条消息 然后退出 例如 int main int argc char argv QApplication a argc arg
  • jq中如何分组?

    这是 json 文档 name bucket1 clusterName cluster1 name bucket2 clusterName cluster1 name bucket3 clusterName cluster2 name bu
  • 查找哪个程序运行另一个程序

    我有一个 NAS 运行在 Redhat Linux 的有限版本上 我按照指示破解了它 这样我就可以访问 shell 这很有帮助 我还做了一些修改 其他人也做过修改 除了一个问题之外 它们似乎都工作得很好 不知何故 每隔 22 天 系统就会关
  • Linux 上有关 getBounds() 和 setBounds() 的 bug_id=4806603 的解决方法?

    在 Linux 平台上 Frame getBounds 和 Frame setBounds 的工作方式不一致 这在 2003 年就已经有报道了 请参见此处 http bugs java com bugdatabase view bug do
  • Tkinter - 浮动窗口 - 调整大小

    灵感来自this https stackoverflow com a 22424245 13629335问题 我想为我的根窗口编写自己的调整大小函数 但我刚刚注意到我的代码显示了一些性能问题 如果你快速调整它的大小 你会发现窗口没有像我希望
  • 如何一步步遍历目录树?

    我发现了很多关于遍历目录树的示例 但我需要一些不同的东西 我需要一个带有某种方法的类 每次调用都会从目录返回一个文件 并逐渐遍历目录树 请问我该怎么做 我正在使用函数 FindFirstFile FindNextFile 和 FindClo

随机推荐

  • 分布式协议与算法——Paxos算法

    目录 Paxos算法 Basic Paxos算法 三种角色 如何达成共识 协商过程 小结 Multi Paxos算法 关于 Multi Paxos 的思考 领导者 优化Basic Paxos Chubby 的 Multi Paxos 实现
  • 解决Elasticsearch查询默认最大值返回10000

    文章目录 1 问题描述 1 描述 2 分析 2 解决方案 1 更改当前索引最大查询条数 max result window 2 能查出数据 但是total依然还是1000 更改track total hits 3 当java使用时应该 4
  • android webview 加载本地html并且解决多图卡顿问题

    使用webview加载本地html 因为本地html使用多张图片 滑动起来卡顿 解决方法如下 把文件夹放入assets文件夹下 Activity加载 WebView wView WebView findViewById R id webvi
  • PANet:基于金字塔注意力网络的图像超分辨率重建(全代码)

    PANet 基于金字塔注意力网络的图像超分辨率重建 本文为全代码 原文请看 传送门 import torch import torch nn as nn import torch nn functional as F from torch
  • 运维实战案例之文件已删除但空间不释放问题解析

    1 错误现象 运维的监控系统发来通知 报告一台服务器空间满了 登陆服务器查看 根分区确实没有空间了 如下图所示 这里首先说明一下服务器的一些删除策略 由于Linux没有回收站功能 我们的线上服务器所有要删除的文件都会首先移动到系统 tmp目
  • 请使用mysql连接池

    在初次使用 python 的 pymysql工具包连接 mysql数据库 的时候 总是发生数据库连接失败的情况发生 经过多方确认 发现这种情况不是自己的连接方式错了 而是mysql数据库服务器因为网络出现闪断 导致在查询的时候发生连接出错的
  • 深度学习与计算机视觉[CS231N] 学习笔记(4.1):反向传播(Backpropagation)

    在学习深度学习的过程中 我们常用的一种优化参数的方法就是梯度下降法 而一般情况下 我们搭建的神经网络的结构是 输入 权重矩阵 损失函数 如下图所示 而在给定输入的情况下 为了使我们的损失函数值达到最小 我们就需要调节权重矩阵 使之满足条件
  • DQN理论基础及其代码实现【Pytorch + CartPole-v0】

    DQN算法的理论基础 基于动态规划方法 基于蒙特卡罗方法和基于时间差分的方法都有一个基本的前提条件 状态空间和动作空间是离散的 而且状态空间和动作空间不能太大 这些强化学习方法的基本步骤是先评估值函数 再利用值函数改善当前的策略 这时的值函
  • ROS rosdep update 出错方法 不需要翻墙切换之类的解决方法 ‘https://raw.githubusercontent.com/ros/rosdistro/master/inde

    系统 ubuntu18 rosdep update参考的这篇文章 https blog csdn net weixin 43311920 article details 114796748 utm source app app versio
  • HBase NoSQL数据库详解

    一 HBase简介 HBase是Hadoop的生态系统 是建立在Hadoop文件系统 HDFS 之上的分布式 面向列的数据库 通过利用Hadoop的文件系统提供容错能力 如果你需要进行实时读写或者随机访问大规模的数据集的时候 请考虑使用HB
  • Android获取当前位置的三种方式及其使用方法

    1 GPS定位 2 基站定位 此类位置的获取有赖于手机无线通讯信号 当手机处在信号覆盖范围内 手机可以获得该区域 即通讯术语中的 小区 的识别号 因为这些识别号是惟一的 因此可以将识别号和地理坐标对应起来 因此根据识别号就可以知道地理位置
  • Unity3D 使用TextMeshPro中文字体

    这一篇简单描述一下如果使用unity的一个强大的文字组件或者插件 开始 第一步 如果你是unity2018版本的话 在编辑器里面的AssetPackgeManager找到这个插件 没有的话就在搜索框里面搜索下载 如果你是低于2018的版本
  • Xilinx ISE系列教程(8):读取FPGA芯片唯一ID号

    文章目录 toc 应用场景 方法1 通过JTAG读取 方法2 调用原语读取 DNA PORT原语的使用 DNACLK频率注意 本文是Xilinx ISE系列教程的第8篇文章 用过单片机的朋友都知道 单片机芯片内部都有一串序列号 比如STM3
  • OkHttp库简介

    一直以来 Java并没有什么比较好用的HTTP库 JDK自带的HTTP类又非常旧 难以使用 今天我发现了一个使用比较广泛的OkHttp库 它在安卓和Java领域都有使用 在Github上的星数有两万多 所以我们可以放心的使用 安装 先来看看
  • linkToDeath机制了解和使用

    转自 http www jianshu com p e38f08e34686 在学习Binder和AIDL的过程中遇到的一些有意思的事情 linkToDeath机制 我们先看看官网如何介绍 When working with remote
  • pytorch:参数pin_memory=True和non_blocking=True的作用

    目录 一 pin memory 二 non blocking 一 pin memory pin memory是dataloader 的参数 默认值为False 其作用是是否把把数据存放在锁页内存中 主机的内存根据物理内存 内存条 与虚拟内存
  • 服务器2012系统截屏,Windows Server 2012 R2 Preview界面截图

    微软将在BUILD大会上公开发布Windows 8 1 预览版 Windows 8 1是Windows Blue升级项目的一部分 那么一直以来与Windows客户端如影随形的Windows Server呢 是的 Blue项目并非仅为Wind
  • 微信小程序和APP优劣势大对比

    小程序的优势 1 无需下载 随走随关 2 功能丰富 体验更简便 3 接口众多 可以进行不断的开发 4 流量入口大 背靠日活9 6亿的微信 5 有强大的微信生态环境 小程序对比APP的好处 1 开发成本低 2 开发门槛低 3 获客成本低于Ap
  • 星星之火-47: 5G的八大组网方案

    目录 1 5G组网方案概述 2 选项3系列 4G LTE接入网 5G NR 接入网 4G LTE核心网 3 选项2 5G NR 5G 核心网 4 选项7系列 4G LTE接入网 5G NR接入网 5G核心网 5 选项4系列 4G LTE接入
  • Qt进程间通信

    进程是操作系统的基础之一 一个进程可以认为是一个正在执行的程序 我们可以把进程当做计算机运行时的一个基础单位 关于进程的讨论已经超出了本章的范畴 现在我们假定你是了解这个概念的 在 Qt 中 我们使用 QProcess 来表示一个进程 这个