内存管理。
XDL实现了四种内存管理方式的函数集,即:堆内存、页内存、全局内存和缓存。堆内存(xmem)为程序在运行时提供了按需使用和释放内存的机制,但从何种堆里分配内存,取决于XDL的启动标志,如果是线程寓所模式(XDL_THREAD_APARTMENT),所需内存从线程私有堆里分配,如果是进程寓所模式(XDL_PROCESS_APARTMENT),则从进程默认堆里分配。页内存(pmen)是一种以页面大小(4096字节)作为最小分配和释放单位的内存管理机制,页内存可以单页、也可以连续页的方式分配,页可以被锁定常驻于物理内存,但这样会占用宝贵的内存资源,所以锁定操作务必慎重,根据应用一些特殊性需要,可以对页进行只读保护。全局内存(gmem)主要用于进程之间共享数据而实现的内存管理机制,常用于剪切板操作。缓存(vmem)为用户提供了一个逻辑连续的虚拟线性地址空间,然后采用内存映射(MapView)的方式来读写数据,32位和64位操作系统,vmem线性空间大小分别为2G和4G。
线程和子进程。
XDL提供了两种独立的执行单元,即:子进程和线程。传统的线程没有独立的堆内存空间,但如果XDL的启动方式为线程寓所模式(XDL_THREAD_APARTMENT),则线程也拥有独立的堆内存空间,可以通过堆内存(xmem)函数来申请、释放。
子进程(process)的创建需依赖于一个可执行文件,子进程被创建后即独立运行。XDL为父进程和子进程的通信提供了三种途径,一是通过命令参数(command line)方式传入,二是父子进程建立双工的管道(SHARE_PIPE)或套接字(SHARE_SOCK)进行通信,三是通过跨进程分配内存空间(process_alloc)来传递数据。子进程通常也需要从运行环境中获取一些用户配置信息,XDL提供了profile的读写函数,profile通常为独立的配置文件或系统注册表存储。
线程(xthread)通常以一个工作函数(PF_THREAD_FUNC)为其执行体,线程被创建后即执行。父进程在创建线程时可以通过为工作函数传入一个参数作为通信的基础,在线程执行过程中,双方可以通过共同维护信号量或互斥体来编排执行秩序。线程也可以通过join方法加入父进程的维护队列,父进程将等待队列中所有线程结束后才终止。
原语对象。
系统的原语对象主要用于竞争性资源的排它性控制,线程执行顺序编排和异步操作调度,XDL提供的原语对象有:临界区、互斥锁、事件、信号灯、异步队列、定时器。
临界区(xcrit)用于线程级的代码排它性执行控制,获准进入临界区的代码被执行,未获准进入的代码将等待。
互斥锁(xmutex)用于进程级的排他行执行控制,获得互斥锁的进程被执行,其他进程将等待。
事件(xevent)维护着一个触发态和非触发态的状态量,事件的状态可以按需重置,主要用于编排多个线程的执行顺序,或者用于线程向父进程报告执行状态。
信号灯(xsemap)用于进程级的有限资源使用控制,信号灯使用一个信号量表示资源可用数,对信号量的P操作(信号量减1)表示申请资源,V操作(信号量加1)表示释放资源。P操作成功的进程予以执行,否则将等待。
异步队列(xqueue)主要用于将一个IO资源句柄投放到系统异步IO队列中,当该句柄相关的IO读写操作可用时,异步队列返回该句柄,读写线程从等待状态中恢复执行。
定时器(xtimer)的使用首先需要创建一个定时队列,队列可以拥有一个或多个定时器,定时器可以设定间隔时间和重复周期,并由用户定义的定时回调函数(PF_TIMERFUCN)来指派功能,每次被执行的工作函数均运行于独立线程。
输入输出(IO)对象。
控制台(Console)、管道(Pipe)、通信端口(COM)、共享内存(Share),文件(File)都属于操作系统平台的输入输出资源。
控制台(xcons)是系统特殊的输入输出对象,它以STDIN为输入系统资源句柄,STDOUT为输出系统资源句柄。一个进程通常只能拥有一个控制台,XDL除了支持控制台的读写操作外,还可以为控制台安装信号中断处理例程,如Ctrl+C中断信号、控制台退出信号等。
管道(xpipe)是进程之间通信的常用机制,通常数据在管道的一端写入,而后在另一端读出。XDL提供了命名管道的实现,采用Client/Server的方式交互,首先需要创建一个命名管道服务方(pipe_srv),然后可以创建多个管道客户方(pipe_cli)等待管道服务可用,连接后进行一对一读写。
通信端口(xcomm)用于和符合RS-232/RS-485通讯规程的仪器进行数据交换。XDL支持两种读写通信端口的方式,一是事件驱动方式,即监听通信端口事件,根据事件类型采取相应的读写动作。二是通过文件流的方式进行直接读写。
共享内存(xshare)也是进程之间共享数据比较高效的一种方式,XDL提供了命名共享内存的实现,也是采用Client/Server的方式交互,当一个命名共享内存服务方(share_srv)创建后,可以被多个客户端(share_cli)读写,独占性写入共享内存操作由同名互斥锁控制。
文件(xfile)是磁盘数据的组织形式,XDL为本地文件、网络路径文件、http文件、tftp文件、oss文件定义了统一的读写形式,提供了同步和异步两种读写机制,除了支持常规的顺序读写外,还支持区块随机读写。
套接字(socket)。
套接字是系统进行网络通讯的基本IO输入输出对象,套接字有三种类型,即流套接字(socket-stream),数据报套接字(socket-dgram)和原始套接字(socket-raw)。
XDL中可以创建和操作tcp、udp、icmp三种套接字,其中tcp套接字面向连接,并按网络编程模型分为三种功能套接字:侦听套接字、服务套接字和客户套接字。客户套接字负责和服务主机侦听建立连接,而后为客户端应用收发网络数据。侦听套接字负责监听通讯端口,等待客户套接字连接申请,并负责创建服务套接字。服务套接字用于服务端应用和客户套接字进行数据交互。XDL还提供了进程间传递套接字的方法,这样使得服务主机负责调度响应的进程和数据服务进程相互分离。
XDL中的套接字读写可以是阻塞方式,也可以为异步方式,两种读写方式均支持基于事件(EVENT)或IO队列(QUEUE)的调度模式。
Shell。
Shell也是一种操作系统资源,我们称之为系统管理壳。在shell中可以调用操作系统提供的命令,也可以完成一些批量操作。XDL实现了一些shell操作函数,为应用程序管理系统资源(文件、文件夹、快捷方式等)提供了便捷。
剪切板(Clipboard)。
剪切板也是应用之间传递数据的一种方式,XDL使用全局内存来设置、获取剪切板数据,支持多字节字符、双字节字符和位图数据格式。XDL中的文档体和子部件均支持基于剪切板的复制、剪切和粘贴操作。
设备场景(Context)与画布(Canvas)。
操作图形资源,必须先创建设备场景,XDL支持三种设备场景:内存缓存场景、显示设备场景、打印设备场景,XDL通常在内存缓存场景中完成绘制,然后递交至显示设备或打印设备场景,以上设备场景均采用点阵坐标。
画布基于设备场景创建,但采用毫米制坐标。XDL支持两种类型画布,图形图像输出画布和SVG文档输出画布。图形图像画布附着于缓存、显示设备和打印设备场景,并通过画布图形函数实现点阵输出。SVG画布附着于SVG文档,也是通过画布图形函数输出为SVG文档。
图形资源(GDI)。
图形资源是操作系统提供文本输出和图形绘制方法库,随着操作系统的发展,图形库的功能也愈来愈强大,但每个系统版本阶段存在图形库不同的情况,XDL会根据运行环境来动态装载合适的图形库。
图形资源操作主要为文本输出、2D和3D图形绘制、图像输出的能力,现有的输出设备都为点阵设备,现实生活中我们所理解的尺寸均以米制坐标系为基础,XDL为点阵坐标系和米制坐标系提供了映射和转换机制,即“所见即所得”。
XDL图形库分别为设备场景(Context)和画布(Canvas)提供了绘制函数集,面向设备场景以象数点阵坐标操作函数集为主,而面向画布则实现了毫米制坐标操作函数集。
窗体资源(Window)。
窗体资源是图形操作系统的基础资源,通常以窗体的形式提供,与用户的交互方式一般为键盘、鼠标等输入设备,并通过窗体消息循环,来响应用户的操作。使用系统的窗体资源,必须理解以下一些概念。
坐标系(Coordinate)。图形系统有三种固有的坐标,即设备坐标、窗体坐标和客户坐标。设备坐标是用于描述设备的显示区域,并用于编排桌面和桌面中的各种应用程序的窗体。窗体坐标用于描述窗体的显示区域,并用于布局窗体标题、边框以及窗体操作按钮。客户坐标用于描述用户视图的显示区域,也用于编排属于该窗体的各种子窗体。除了支持以上三种坐标系,XDL还提供了画布坐标系,它采用毫米制坐标,并于窗体客户坐标系建立一一映射和转换关系。
焦点(Focus)。焦点是窗体与用户操作的连接点,用于响应用户的输入(通常是键盘等输入设备),窗体可以获得焦点,也可以失去焦点。由于XDL采用动态编辑件技术,响应用户输入必须激活编辑件并赋予其焦点。
快捷键(Accelerator)。快捷键是建立一个键盘按键与命令标识的映射表资源,并附加于目标窗体,在用户输入过程中,优先将按键转换为一个命令消息。
菜单(Menu)。菜单也是窗体的附加资源,不过XDL的菜单方式与传统菜单资源有所不同,它需要先创建一个菜单文档(MenuDoc),在附加于窗体后被编排为窗体菜单栏。
滚动栏(ScrollBar)。当用户视图的宽度或高度超过窗体客户区域时,需要滚动栏来支持将视图内容通过左右或上下滚动的方式掉整至窗体客户区域(可视区域)。由于XDL的视图可以以分页方式显示,所以在滚动栏增加了对页面滚动的支持。
消息派发器(MessageDispatch)。窗体采用消息循环机制来响应用户的操作,因此在创建XDL窗体时,需要安装消息派发器(if_event_t),它是一个窗体事件回调函数集。
子类化(Subclass)。XDL可以通过子类化结构(if_subproc_t)来向窗体安装子类化操作,子类操作也是消息回调函数,但它在消息循环中,总是优先被执行。