1 glib 事件循环概述
glib
是一个跨平台、用 C 语言编写的若干底层库的集合。编写案例最好能够结合 glib 源码,方便随时查看相关函数定义。glib
实现了完整的事件循环分发机制。有一个主循环负责处理各种事件。事件通过事件源描述,常见的事件源
- 文件描述符(文件、管道和 socket)
- 超时
- idle 事件
当然,也可以自定义事件源,通过 glib 提供的函数 g_source_attach() 就可以手动添加我们自定义的新类型事件源。可参考 [2.2](##2.2 案例2 glib 自定义事件源)
事件源默认会被分配一个优先级,默认为 G_PRIORITY_DEFAULT(200),数字越小,优先级越高。当然也可以在添加空闲函数(g_idle_add_full)的时候,指定该事件源的优先级。具体应用还是结合后面的示例以及源码动手实践。
1.1 glib 主事件循环涉及的重要数据结构
GMainContext
为了让多组独立事件源能够在不同的线程中被处理,每个事件源都会关联一个GMainContext
。一个线程只能运行一个GMainContext
,但是在其他线程中能够对事件源进行添加和删除操作。GMainContext
定义如下
/**
* GMainContext:
*
* The `GMainContext` struct is an opaque data
* type representing a set of sources to be handled in a main loop.
*/
typedef struct _GMainContext GMainContext;
GMainLoop
GMainLoop
数据类型代表了一个主事件循环。通过g_main_loop_new()来创建GMainLoop对象。在添加完初始事件源后执行g_main_loop_run(),主循环将持续不断的检查每个事件源产生的新事件,然后分发它们,直到处理来自某个事件源的事件的时候触发了g_main_loop_quit()调用退出主循环为止。
struct _GMainLoop
{
GMainContext *context;
gboolean is_running; /* (atomic) */
gint ref_count; /* (atomic) */
};
其实很多博客只是介绍了上述内容,如果你对glib
本身就不熟悉,还是很难明白其中的道理。因此一定要结合源码,以及动手调试,才能够更好的理解glib
事件循环。所以,动手试试笔者第二节改写的三个案例吧。
1.2 glib / glibc /libc 傻傻分不清楚
glibc
和libc
都是Linux
下的 C 函数库
libc 是 Linux 下的 ANSI C 函数库
glibc 是 Linux 下的 GUN C 函数库
glib 是 GTK+ 的基础库,一个综合用途的实用的轻量级的C程序库,与 glibc 没有实际联系
ANSI C 函数库是基本的 C 语言函数库,包含了 C 语言最基本的库函数。GNU C 函数库是一种类似于第三方插件的东西。由于 Linux 是用 C 语言写的,所以 Linux 的一些操作是用 C 语言实现的,因此,GUN 组织开发了一个 C 语言的库 以便让我们更好的利用 C 语言开发基于 Linux 操作系统的程序。
如今,glibc是 linux 下面 c 标准库的实现,即 GNU C Library,所以,我们在 Linux 用户态编程中最常用的库,libc.so,其实就是 glibc。
可能有人会认为,glib 前面有个 “g” ,所以认为 glib 是 GNU 的东西;同时认为 glibc 是 glib 的一个子集。 其实,glib 和 glibc 基本上没有太大联系,可能唯一的共同点就是,其都是 C 编程需要调用的库而已。
glib是GTK+的基础库,它由基础