学习Wayland协议已经好几个月了,期间也查阅了不少资料,奈何目前对于它的资料并不是很多,对他原理以及解析更是寥寥无几,其中有一篇非常不错,给个链接: https://blog.csdn.net/jinzhuojun/article/details/40264449, 需要的可以去查看查看.本文的目的是更加通俗详细的解释wayland协议.好了,废话不多说,下面开始讲述wayland协议.

什么是wayland

关于什么是wayland网上有很多解释,我这里就不在赘述,而是以我自己的理解来浅显易懂的给大家解释一下.

Wayland协议,是一个定义怎么来进行窗口管理的协议. 什么叫窗口管理呢? 我们知道在windows操作系统上有很多很多的应用程序,在启动该应用程序之后,一般会弹出一个该应用程序的窗口.这个窗口是怎么产生的? 太深入理解没必要,我们只需要知道,我们在创建窗口的时候都是必须调用指定的接口才可以创建,是吧? 这个接口就相当于窗口管理的协议提供的接口. 各种形形色色的接口在不同的操作系统上是不一样的,因此如果我们要创建窗口,在不同的操作系统上就需要不同的代码,因此,跨平台就是件很麻烦的事情. 然而,在这种情况下,涌现出了大量跨平台的框架,他们把和操作系统相关的创建窗口的接口封装了起来,然后通过提供统一的接口给用户,这样,用户就可以使用相同的代码在不同的操作系统上创建出窗口, 比如Qt, 因为作者本身也是在使用Qt的,因此,此处只列出Qt.

上面说了,窗口在不同操作系统上调用不同的接口去创建窗口,其实是不准确的,因为,其实窗口管理理论上是和操作系统不强绑定的关系.只是有些操作系统把窗口管理给绑定到内核了,比如windows(这里我也是看资料了解的,至于正确性,我不做保证,但是现象还是很明确的).但是也有明确的例子证明,窗口管理和操作系统是不绑定的,比如高版本的ubuntu(18.04),该系统提供了两种窗口管理的方式,一种就是本文的wayland,另一种是原有的x11,但由于支持wayland协议的软件比较少,现在还比较难以流行起来。

为什么需要窗口管理呢? 我们都知道,那个窗口什么的都是通过显示器显示给我们看的,然后通过鼠标键盘等外设来操作的,但这些东西都只有一份(当然,你有多个显示器多个鼠标键盘什么的,也是可以的,但是总不能同时操作吧,显示屏多个的问题自己想想怎么反驳吧),如果现在有两个进程都需要显示出来,他们都去争夺这个显示屏去绘制,最终出来的不就花屏了?因为这两个进程是不知道对方的存在,不知道对方现在占用了哪里,因此,需要一个东西来协调才能让多个进程完美的同时显示出来,这个就是窗口管理的作用。

说实话,就上面讲的这些东西,都是在我理解wayland是什么之后才彻底明白的,因此,也希望读者能够通过本文对wayland有所了解,并且开始理解窗口管理的本质。

好了,开始说说wayland。

上面我说了wayland是一种窗口管理的协议,它和x11协议是同等的。那么,是什么样的协议呢?看下面

<interface name="wl_buffer" version="1">

<description summary="content for a wl_surface">

A buffer provides the content for a wl_surface. Buffers are

created through factory interfaces such as wl_drm, wl_shm or

similar. It has a width and a height and can be attached to a

wl_surface, but the mechanism by which a client provides and

updates the contents is defined by the buffer factory interface.

</description>

<request name="destroy" type="destructor">

<description summary="destroy a buffer">

Destroy a buffer. If and how you need to release the backing

storage is defined by the buffer factory interface.

For possible side-effects to a surface, see wl_surface.attach.

</description>

</request>

<event name="release">

<description summary="compositor releases buffer">

Sent when this wl_buffer is no longer used by the compositor.

The client is now free to reuse or destroy this buffer and its

backing storage.

If a client receives a release event before the frame callback

requested in the same wl_surface.commit that attaches this

wl_buffer to a surface, then the client is immediately free to

reuse the buffer and its backing storage, and does not need a

second buffer for the next surface content update. Typically

this is possible, when the compositor maintains a copy of the

wl_surface contents, e.g. as a GL texture. This is an important

optimization for GL(ES) compositors with wl_shm clients.

</description>

</event>

</interface>

