Skip to main content

5. 数据结构—结构(struct)

一、概述 Libuv 和其他 C 项目一样,大量使用结构,本文主要关注结构的声明方式、结构的” 继承” 和结构的分类。

一、概述

Libuv 和其他 C 项目一样,大量使用结构,本文主要关注结构的声明方式、结构的” 继承” 和结构的分类。 如果在分析具体的结构时遇到宏,可以先预处理展开宏,如:

gcc -E src/uv-common.c -o src/uv-common.i -Iinclude -Isrc -Isrc/unix

二、结构的分类

从功能上看,Libuv 的结构主要分为这几类: Loop :事件循环 (event loop)。本质上是个特殊的 Handle 。 Handles : 句柄。表示在其被激活时可以执行某些操作且持久存在的对象。 Requests : 请求。(通常) 表示一个短暂存在的操作。 Other : 如: uv_buf_suv_stat_suv_cpu_info_suv_interface_address_suv_dirent_suv_passwd_s 等出于数据封装和跨平台的目的而定义的结构。

三、Handles 和 Requests 的结构 “继承”

主要是结构字段的 “继承”,父结构(“类”) 定义基本字段,子结构在父结构尾部添加字段。在声明结构的过程中使用宏。以 uv_handle_su_stream_suv_tcp_s 为例:

struct uv_handle_s {
UV_HANDLE_FIELDS
};


struct uv_stream_s {
UV_HANDLE_FIELDS
UV_STREAM_FIELDS
};

struct uv_tcp_s {
UV_HANDLE_FIELDS
UV_STREAM_FIELDS
UV_TCP_PRIVATE_FIELDS
};

四、Handles 和 Requests 的继承关系图

Handles 的继承关系图 Requests 的继承关系图

五、结构及结构字段的命名方式

首先,以 struct uv__ (两个下划线) 开头的,是 Libuv 内部使用的结构 (当然,用户代码也可以使用暴露出来的结构。);以 struct uv_ (一个下划线) 开头的,是公开的、可供外部使用的结构。 在声明结构时,用了不少的宏,以达到抹平不同操作系统之间的差异,“实现” 结构的” 封装” 和” 继承”,方便维护、减少出错几率和减少代码量的目的。大部分是以 _FIELDS 结尾的。

UV_PLATFORM_*_FILEDS : 平台相关的结构字段。体现 UNIX 实现之间的差异。有两个:UV_PLATFORM_LOOP_FIELDSUV_PLATFORM_FS_EVENT_FIELDS 。特别地,有一个接近此命名方式的 UV_PLATFORM_SEM_T 宏是为了抹平 Darwin 和其他 UNIX 实现之间, 信号量 (semaphore) 数据类型的差异。

注:UV_PLATFORM_*_FIELDS 类似于面向对象语言中子类的定义的 override public 字段。

UV_*_PRIVATE_PLATFORM_FIELDS : 平台相关的、Handles 和 Requests 的结构” 私有” 字段。有三个:UV_LOOP_PRIVATE_PLATFORM_FIELDSUV_STREAM_PRIVATE_PLATFORM_FIELDSUV_IO_PRIVATE_PLATFORM_FIELDSUV_LOOP_PRIVATE_PLATFORM_FIELDS 目前是空实现;UV_STREAM_PRIVATE_PLATFORM_FIELDS 是为了抹平 Darwin 和其他 UNIX 实现之间的差异;UV_IO_PRIVATE_PLATFORM_FIELDS 是为了抹平 Darwin 、BSD 和 其他 UNIX 三者之间的差异。

注:UV_PLATFORM_*_FIELDS 类似于面向对象语言中子类的 private 字段。

UV_*_FIELDS: 平台无关的、Handles 和 Requests 的结构字段。是为了 “实现” 结构的”继承”。 UV_*_PRIVATE_FIELDS : 平台无关的、Handles 和 Requests 的结构” 私有” 字段。

参考资料