其实整个glusterfs的初始化过程就是这4个进程(gluster、glusterd、glusterfs和glusterfsd)的初始化过程,下面就详细说明下这4个进程的初始化过程。
整个glusterfs的代码目录结构截图如下:
图3:
一、gluster进程的初始化过程:
gluster作为一个cli命令执行工具,初始化代码位于glusterfs/cli/Src/cli.c的main函数里面,具体初始化过程为:
①Cli开始:全局变量的初始化包括glusterfs_ctx, global_xlator, gf_mem_acct_enable等
②命令行参数解析:解析命令行参数并存到state里,这里主要包括参数的格式和合法性进行判断
③Rpc初始化:这里主要初始化rpc通信环境,注册epoll读写事件和相应的处理函数。值得注意的是这里也注册了rpc请求通知函数(在glusterd中会调用),具体的rpc通信协议有不了解的自行脑补吧!
④注册命令:这里会将所有的命令和其对应的回调函数迚行注册,这里主要分为4类注册命令:cli_cmd_volume_register、cli_cmd_probe_register、cli_cmd_system_register和cli_cmd_misc_register其格式如下(跟进入gluster后我们输入的命令完全一样):
⑤接收命令并执行(即我们输入命令后的处理过程):
a)如果存在有效的命令行参数,则创建新线程进行处理。
b)如果没有命令行参数,则等待用户交互式输入命令。用户输入命令后,则对命令迚行解析,若无误,则创建新线程进行处理。
c)在新线程中根据解析的命令查询并调用相应的回调函数,如上面命令的回调函数为:cli_cmd_colume_add_brick_cbk;
处理完成后整个gluster进程即 初始化完成,也能够开始接收命令进行处理了;
整个代码如下:
图4:
二、glusterd的初始化过程:
Glusterd的主要负责管理daemon进程和处理gluster 发送过来的请求,其初始化代码应该是在(笔者自己理解的,不确定对否):glusterfs/glusterfsd/src/Glusterfsd.c的main函数,具体初始化过程为:
①glusterfs_globals_init()//初始化全局变量
②glusterfs_ctx_defaults_init(ctx)//初始化ctx缺省参数
③parse_cmdline(argc, argv, ctx)//解析命令行参数
④logging_init(ctx)//初始化日志
⑤create_fuse_mount(ctx)//这里不处理,直接返回
⑥daemonize(ctx)//根据是否debug等参数,确定进入前台或后台运行模式
⑦glusterfs_volumes_init(ctx)//负责创建监听端口,与监听端口建立连接,或通过RPC从daemon上获取卷配置信息等工作
⑧event_dispatch(ctx->event_pool)//监听事件池中注册的句柄,并调用事件池中注册的函数处理(通过rpc协议获得对应的请求,来触发对应的事件)!这样,整个glusterd的初始化完成。
图5:
三、glusterfsd的初始化过程:
Glusterfsd作为服务进程,主要根据卷配置信息执行从glusterfs发送过来的请求,同时也负责glusterd的请求处理;其初始化代码跟glusterd的初始化代码在一个位置,即:glusterfs/glusterfsd/src/Glusterfsd.c的main函数,具体初始化过程为:
①glusterfs_globals_init()//初始化全局变量;
②glusterfs_ctx_defaults_init(ctx)//初始化ctx缺省参数;
③parse_cmdline(argc, argv, ctx)//解析命令行参数;
④logging_init(ctx)//初始化日志;
⑤create_fuse_mount(ctx)//这里不处理,直接返回;
⑥daemonize(ctx)//根据是否debug等参数,确定进入前台或后台运行模式;
⑦glusterfs_volumes_init(ctx)//创建brick监听端口,同daemon建立连接获取相关brick配置信息;
⑧event_dispatch(ctx->event_pool)//调用创建socket时候注册的事件处理函数处理事件,这里的事件包括glusterd进程发过来的事件和glusterfs进程发过来的事件,具体见后面的业务处理流程!
这样,整个glusterfsd的初始化完成,整个初始化代码如图5。
四、glusterfs的初始化过程:
Glusterfs作为客户端的进程,根据卷配置信息将fuse发过来的操作请求逐层传递到最底层的protocol/client的xlator上,该xlator通过rpc与glusterfs连接,将请求发送到glusterfsd服务器执行;其初始化代码跟glusterd的初始化代码在一个位置,即:glusterfs/glusterfsd/src/Glusterfsd.c的main函数,具体初始化过程为:
①glusterfs_globals_init()//初始化全局变量;
②glusterfs_ctx_defaults_init(ctx)//初始化ctx缺省参数;
③parse_cmdline(argc, argv, ctx)//解析命令行参数;
④logging_init(ctx)//初始化日志;
⑤create_fuse_mount(ctx)//该根据mount 时候的参数,判断是否有mount point,如果有创建一个translator结构体,并初始化。
⑥daemonize(ctx)//这里不处理,直接返回;
⑦glusterfs_volumes_init(ctx)//利用rpc的sokcet库与glusterfs的damon建立连接,获取卷信息文件,初始化client端的translator 并初始化,注册事件处理函数。
⑧event_dispatch(ctx->event_pool)//监听注册事件处理函数的文件句柄。进入监听socket 过程,首先监听socket 建立连接事件,启动fuse 的while 循环进入客户端工作流程。
这样,整个glusterfs的初始化完成,整个初始化代码如图5。
这里重点说明下translator 的初始化过程:
根据配置文件创建树,创建一个xlator后即进行初始化工作,主要是调用每个xlator的init函数(初始化的一个很重要工作就是根据xlator_fops来对事件进行注册,方便后面进行处理)。再来看看整个fops的结构体,下面是以afr模块来进行举例说明的:
struct xlator_fops fops = {
.lookup = afr_lookup, 查询指定的目录(这里是将请求发向所有的节点)
.open = afr_open, 以指定方式打开文件
.lk = afr_lk,
.flush = afr_flush, 将文件从内存写到磁盘
.statfs = afr_statfs, 搜集磁盘的容量状态
.fsync = afr_fsync,
.fsyncdir = afr_fsyncdir,
.xattrop = afr_xattrop,
.fxattrop = afr_fxattrop,
.inodelk = afr_inodelk,
.finodelk = afr_finodelk,
.entrylk = afr_entrylk,
.fentrylk = afr_fentrylk,
/* inode read */
.access = afr_access, 检查调用进程是否可以对指定的文件执行某种操作
.stat = afr_stat, 通过文件名获取文件的信息
.fstat = afr_fstat, 以fd的方式来获取文件的信息
.readlink = afr_readlink,读取链接文件
.getxattr = afr_getxattr, 以路径参数得到对应文件扩展属性
.fgetxattr = afr_fgetxattr,以fs作为参数得到对应文件扩展属性
.readv = afr_readv, 读取对应文件内容
/* inode write */
.writev = afr_writev, 写文件
.truncate = afr_truncate, 以路径参数改变和修辞文件的大小
.ftruncate = afr_ftruncate,以fd参数改变和修辞文件的大小
.setxattr = afr_setxattr, 以路径参数设置文件的扩展属性
.fsetxattr = afr_fsetxattr,以fd参数设置文件的扩展属性
.setattr = afr_setattr, 以路径参数设置文件的属性
.fsetattr = afr_fsetattr, 以fd参数设置文件的属性
.removexattr = afr_removexattr,以路径参数删除文件的扩展属性
.fremovexattr = afr_fremovexattr,以fd参数删除文件的扩展属性
/* dir read */
.opendir = afr_opendir,打开目录
.readdir = afr_readdir,读取目录
.readdirp = afr_readdirp,读取目录
/* dir write */
.create = afr_create,以指定的格式创建文件
.mknod = afr_mknod, 创建文件,主要是fifo文件
.mkdir = afr_mkdir, 创建目录
.unlink = afr_unlink, 删除目录项,并且减少一个链接数
.rmdir = afr_rmdir, 删除目录
.link = afr_link, 创建硬链接
.symlink = afr_symlink, 创建软链接
.rename = afr_rename, 重命名文件
};
整个fops即我们后面要处理的对应事件的函数(包括对应的cbk回调函数),xlator的初始化即主要通过fops来对事件进行注册,方便后面进行处理。
Ok,整个初始化工作基本上完成,初始化完成后,整个树的结构以及对应的注册函数都已经形成,后面就开始进入到事件处理过程。
转自:http://blog.csdn.net/york_1986/article/details/38864789