上面的片段是从wayland.xml里面截取出来的,以此来介绍. Wayland的核心协议全部在wayland.xml这个xml文件里面.也有很多wayland的扩展协议,是为了实现一些其他目的而添加,当然,读者如果学了该协议也可以自己添加一些协议内容. 为了实现一些功能,这个是非常有必要的

解析上面的xml可以分为以下标签:

  1. Interface (接口类)
  2. Description (描述, 可能是接口的描述,请求的描述,事件的描述等)
  3. Request (请求,客户端主动调用的接口, 实际就是个函数)
  4. Event (事件,服务器端主动调用的接口, 实际就是个函数)

如果,总结整个wayland.xml协议文件还有以下标签:

  1. Arg (参数, 请求或者事件的参数)
  2. Enum (枚举, 用来更形象的代表一些值)
  3. Entry (枚举的成员)

这些是什么东西? 如果第一次接触肯定不知道是什么了,是吧! 我这里就给大家解释一下.

Wayland协议就是通过这样一个文件描述一个客户端和服务器端相互知道的调用接口. 转换成C++的方式来理解这些你们肯定会很容易的.

首先,这些标签是有包含关系的, 一个wayland协议xml文件里包含一个或多个interface, 一个interface里面可能包含一个或多个request和event, 有些可能包含enum,也可能没有,根据实际情况.

其中最简单的enum最终就是直接转换成C语言的枚举类型,Entry即是它的成员。

现在结合上面的定义来解释: wayland.xml协议文件里面定义一个类wl_buffer,该类是干什么的,可以通过description标签的描述知道.然后,该类有两个成员函数,一个是request(destroy),还有一个event(release), 这两个函数又有个description标签的描述该函数是用来干什么的. 但是截取的这个片段两个成员函数都没有参数,所以没有arg标签. 但是我们知道,一个函数定义的组成一般都有参数, 这个arg标签就是用来描述参数的,所以有些request和event包含arg标签, 用来描述他的参数. 然后我们知道,一个参数我们肯定得知道参数的名字,类型, 因此arg标签有一些属性是用来表示这些的,看下面:

<request name="attach">

<arg name="buffer" type="object" interface="wl_buffer" allow-null="true" summary="buffer of surface contents"/>

<arg name="x" type="int" summary="surface-local x coordinate"/>

<arg name="y" type="int" summary="surface-local y coordinate"/>

</request>

一个参数可能有5个属性:

  1. Name (参数的名字)
  2. Type (参数的类型)
  3. Interface (参数的类型)
  4. Allow-null (是否可以为空)
  5. Summary (描述参数是做什么的)

一个参数有几个要素, 名字和类型, 然后也可能是一个类的指针(interface就是描述是指针类型)

通过上面的解释来分析buffer这个参数:

buffer 是一个wl_buffer类型的指针参数,名字是buffer,并且这个指针可以为空, 对这个指针参数的描述是” buffer of surface contents”.

X是一个int类型的参数,名字是x, 对这个参数的描述是” surface-local x coordinate”

Y是一个int类型的参数,名字是y, 对这个参数的描述是” surface-local y coordinate”

最后把上面的函数翻译成: attach(wl_buffer *buffer, int x, int y), 这样看好像有点问题,有没有?有没有?有没有?哈哈哈,确实是。一个函数必须有返回值,但是wayland协议里面没有描述返回值的,因此,大部分函数的返回值都是void,这里说了,只是大部分,还有小部分怎么描述呢?这个就是有一种arg类型是new_id的会作为函数的返回值类型。因此上面的函数最终会转换成:

void wl_surface_attach(struct wl_surface *wl_surface, struct wl_buffer *buffer, int32_t x, int32_t y)

然后,是不是感觉又不对? 咋多了个参数?

是这样的,wayland协议在翻译协议文件的时候,会给所有的函数添加一个默认的参数,就是它所在的interface,作为第一个参数传入进去,就相当于给一个类成员函数传递this指针一样。告诉是哪个具体对象调用的这个接口。

好了,到这里该总结性的介绍下wayland的参数类型到底有哪些,不然你肯定不能自己翻译出来的。首先,我必须说明一点,wayland是由C语言实现的,因此,最终协议文件肯定是翻译成c语言的语法。只是,这个协议其实理解成C++面向对象更通俗易懂。如果你会面向对象语言。反正我是,嘿嘿。好了,看下面:

union wl_argument {

int32_t i;           /**< `int`    */

uint32_t u;         /**< `uint`   */

wl_fixed_t f;        /**< `fixed`  */

const char *s;       /**< `string` */

struct wl_object *o;  /**< `object` */

uint32_t n;         /**< `new_id` */

struct wl_array *a;   /**< `array`  */

int32_t h;          /**< `fd`     */

};

