Linux 程序开发 QT内部进程通信

移动开发
QCOP 是Qt 内部的一种通信协议,这种协议用于不同的客户之间在同一地址空间内部或者不同的进程之间的通信。目前,这种机制还只在Qt 的嵌入式版本中提供。

Linux 程序开发QT内部进程通信的内容是本文要介绍的内容,在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 相关联。在发送消息时,将利用如下的协议机制:

  1. QCopEnvelope e(channelname, messagename); 

对于需要携带参数的消息,必须使用"<<()"运算符将参数添加到envelope 中。

  1. << parameter1 << parameter2 << ...

对于不带参数的消息,只需要利用:

  1. QCopEnvelope e(channelname, messagename); 

在Qtopia 中,所有的channels 名都以"QPE/"开始,而messagename 则是一个函数的标识符。在接收消息时,通常只需要利用在应用程序中预先定义好的QPE/Application/{appname}管道,当然,也可以根据需要自己定义管道,并将其与一个slot 函数相关联:

  1. myChannel = new QCopChannel( "QPE/FooBar", this );;  
  2. connect( myChannel, SIGNAL(received(const QCString &, const QByteArray &)),this,  
  3. SLOT(fooBarMessage( const QCString &, const QByteArray &)) ); 

下面将具体的通信过程举例如下,在需要接收消息的类(如Window1)中定义管道:

  1. QCopChannel *doChannel = new QCopChannel("QPE/Do", this);  
  2. connect(doChannel, SIGNAL(received(const QCString &, const QByteArray &)),  
  3. this, SLOT(doMessage  
  4. (const QCString &, const QByteArray &))); 

