CIFS Server处理流程解析

Samba Server端,存在一个smbd守护进程接收Client端的连接和请求,每建立一个连接,会fork一个子进程。因此,本文主要描述smbd进程的启动以及SMB请求处理过程中函数调用关系。

1、概述
SMB(Server Message Block)通信协议是微软和英特尔在1987年制定的协议,主要是作为Microsoft网络的通讯协议。SMB 是在会话层(session layer)和表示层(presentation layer)以及小部分应用层(application layer)的协议。SMB使用了NetBIOS的应用程序接口 ,一般端口使用为139,445。
2、基本流程
Samba Server的总体架构如下图所示。
在这里插入图片描述
如上图所示,当客户端发送请求到服务端时,首先由SMB协议模块接收客户端发送的Packet,然后将Packet解析,并交由VFS模块,最后由VFS模块调用系统调用下发给具体文件系统。
2.1、SMBD服务启动
2.1.1、服务注册
SMBD进程启动时,会将自己注册为服务器服务(加入到全局链表registered_servers中),并提供服务初始化回调函数。
全局链表register_servers定义如下:

static struct registered_server
{
struct registered_server *next, *prev;
const char *service_name;
struct service_details *service_details;
void (*task_init)(struct task_server *);
} *registered_servers;

SMBD服务注册流程如下:
在这里插入图片描述
2.1.2、服务启动
SMB主进程启动(定义在source4/smbd/server.c中的main())时,会扫描register_servers全局链表,查找名字为“smbd”的服务,然后调用服务初始化回调函数启动服务。
SMBD服务启动过程中,函数的调用关系如下图所示。

说明:
1.server_service_startup()函数中根据名字“standard”查找注册的model_ops对象(standard_ops),并在task_server_startup()中将其注册给task_state对象;
2.task_server_startup()函数根据注册给task_state对象的model_ops.new_task(standard_new_task)为SMBD服务启动一个线程,线程的处理函数为task_server_callback();
3.启动SMBD服务线程后,首先创建task_server对象,然后调用SMBD服务的初始化回调函数smbsrv_task_init;
4.调用接口smbsrv_add_socket()为SMB服务关联的所有端口建立监听;
4.1.调用接口stream_setup_socket()建立socket监听,同时构造stream_socket对象,并将socket_context对象加入到tevent_context中;
4.2.设置stream_socket对象的accept处理函数为:stream_accept_handler;
5.在客户端通过某一端口与SMBD服务建立连接时,触发accept回调函数stream_accept_handler;
6.Socket连接建立成功后,调用接口stream_new_connection创建Stream连接对象(stream_connection),同时设置此连接上的io处理函数:stream_io_handler_fde;
7.调用注册的smb_stream_ops.accept_connection(smbsrv_accept)回调函数来注册RPC,同时构造smbsrv_connection对象和客户端与服务端之间的消息对象packet_context。

SMBD服务启动完成后,对象之间的关系如下图所示。
在这里插入图片描述
2.2、SMB请求处理流程
函数调用关系如下图所示。
在这里插入图片描述
说明:
1.在SMBD服务启动阶段创建connection时,注册了Socket描述符的流IO处理函数stream_io_handler_fde;
2.在stream_io_handler中,根据stream_connection对象查找到smbsrv_connection对象;
根据2.1.2中的对象关系图可知,stream_connection对象的private_data字段指向smbsrv_connection对象。
3.Packet_recv接口首先调用接口socket_recv接收客户端的请求包,然后再调用packet_context对象的callback回调函数处理客户端请求包。
2.3、NTVFS实例化
Ntvfs的backends全局链表定义如下:

    static struct ntvfs_backend {
    	const struct ntvfs_ops *ops;
    } *backends = NULL;

2.3.1、backend回调函数注册
“default”的VFS和“posix”的VFS注册:
在这里插入图片描述

将pvfs_xxx系列函数(初始化流程定义在vfs_posix.c中,pvfs_xxx系列函数的实现在pvfs_xxx.c文件中)注册到ntvfs_ops对象,然后将此对象作为“default”和“pasix”的backend回调函数加入到backends全局链表中。
2.3.2、创建smbsrv_tcon对象
在开始建立smb连接时,会注册连接完成异步处理回调函数smb2_connect_session_done。
客户端在完成连接建立时,触发异步回调函数smb2_connect_session_done,回调函数通过接口smb2cli_tcon_send向Server发送请求SMB2_OP_TCON来为此连接创建smbsrv_tcon对象。smbsrv_tcon对象中保存了backend的回调函数。
函数调用关系如下图所示。
在这里插入图片描述
说明:
1.smb2srv_tcon_backend接口在为连接(Connection)创建smbsrv_tcon对象时,首先调用接口ntvfs_init_connection初始化smbsrv_tcon对象,然后再调用接口ntvfs_connect触发backend的connet_fn回调函数来连接到共享。
2.4、SMB读写请求
SMB的读写请求流程与SMB2_OP_TCON请求的处理流程类似,其请求为:SMB2_OP_READ和SMB2_OP_WRITE,最终会调用pvfs_read和pvfs_write接口。

猜你喜欢

转载自blog.csdn.net/qq_41688455/article/details/84655254