上面这个结构体是从wayland源码里面截取出来的,由此可以看出来,wayland协议里面的参数类型有以上几种。

  1. 其中int、uint比较简单,就直接转换成32位的有符号整数和无符号整数。
  2. Fixed类型就相当于是一个double和int的兼容类型,wayland有一段对它的解释:

/**

* Fixed-point number

*

* A `wl_fixed_t` is a 24.8 signed fixed-point number with a sign bit, 23 bits

* of integer precision and 8 bits of decimal precision. Consider `wl_fixed_t`

* as an opaque struct with methods that facilitate conversion to and from

* `double` and `int` types.

*/

然后实际定义为: typedef int32_t wl_fixed_t; ,并且wayland提供了几个对这种类型转换成int或者double的接口wl_fixed_to_double、wl_fixed_from_double、wl_fixed_to_int、wl_fixed_from_int。

  1. String类型很简单就是char *类型
  2. Object类型比较特殊,他表示是一种基类指针,可以接受保存所有interface的指针,因此,object类型的参数会多一个描述interface的属性,指明是哪一个interface,但是C语言哪里来的基类指针这回事?在C语言里,只有结构体,结构体的第一个成员可以看做是它的基类,不信你试试?
  3. new_id类型就更特殊了。前面我说了,这个类型是会作为函数的返回值的,但是说的不准确,这个类型的参数在客户端被解释的时候是返回值,被返回回来给调用者使用,但是在服务器端,这个参数被转换成uint32_t类型传递过来一个id,具体为什么这么做,我们后面再说。所以,这个也算是个参数。
  4. array类型,这个是wayland定义的一种数据结构,具体如下:

struct wl_array {

/** Array size */

size_t size;

/** Allocated space */

size_t alloc;

/** Array data */

void *data;

};

并且wayland提供了一系列对该数据结构操作的接口。

  1. fd类型,这个类型比较简单,就是表面这个参数是个文件描述符,为什么要特别指出呢?因为底层在传递这种参数的时候,和其他的方式不一样,具体可以参考linux 进程间文件描述符传递方法。另外需要强调,文件描述符在进程间传递之后,大多数情况下,是不一样的值。

好了,所有的wayland可传递的参数都说完了,你们能不能总结出来些什么?

是的,进程间传递基本类型还好,传递文件描述符有系统的支持也还好,但是传递一个独属于一个进程的指针,这不合理了吧???哈哈哈,确实是的,因此wayland协议底层根本不是传递的指针,而是传递的一个对象的id,就是说,wayland的所有的interface对象在客户端和服务器端都有个对应关系,通过一个id来查找对应的对象。因此,进程间传递的时候只需要传递这个id,对应进程就知道是哪个具体对象了。具体的原理后面再说。这个id就和new_id类型的参数类似。

Wayland有一个专门解析wayland协议文件的工具,源码是scanner.c, 就是把wayland协议文件的内容转换成C语言的源文件,分为以下:

注意: 其中有几个interface是wayland特殊处理的,规则和一般的有点不一样,被wayland特殊处理(wl_display、wl_registry)

因此,如果想更多的了解wayland协议,可以尝试阅读此源码. 另外,Qt也实现了一个解析wayland协议的工具, 但是Qtwayland把wayland协议解释为C++语法, 就像我之前列举那样interface就解释成了一个类. 更多的可以去查看Qtwayland的源码.

我大篇幅的介绍其实是在说明怎么去解析wayland协议,但是我前面说了,wayland协议是一个窗口管理的协议, 因此,协议内容才是最关键的. 协议内容里面给出了怎么创建窗口的标准接口,对窗口的操作的标准接口,以及一些输入(键盘鼠标)获取的标准接口.只有通过这些标准接口创建的窗口管理器,就满足wayland协议,即使客户端不知道服务器端的存在,也可以根据这些标准来实现.

到此,wayland的协议基本就描述完了。有什么不懂的,可以留言咨询。

