热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

Linux下应用程序开发:QT的内部进程通信

文章标题:Linux下应用程序开发:QT的内部进程通信。Linux是中国IT实验室的一个技术频道。包含桌面应用,Linux系统管理,内核研究,嵌入式系统和开源等一些基本分类

  Qt 作为一种跨平台的基于 C++ 的 GUI 系统,能够提供给用户构造图形用户界面的强大功能。自从 1996 年 Qt 被 Trolltech 公司发布以来,该系统成为世界上很多成功的图形用户应用所使用的主要系统。更为重要的是,Linux 操作系统的桌面环境系统 KDE 也是基于 Qt 构造的。目前,Qt 已经提供了对包括 MS/Windows、Unix/X11 和嵌入式平台的支持,得到了越来越广泛的应用。
  
  在 Qt 系统中,不仅有着构造完善的系统结构,而且为了满足用户对编写图形用户界面应用的种种需求,它还创建了许多新的系统机制,其中 Qt 所特有的内部进程通信机制尤其值得一提。 本文分析了基于 QT 的应用进程之间通信常用的三种机制:QCOP 协议,Signal-Slot 机制和 FIFO 机制。给出了各自的使用方法,并指出了各自的使用场合。
  
  1、 QCOP协议
  QCOP 是 Qt 内部的一种通信协议,这种协议用于不同的客户之间在同一地址空间内部或者不同的进程之间的通信。目前,这种机制还只在 Qt 的嵌入式版本中提供。
  
  为实现这种通信机制,Qt 中包括了由 QObject 类继承而来的 QCopChannel 类,该类提供了诸如 send()、isRegistered() 等静态函数,它们可以在脱离对象的情况下使用。为了在 channel 中接收通信数据,用户需要构造一个 QCopChannel 的子类并提供 receive() 函数的重载函数,或者利用 connect() 函数与接收到的信号相联系。
  
  值得一提的是,在 Qt 系统中,只提供了 QCOP 协议机制和用于接收消息的类,而如何发送消息则没有提供相应的类供用户使用。
  
  在基于 Qt 的桌面系统 Qtopia(QPE)中,则提供了相应的发送类:QCopEnvelope。用户可以通过该类利用 channel 向其他进程发送消息。该类将通过 QCopChannel 发送 QCop 消息的过程进行了封装,用户只需要调用该类中的相关函数就可以方便地实现进程之间的通信过程。一方面,QCop 消息的发送要利用 QCopEnvelope 类,另一方面,接收消息则是通过与一个 QCopChannel 相关联。
  
  在发送消息时,将利用如下的协议机制:
  
  QCopEnvelope e(channelname, messagename);
  
  对于需要携带参数的消息,必须使用"<<()"运算符将参数添加到envelope中。
  
  e <  
  对于不带参数的消息,只需要利用:
  
  QCopEnvelope e(channelname, messagename);
  
  在Qtopia中,所有的channels名都以"QPE/"开始,而messagename则是一个函数的标识符。
  
  在接收消息时,通常只需要利用在应用程序中预先定义好的QPE/Application/{appname}管道,当然,也可以根据需要自己定义管道,并将其与一个slot函数相关联:
  
  myChannel = new QCopChannel( "QPE/FooBar", this );
  connect( myChannel, SIGNAL(received(const QCString &, const QByteArray &)),
       this, SLOT(fooBarmessage( const QCString &, const QByteArray &)) );
  
  下面将具体的通信过程举例如下:
  
  在需要接收消息的类(如Window1)中定义管道:
  
   QCopChannel *doChannel = new QCopChannel("QPE/Do", this);
   connect(doChannel, SIGNAL(received(const QCString &, const QByteArray &)), this, SLOT(doMessage(const QCString &, const QByteArray &)));
  
  同时,需要在该类中定义相应的消息处理函数doMessage,
  
  void Window1::doMessage(const QCString &msg, const QByteArray &args)
  {
   QDataStream stream(args, IO_ReadOnly);
   if(msg == "Message1(QString)")
   {
   QString text;
   stream >> text;
   button->setText(text);
   }
   else if(msg == "Message2()")
   {
   close();
   }
  }
  
  其中的Message1(QString)和Message2(QString)都是用户自己定义的消息,该函数中分别对这些消息进行了相应的处理。在该例中当收到带有参数的Message1消息时,将该字符串参数stream显示在按钮button上;当收到Message2消息时,将执行关闭Window1窗口的动作,当然用户可以根据需要自行编写相应的处理过程。
  
  另一方面,在类Class2中需要发出消息的函数function中利用QCopEnvelope发送消息:
  
  
  void Class2::function()
  {  QCopEnvelope e("QPE/Do", "Message1(QString)");
    e <  
  这里发出了Message1消息,并将需要携带的参数param发送到管道中。
  
  通过这样的过程,用户可以很方便地实现不同对象、不同进程之间通信过程,而且可以根据需要在通信过程中任意传递参数。
  
  2、 信号-槽(Signal-Slot)机制
  在Qt中,有一种用于对象之间的通信:信号-槽机制,这种机制是Qt的核心机制,也是它区别于其他GUI工具的最主要的特征。在大多数GUI工具中,通常为可能触发的每种行为定义一个回调函数,这个回调函数是一个指向函数的指针。在Qt中,信号-槽机制取代了这种繁杂的函数指针,能够实现同样的功能。信号-槽机制可以携带任意类型、任意数量的参数,而且完全是安全的,不会引起系统的崩溃。
  
  所有由QObject类继承而来的类,或者是它的一个子类,都可以包括信号-槽机制。信号通常是当对象改变他们的状态时发出的,这就是一个对象在需要与其他对象通信时所需要做的一切,它并不知道是否有其他对象在另一端接收该信号。从这个意义上来说,这种机制实现了真正的信息封装,确保了对象可以被当作一个独立的软件构件来使用。
  
  而槽可以被用于接收信号,它们通常是类中的成员函数。一个槽并不知晓是否有一个信号与自己相联系,同样,包含有槽函数的对象也对通信机制一无所知,它们也可以作为一个独立的软件构件。
  
  用户可以按照需要将许多信号与一个单独的槽函数相联系,一个信号也可以按需要被联系到很多不同的槽函数。甚至还可以将一个信号直接与另一个信号相联系,这样当第一个信号被发出时立刻发出第二个信号。
  
  这样,信号-槽相结合就产生了一种功能强大的编程机制。
  
  例如:
  
  button = new QAction(tr("button"), QIconSet(QPixmap("button.png")), 0, 0, this);
  connect(button, SIGNAL(activated()), this, SLOT(slotButton()));
  
  程序中定义了一个按钮,并利用connect()函数将该按钮button的activated()信号与slotButton()函数相关联,当用户触发按钮时,就会执行相应的槽函数。当然,这里的信号是QAction类中预先定义好的信号,用户在使用该机制时,可以根据需要自行定义信号,同时在适当的时候利用emit语句发出该信号。另外,在信号和相应的槽函数之间还可以传递任意参数,如:
  
  emit signal(parameter);
  
  3、 FIFO机制
  当然,除了 Qt 内部所特有的通信机制之外,一般操作系统中常用的进程间通信机制同样可以用于 Qt 系统内部不同进程之间的通信。如消息队列、共享内存、信号量、管道等机制,其中有些机制,如信号量,在 Qt 中重新进行了封装;有些机制则可以直接调用操作系统的系统调用来实现。这里,有名管道是一种简单实用的通信机制,用户在对Qt内部机制
  
  不甚了解的情况下,同样可以使用这种方法实现对象进程之间的通信。下面就对利用这种机制实现Qt内部进程之间的通信过程进行介绍。
  
  首先,需要创建 FIFO,这个过程类似于创建文件,在系统中可以利用 mkfifo 命令来创建,这样就可以用 open 函数打开它,同时,一般的文件 I/O函数(close、read、write)都可以用于 FIFO。
  
  在基于 Qt 的应用中,有很多应用采用了一种客户机-服务器模式,这时就可以利用 FIFO 在客户机和服务器之间传递数据。例如,有一个服务器,它负责接收底层程序发来的消息,同时,它与很多客户机有关,服务器需要将收到的不同消息发送到不同的客户机,而每个客户机也有请求需要发给服务器,进而发给底层程序。
  
  下面是服务器端的程序示例:(架设已有客户端进程为读而打开/dev/fifoclient1和/dev/fifoclient1)
  
  fd = open("/dev/fifoserver", O_NONBLOCK|O_RDONLY);
    file = fdopen(fd, "r");
  ret = fgets(buf, MAX_LINE, file );
   if(buf[0] == '0')
   {
    QFile fd_file("/dev/fifoclient1");
    QString temp(buf);
    if(fd_file.open(IO_WriteOnly|IO_Append)) {
       QTextStream t(&fd_file);
   t<    fd_file.close();
   }
   else if(buf[0] == '1')
   {
    QFile fd_file("/dev/fifoclient2");
    QString temp(buf);
    if(fd_file.open(IO_WriteOnly|IO_Append)) {
       QTextStream t(&fd_file);
   t<    fd_file.close();
   }
  ……
  
  在该程序中,服务器接收底层发来的信息(这里假设也是由 FIFO 管道传来),然后根据收到的信息内容,如第一个字节的内容,将信息发到不同客户端的管道中,实现对信息的正确分发。
  
  客户端程序示例如下:(假设服务器端已经为读而打开 /dev/fifo 管道)
  
  QFile out_file("/dev/fifo");
   if(out_file.open(IO_WriteOnly|IO_Append)) {
   QTextStream t(&out_file); 
  t <  
  当任意一
推荐阅读
  • 本文介绍了在Hibernate配置lazy=false时无法加载数据的问题,通过采用OpenSessionInView模式和修改数据库服务器版本解决了该问题。详细描述了问题的出现和解决过程,包括运行环境和数据库的配置信息。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • Win10下游戏不能全屏的解决方法及兼容游戏列表
    本文介绍了Win10下游戏不能全屏的解决方法,包括修改注册表默认值和查看兼容游戏列表。同时提供了部分已经支持Win10的热门游戏列表,帮助玩家解决游戏不能全屏的问题。 ... [详细]
  • 如何在联想win10专业版中修改账户名称
    本文介绍了在联想win10专业版中修改账户名称的方法,包括在计算机管理中找到要修改的账户,通过重命名来修改登录名和属性来修改显示名称。同时指出了windows10家庭版无法使用此方法的限制。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • Windows下配置PHP5.6的方法及注意事项
    本文介绍了在Windows系统下配置PHP5.6的步骤及注意事项,包括下载PHP5.6、解压并配置IIS、添加模块映射、测试等。同时提供了一些常见问题的解决方法,如下载缺失的msvcr110.dll文件等。通过本文的指导,读者可以轻松地在Windows系统下配置PHP5.6,并解决一些常见的配置问题。 ... [详细]
  • 电脑公司win7剪切板位置及使用方法
    本文介绍了电脑公司win7剪切板的位置和使用方法。剪切板一般位于c:\windows\system32目录,程序名为clipbrd.exe。通过在搜索栏中输入cmd打开命令提示符窗口,并输入clip /?即可调用剪贴板查看器。赶紧来试试看吧!更多精彩文章请关注本站。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文讲述了作者通过点火测试男友的性格和承受能力,以考验婚姻问题。作者故意不安慰男友并再次点火,观察他的反应。这个行为是善意的玩人,旨在了解男友的性格和避免婚姻问题。 ... [详细]
  • macOS10.12安装win10系统教程,实现双系统安装
    本文介绍了如何在macOS10.12系统上安装win10系统,实现双系统的安装。通过使用Boot Camp助理,选取win10系统镜像并分配系统容量,然后进行安装。安装完win10系统后,安装驱动并重启系统即可完成双系统的安装。 ... [详细]
author-avatar
手机用户2502914831
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有