同时,需要在该类中定义相应的消息处理函数doMessage,

  1. void Window1::doM essage(const QCString &msg, const QByteArray &args)  
  2. {  
  3. QDataStream stream(args, IO_ReadOnly);  
  4. if(msg == "Message1(QString)")  
  5. {  
  6. QString text;  
  7. stream >> text;  
  8. button->setText(text);  
  9. }  
  10. else if(msg == "Message2()")  
  11. {  
  12. close();  
  13. }  


其中的Message1(QString)和Message2(QString)都是用户自己定义的消息,该函数中分别对这些消息进行了相应的处理。在该例中当收到带有参数的Message1 消息时,将该字符串参数stream 显示在按钮button 上;当收到Message2 消息时,将执行关闭Window1 窗口的动作,当然用户可以根据需要自行编写相应的处理过程。

另一方面,在类Class2 中需要发出消息的函数function 中利用QCopEnvelope 发送消息:

  1. void Class2::function()  
  2.  
  3. {  
  4. QCopEnvelope e("QPE/Do", "Message1(QString)");  
  5. << param; } 

这里发出了Message1 消息,并将需要携带的参数param 发送到管道中。通过这样的过程,用户可以很方便地实现不同对象、不同进程之间通信过程,而且可以根据需要在通信过程中任意传递参数。

2、信号-槽(Signal-Slot)机制

在Qt 中,有一种用于对象之间的通信:信号-槽机制,这种机制是Qt 的核心机制,也是它区别于其他GUI 工具的最主要的特征。在大多数GUI 工具中,通常为可能触发的每种
行为定义一个回调函数,这个回调函数是一个指向函数的指针。在Qt 中,信号-槽机制取代这种繁杂的函数指针,能够实现同样的功能。信号-槽机制可以携带任意类型、任意数量
的参数,而且完全是安全的,不会引起系统的崩溃。

所有由QObject 类继承而来的类,或者是它的一个子类,都可以包括信号-槽机制。信号通常是当对象改变他们的状态时发出的,这就是一个对象在需要与其他对象通信时所需要做的一切,它并不知道是否有其他对象在另一端接收该信号。从这个意义上来说,这种机制实现了真正的信息封装,确保了对象可以被当作一个独立的软件构件来使用。

而槽可以被用于接收信号,它们通常是类中的成员函数。一个槽并不知晓是否有一个信号与自己相联系,同样,包含有槽函数的对象也对通信机制一无所知,它们也可以作为一个独立的软件构件。用户可以按照需要将许多信号与一个单独的槽函数相联系,一个信号也可以按需要被联系到很多不同的槽函数。甚至还可以将一个信号直接与另一个信号相联系,这样当***个信号被发出时立刻发出第二个信号。这样,信号-槽相结合就产生了一种功能强大的编程机制。

例如:

  1. button = new QAction(tr("button"), QIconSet(QPixmap("button.png")), 0, 0, this);  
  2. connect(button, SIGNAL(activated()), this, SLOT(slotButton())); 

程序中定义了一个按钮,并利用connect()函数将该按钮button 的activated()信号与slotButton()函数相关联,当用户触发按钮时,就会执行相应的函数。当然,这里的信号是QAction 类中预先定义好的信号,用户在使用该机制时,可以根据需要自行定义信号,同时在适当的时候利用emit 语句发出该信号。另外,在信号和相应的函数之间还可以传递任
意参数,如:

  1. emit signal(parameter); emit signal(parameter); 

3、FIFO 机制

当然,除了Qt 内部所特有的通信机制之外,一般操作系统中常用的进程间通信机制同样可以用于Qt 系统内部不同进程之间的通信。如消息队列、共享内存、信号量、管道等机制,其中有些机制,如信号量,在Qt 中重新进行了封装;有些机制则可以直接调用操作系统的系统调用来实现。这里,有名管道是一种简单实用的通信机制,用户在对Qt 内部机制不甚了解的情况下,同样可以使用这种方法实现对象进程之间的通信。下面就对利用这种机制实现Qt 内部进程之间的通信过程进行介绍。首先,需要创建FIFO,这个过程类似于创建文件,在系统中可以利用mkfifo 命令来创建,这样就可以用open 函数打开它,同时,一般的文件I/O 函数(close、read、write)都可以用于FIFO。

在基于Qt 的应用中,有很多应用采用了一种客户机-服务器模式,这时就可以利用FIFO 在客户机和服务器之间传递数据。例如,有一个服务器,它负责接收底层程序发来的消息,同时,它与很多客户机有关,服务器需要将收到的不同消息发送到不同的客户机,而每个客户机也有请求需要发给服务器,进而发给底层程序。

下面是服务器端的程序示例:(架设已有客户端进程为读而打开/dev/fifoclient1 和

  1. /dev/fifoclient1)  
  2. fd = open("/dev/fifoserver", O_NONBLOCK|O_RDONLY);  
  3. file = fdopen(fd, "r");  
  4. ret = fgets(buf, MAX_LINE, file );  
  5. if(buf[0] == '0')  
  6. {  
  7. QFile fd_file("/dev/fifoclient1");  
  8. QString temp(buf);  
  9. if(fd_file.open(IO_WriteOnly|IO_Append)) {  
  10. QTextStream t(&fd_file);  
  11. t<< temp;  
  12. fd_file.close();  
  13. }  
  14. else if(buf[0] == '1')  
  15. {  
  16. QFile fd_file("/dev/fifoclient2");  
  17. QString temp(buf);  
  18. if(fd_file.open(IO_WriteOnly|IO_Append)) {  
  19. QTextStream t(&fd_file);  
  20. t<< temp;  
  21. fd_file.close();  
  22. }  
  23. …… 

在该程序中,服务器接收底层发来的信息(这里假设也是由FIFO 管道传来),然后根据收到的信息内容,如***个字节的内容,将信息发到不同客户端的管道中,实现对信息的
正确分发。

客户端程序示例如下:(假设服务器端已经为读而打开/dev/fifo 管道)

  1. QFile out_file("/dev/fifo");  
  2. if(out_file.open(IO_WriteOnly|IO_Append)) {  
  3. QTextStream t(&out_file);  
  4. << text << "\n"; } 

小结:Linux 程序开发 QT内部进程通信的内容介绍完了,希望本篇文章能够帮助你有效学习,刚铎内容参考编辑推荐吧!

责任编辑:zhaolei 来源: 互联网
相关推荐

2011-06-22 16:50:09

Qt 进程 通信机制

2011-06-22 17:09:50

QT 进程 通信

2011-06-28 13:38:15

Arm linux QT

2011-06-24 14:01:34

Qt QCOP 协议

2010-01-05 10:00:48

Linux进程间通信

2021-07-06 21:30:06

Linux进程通信

2011-06-29 14:42:06

Qt 串口

2011-06-29 14:23:08

Qt 串口

2011-06-29 14:32:25

Qt 串口

2011-06-29 14:06:15

Qt 串口

2011-06-29 13:50:15

Qt 串口

2009-12-24 14:47:42

Linux系统进程

2017-06-19 13:36:12

Linux进程消息队列

2018-01-12 14:35:00

Linux进程共享内存

2021-09-30 10:45:33

Linux进程通信

2011-06-15 18:38:17

Linux Qt Symbian

2011-06-22 17:49:35

Linux Qt 串口

2018-05-30 13:58:02

Linux进程通信

2019-05-08 11:10:05

Linux进程语言

2011-08-08 10:02:55

iPhone开发 进程 通信
点赞
收藏

51CTO技术栈公众号