Wayland协议解析 一 什么是Wayland相关推荐

  1. Wayland 协议的解析

    Wayland 首先是一种协议(Compositor 与客户端之间进行通信的协议),然后才是对协议的实现.所以第一步是协议的定义. 1. Wayland 协议的定义 Wayland 协议使用 XML ...

  2. Wayland协议了解

    一 什么是wayland Wayland协议,通俗的讲就是一个定义怎么来进行窗口管理的协议. 什么叫窗口管理呢? 我们知道在Windows操作系统上有很多很多的应用程序,在启动该应用程序之后,一般会弹 ...

  3. wayland与linux_将Linux与Wayland一起使用? 您需要知道的 | MOS86

    Linux桌面的各个方面一直在变化,但是某些组件已经存在了数十年. 以X窗口系统(主要称为X)为例. 正在努力创建一种更快,更安全的替代产品. 那个替代者是Wayland. 立即解锁"基本L ...

  4. synopsys PCIE IP协议解析

    synopsys PCIE IP协议解析 1.Overview Core支持单个Pcie内核的Loopback功能,该功能主要为了做芯片验证,以及在没有远程接收器件的情况下完成自己的回环.同时,Cor ...

  5. 详解BLE 空中包格式—兼BLE Link layer协议解析

    BLE有几种空中包格式?常见的PDU命令有哪些?PDU和MTU的区别是什么?DLE又是什么?BLE怎么实现重传的?BLE ACK机制原理是什么?希望这篇文章能帮你回答以上问题. 虽然BLE空中包(pa ...

  6. wireshark协议解析器 源码分析 封装调用

    源码分析 Wireshark启动时,所有解析器进行初始化和注册.要注册的信息包括协议名称.各个字段的信息.过滤用的关键字.要关联的下层协议与端口(handoff)等.在解析过程,每个解析器负责解析自己 ...

  7. wireshark协议解析器原理与插件编写

    工作原理 每个解析器解码自己的协议部分, 然后把封装协议的解码传递给后续协议. 因此它可能总是从一个Frame解析器开始, Frame解析器解析捕获文件自己的数据包细节(如:时间戳), 将数据交给一个 ...

  8. SGS 0.9.7 协议解析

    SGS as客户端发送数据规则: sgs 是0.9.7版 协议规则:  包头3个字节: 包大小(2个字节),命令(1个字节)  数据包  注意:包大小=命令+ 数据包 的大小 登陆命令:   命令是: ...

  9. 简易HTTP协议解析

    首先介绍一些必要的知识点. TCP协议为操作系统底层协议,能够保证应用层获取到完整的.顺序一直的包序列.但TCP不提供具体的分包,需要上层协议自己解决.TCP发送给上层协议的数据是一个没有意义的字符串 ...

最新文章

  1. 个人博客开发-01-nodeJs项目搭建
  2. 小学生学python到底能干什么-小学生都学Python了,你还没用万矿?
  3. Qt Creator开放项目
  4. 仿个人税务 app html5_【注意】你下载的可能是个假的个税App
  5. 关于Java中String的问题
  6. Hadoop! | 大数据百科 | 数据观 | 中国大数据产业观察_大数据门户
  7. 美将遣返庇护申请者至墨西哥 弱势人士有望豁免
  8. 中国诗歌艺术8诗的魅惑:中国诗歌的几个基本元素之不循常规的语序
  9. 如何删除C++容器中的值
  10. 任何性能指标越界或造成 APP 崩溃,优酷通用性能测试一招搞定
  11. 力扣-989 数组形式的整数加法
  12. java 方法注释_Java注释,java方法注释详解
  13. 计算机logo设计图片简单,一个简单的字体LOGO设计流程:你看简单吗?
  14. 树莓派 与 Xbox360手柄 基于pygame 的一次邂逅
  15. Swift 类和结构体总结
  16. MT8735芯片技术资料解析,MT8735处理器简介
  17. shell脚本——sql连接及其查询结果重定向到txt
  18. Android 异步进程
  19. 团队管理之团队气氛篇
  20. 错误检测的奇偶校验方法

热门文章

  1. 02.微软官方启动U盘装机教程
  2. matlab设置列宽,matlab和Excel的交互-(2-单元格操作)
  3. kermit的安装、配置、使用 .
  4. 蓝牙模块的配置(HC05):修改密码、修改模块名字、修改波特率。
  5. linux gitlab安装教程,linux安装gitlab(官方)
  6. NTC电阻在电源输入端的应用-测试案例
  7. STM32F10xxx20xxx21xxxL1xxxx Cortex-M3程序设计手册 阅读笔记二(5):Cortex-M3处理器能量管理
  8. 怎么写一份好的接口文档?
  9. 【matlab图像处理】直方图均衡化操作
  10. 腾讯云windos服务器如何迁移?