C/C++编程:FastDFS单机版环境部署
发布日期:2022-03-16 03:25:43 浏览次数:31 分类:技术文章

本文共 16352 字,大约阅读时间需要 54 分钟。

gcc、g++编译器

apt-get install gccapt-get install g++apt-get install build-essentialapt-get install libtool

Nginx的安装和部署

准备

PCRE库

  • PCRE(Perl Compatible Regular Expressions):perl语言兼容正则表达式。PCRE是一个用C语言编写的正则表达式函数库。PCRE是一个轻量级的函数库,比Boost之中的正则表达式库小得多。PCRE十分易用,同时功能也很强大,性能超过了POSIX正则表达式库和一些经典的正则表达式库
  • PCRE(Perl Compatible Regular Expressions):perl语言兼容正则表达式。PCRE是一个用C语言编写的正则表达式函数库。PCRE是一个轻量级的函数库,比Boost之中的正则表达式库小得多。PCRE十分易用,同时功能也很强大,性能超过了POSIX正则表达式库和一些经典的正则表达式库
  • PCRE被广泛使用在许多开源软件之中,最著名的莫过于Apache HTTP服务器和PHP脚本语言、R脚本语言,此外,正如从其名字所能看到的,PCRE也是perl语言的缺省正则库
  • PCRE是用C语言实现的,其C++实现版本叫PCRE++
wget https://sourceforge.net/projects/pcre/files/pcre/8.44/pcre-8.44.tar.gztar -zxvf pcre-8.44.tar.gzcd pcre-8.44/./configuremakemake install

zlib库

  • zlib 适用于数据压缩的函式库,由Jean-loup Gailly (负责compression)和 Mark Adler (负责decompression)开发。
  • zlib被设计成一个免费的、通用的、法律上不受阻碍(即没有被任何专利覆盖) 的无损数据压缩库。zlib几乎适用于任何计算器硬件和操作系统。
  • zlib本身的数据格式可以进行跨平台的移植。 与在Unix上适用的LZW压缩方法 以及 GIF 图像压缩不同, zlib中适用的压缩方法从不对数据进行拓展。(LZW在极端情况下会导致文件大小变为原来的两倍、甚至三倍)。zlib的内存占用也是独立于输入数据的,并且在必要的情况下可以适当减少部分内存占用。
wget https://nchc.dl.sourceforge.net/project/libpng/zlib/1.2.11/zlib-1.2.11.tar.gztar -zxvf zlib-1.2.11.tar.gzcd zlib-1.2.11/./configuremakemake install

OpenSSL开发库

  • 在计算机网络上,OpenSSL是一个开放源代码的软件库包,应用程序可以使用这个包来进行安全通信,避免窃听,同时确认另一端连接者的身份。这个包广泛被应用在互联网的网页服务器上。
wget https://www.openssl.org/source/openssl-1.1.1g.tar.gztar -zxvf openssl-1.1.1g.tar.gzcd openssl-1.1.1g/./configmakemake install

Nginx的安装和启动

编译和安装

wget http://nginx.org/download/nginx-1.16.1.tar.gztar -zxvf nginx-1.16.1.tar.gzcd nginx-1.16.1/./configure --with-http_ssl_modulemakemake install//./configure --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_ssl_module --with-http_realip_module --with-http_v2_module --with-openssl=../openssl-1.1.1g

启动和关闭

默认情况下,Nginx被安装在目录/usr/local/nginx中

$ cd /usr/local/nginx/$ lsconf  html  logs  sbin

其中,nginx的配置文件是conf/nginx.conf,bin文件位于sbin目录下的nginx

1) 默认方式启动nginx服务器

/usr/local/nginx/sbin/nginx

这时,会自动读取配置文件:/usr/local/nginx/conf/nginx.conf

2)查看nginx进程

ps -ef | grep nginx/root       93540    1384  0 08:40 ?        00:00:00 nginx: master process /usr/local/nginx/sbin/nginxroot       97295    2911  0 08:41 pts/0    00:00:00 grep --color=auto nginx/

可以看到,nginx的主进程已经启动(nginx: master process)

打开浏览器访问此机器的IP,如果浏览器出现 Welcome to nginx! 则表示 Nginx 已经安装并运⾏成功

在这里插入图片描述

3)指定配置⽂件启动服务器

$ /usr/local/nginx/sbin/nginx -c /usr/local/nginx/conf/nginx.conf

4))测试配置信息

$ /usr/local/nginx/sbin/nginx -tnginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is oknginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful

FastDFS 安装与配置

版本:

  • libfastcommon 1.0.50
  • fastdfs 6.0.7

中文地址:

安装libfastcommon

libfastcommon是一款开源的C基础库,是从FastDFS项目中剥离出来的C基础库

git clone https://gitee.com/fastdfs100/libfastcommoncd libfastcommongit checkout V1.0.50./make.sh./make.sh install

注意版本一定要切换到V1.0.50,否则安装 FastDFS时可能出现莫名其妙的错误

安装 FastDFS

git clone https://gitee.com/fastdfs100/fastdfs.gitcd fastdfsgit checkout V6.07./make.sh./make.sh install

在这里插入图片描述

配置Tracker

  • Tracker是FastDFS的协调者,负责管理所有的storage server和group
  • 每个storage在启动后会连接Tracker,告知⾃⼰所属的group等信息,并保持周期性的⼼跳,tracker根据storage的⼼跳信息,建⽴group==>[storage server list]的映射表。
# 创建Tracker的存储日志和数据的根目录mkdir -p /home/fastdfs/trackercd /etc/fdfcp tracker.conf.sample tracker.conf# 配置tracker.confgedit tracker.conf

在这里,tracker.conf只是修改一下tracker存储日志和数据的路径

# 启⽤配置⽂件(默认为 false,表示启⽤配置⽂件)disabled=false# Tracker 服务端⼝(默认为 22122)port=22122# 存储⽇志和数据的根⽬录base_path=/home/fastdfs/tracker

主要修改base_path路径。

配置storage

  • Storage server(后简称storage)以组(卷,group或volume)为单位组织,⼀个group内包含多台storage机器,数据互为备份
  • group内每个storage的存储依赖于本地⽂件系统,storage可配置多个数据存储⽬录,⽐如有10块磁盘,分别挂载在/data/disk1-/data/disk10,则可将这10个⽬录都配置为storage的数据存储⽬录。
# 创建 Storage 的存储⽇志和数据的根⽬录mkdir -p /home/fastdfs/storagecd /etc/fdfscp storage.conf.sample storage.conf# 配置 storage.confgedit  storage.conf

在这⾥,storage.conf 只是修改⼀下 storage 存储⽇志和数据的路径

# 启⽤配置⽂件(默认为 false,表示启⽤配置⽂件)disabled = false# Storage服务端口,默认为23000port = 23000# 数据和日志文件存储根目录base_path = /home/fastdfs/storage# store_path1 则为 M01,以此递增到 M99(如果配置了多个存储⽬录的话,这⾥只指定 1 个)store_path0=/home/fastdfs/storage# Tracker 服务器 IP 地址和端⼝,单机搭建时也不要写 127.0.0.1# tracker_server 可以多次出现,如果有多个,则配置多个tracker_server=192.168.0.59:22122  #192.168.0.59为本机IP地址# 设置 HTTP 访问⽂件的端⼝。这个配置已经不⽤配置了,配置了也没什么⽤# 这也是为何 Storage 服务器需要 Nginx 来提供 HTTP 访问的原因http.server_port=8888

主要修改:base_path、store_path0、tracker_server

启动 Tracker 和 Storage 服务

启动服务

# 启动 Tracker 服务# 其它操作则把 start 改为 stop、restart、reload、status 即可。Storage 服务相同/etc/init.d/fdfs_trackerd start# 启动 Storage 服务/etc/init.d/fdfs_storaged start

可以通过对应服务的端⼝查看服务是否正常启动

$ lsof -i:22122COMMAND      PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAMEfdfs_trac 132006 root    5u  IPv4 1862830      0t0  TCP *:22122 (LISTEN)$ lsof -i:23000COMMAND      PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAMEfdfs_stor 131914 root    5u  IPv4 1860968      0t0  TCP *:23000 (LISTEN)

可以通过 fdfs_monitor 查看集群的情况

# 查看 Storage 是否已经注册到 Tracker 服务器中# 当查看到 ip_addr = 192.168.0.59: (localhost.localdomain) ACTIVE# ACTIVE 表示成功/usr/bin/fdfs_monitor /etc/fdfs/storage.conf

在这里插入图片描述

查看⽇志

tracker:

  • tail -f /home/fastdfs/tracker/logs/trackerd.log

storage:

  • tail -f /home/fastdfs/storage/logs/storaged.log

上传文件测试

1)修改配置

# 修改 Tracker 服务器客户端配置⽂件mkdir -p /home/fastdfs/clientcp /etc/fdfs/client.conf.sample /etc/fdfs/client.confgedit /etc/fdfs/client.conf

client.conf 中修改 base_path 和 Tracker 服务器的 IP 地址与端⼝号即可

# 存储⽇志⽂件的基本路径base_path=/home/fastdfs/client# Tracker 服务器 IP 地址与端⼝号tracker_server=192.168.0.59:22122

主要修改base_path和tracker_server

2)开始上传

# 存储到FastDFS服务器中# 格式:  /usr/bin/fdfs_upload_file 配置⽂件 要上传的⽂件$ /usr/bin/fdfs_upload_file /etc/fdfs/client.conf ./client.confgroup1/M00/00/00/wKgAO2IgGsaAepcnAAAHdc51W4U54.conf

返回了文件ID号group1/M00/00/00/wKgAO2IgGsaAepcnAAAHdc51W4U54.conf,表示上传成功

进入目录/home/fastdfs/storage/data/00/00,可以看到wKgAO2IgGsaAepcnAAAHdc51W4U54.conf就是我们刚刚上传的文件

$ cd  /home/fastdfs/storage/data/00/00$ lswKgAO2IgGsaAepcnAAAHdc51W4U54.conf

下载文件测试

  1. 下载文件
$ fdfs_download_file /etc/fdfs/client.conf  group1/M00/00/00/wKgAO2IgGsaAepcnAAAHdc51W4U54.conf$ lswKgAO2IgGsaAepcnAAAHdc51W4U54.conf
  1. 删除文件
$ fdfs_delete_file /etc/fdfs/client.conf  group1/M00/00/00/wKgAO2IgGsaAepcnAAAHdc51W4U54.conf

进入目录/home/fastdfs/storage/data/00/00,可以看到wKgAO2IgGsaAepcnAAAHdc51W4U54.conf这个目录没有了

到目前为止,我们已经 完成了FastDFS的安装和测试,可以使用api来完成文件的上传、同步和下载。

接下来,我们还会安装nginx,目的如下:

  • Storage安装nginx:提供http的访问和下载服务,同时解决group中storage服务器的同步延迟问题
  • Tracker安装nginx:提供http访问的反向代理、负载均衡、缓存服务

fastdfs-nginx-module安装

备份原来的nginx

为了避免端口冲突,建议备份原来的nginx服务

$ cd /usr/local$ /usr/local/nginx/sbin/nginx -s stop$ mv nginx bk-nginx-20220223

安装

注意:在安装之前,先确保之前fastDFS的tracker、storage、client可以正常使用(服务必须已经开启),否则上传/下载文件时会出现:

ERROR - file: connection_pool.c, line: 140, connect to server 192.168.0.59:22122 fail, errno: 111, error info: Connection refused

下载fastdfs-nginx-module

$ git clone https://github.com/happyfish100/fastdfs-nginx-module.git$ cd fastdfs-nginx-module$ lsHISTORY  INSTALL  LICENSE  src$ git checkout V1.22$ pwd/home/oceanstar/workspace/fastdfs-nginx-module/src

cd fastdfs-nginx-module可以看到里面有个INSTALL和src目录,这个不需要make而是需要重新编译一些storage的nginx模块

重新编译nginx

1) 添加FastDFS模块

$ cd nginx-1.16.1  # 进入之前下载的nginx源目录$ ./configure --add-module=/home/oceanstar/workspace/fastdfs-nginx-module/src  #是在编译Nginx时候,连同刚刚下载的fastdfs-nginx-module模块⼀起编译

编译时, 出现以下信息表示添加成功

在这里插入图片描述
2) 给 nginx ⽬录下的 objs/Makefile ⽂件中增加头⽂件⽬录

gedit objs/Makefile

添加

ALL_INCS = -I src/core \-I /usr/include/fastdfs \-I /usr/include/fastcommon \-I src/event \-I src/event/modules \

在这里插入图片描述

3) 重新编译并安装nginx

makemake install

配置fastdfs-nginx-module

拷贝配置文件

1) 拷⻉fastdfs-nginx-module配置⽂件

$ cd /home/oceanstar/workspace/fastdfs-nginx-module/src/$ lscommon.c  common.h  config  mod_fastdfs.conf  ngx_http_fastdfs_module.c$ cp mod_fastdfs.conf /etc/fdfs/

2) 拷⻉fastdfs/conf 配置⽂件

$ cd /home/oceanstar/workspace/fastdfs/conf$ cp http.conf /etc/fdfs/$ cp mime.types /etc/fdfs/

修改配置文件

$ mkdir -p /home/fastdfs/mod_fastdfs$ gedit  /etc/fdfs/mod_fastdfs.conf

修改base_path 、tracker_server、url_have_group_name、store_path0。

#保存⽇志⽬录base_path =/home/fastdfs/mod_fastdfs# Tracker 服务器IP和端⼝修改,确保跟storage.conf⼀致即可tracker_server=192.168.0.59:22122# url 中是否包含 group 名称,改为 true,包含 groupurl_have_group_name = true# store_path0的路径必须和storage.conf的配置⼀致store_path0=/home/fastdfs/storage# 其它的⼀般默认即可,例如group_name=group1storage_server_port=23000store_path_count=1

配置nginx

gedit /usr/local/nginx/conf/nginx.conf

配置为⽀持 group0-group9,以及 M00-M99,以便于以后扩容

location ~/group([0-9])/M([0-9])([0-9]) {
ngx_fastdfs_module;}

在这里插入图片描述

启动nginx

/usr/local/nginx/sbin/nginx

测试环境

服务器中测试上传

$ touch 0voice.txt$ echo "You are not strong, no one brave for you" > 0voice.txt$ fdfs_upload_file /etc/fdfs/client.conf 0voice.txtgroup1/M00/00/00/wKgAO2IgJzeANR9sAAAAKTIQHvk110.txt

浏览器中输入: http://192.168.0.59:80/group1/M00/00/00/wKgAO2IgJzeANR9sAAAAKTIQHvk110.txt

在这里插入图片描述

协议格式

协议

FastDFS采用二进制TCP通信协议。一个数据包由包头(header)和包体(body)组成。包头只有10个字节,格式如下:

  • pkg_len:8字节整数,body长度,不包含header,只是body的长度
  • cmd:1字节整数,命令码
  • status:1字节整数,状态码,0表示成功,非0失败(unix错误码)
tracker\tracker_proto.h TrackerHeadertypede fstruct{
char pkg_len[FDFS_PROTO_PKG_LEN_SIZE]; // body⻓度,不包括header char cmd; //command 命令 char status; //status code for response 响应的状态码} TrackerHeader;即是头部固定10字节,body⻓度通过pkg_len给出。即是⼀帧完整的协议为 TrackerHeader + body数据(可以为0).

数据包中的类型说明:

  • 整数类型采用网络字节序(Big-Endian),包括4字节整数和8字节整数
  • 1字节整数不存在字节序问题,在java中直接映射为byte类型,在C/C++中为char类型
  • 固定长度的字符串类型以ASCII码0结尾,对于Java等语言语⾔需要调⽤trim处理返回的字符串。变⻓字符串的⻓度可以直接拿到或者根据包⻓度计算出来,不以ASCII 0结尾。

下⾯将列举client发送给FastDFS server的命令码及其body(包体)结构。

公共命令码

  • FDFS_PROTO_CMD_ACTIVE_TEST:激活测试,通常⽤于检测连接是否有效。客户端使⽤连接池的情况下,建⽴连接后发送⼀次active test即可和server端保持⻓连接。
    • 请求body:⽆
    • 响应body:⽆

发送给tracker server的命令码

  • TRACKER_PROTO_CMD_SERVER_LIST_ONE_GROUP:查看⼀个group状态
    • 请求body:
      • @group_name:16字节字符串,组名
    • 响应body:
      • @group_name:17字节字符串
      • @total_mb:8字节整数,磁盘空间总量,单位MB
      • @free_mb:8字节整数,磁盘剩余空间,单位MB
      • @trunk_free_mb:8字节整数,trunk⽂件剩余空间,单位MB(合并存储开启时有效)
      • @server_count:8字节整数,storage server数量
      • @storage_port:8字节整数,storage server端⼝号
      • @storage_http_port:8字节整数,storage server上的HTTP端⼝号
      • @active_count:8字节整数,当前活着的storage server数量
      • @current_write_server:8字节整数,当前写⼊的storage server顺序号
      • @store_path_count:8字节整数,storage server存储路径数
      • @subdir_count_per_path:8字节整数,存储路径下的⼦⽬录数(FastDFS采⽤两级⼦⽬录),如 256
      • @current_trunk_file_id:8字节整数,当前使⽤的trunk⽂件ID(合并存储开启时有效)

⽂件上传

client\fdfs_test1.c

  1. FDFS_UPLOAD_BY_FILE: storage_upload_by_filename1
  2. FDFS_UPLOAD_BY_BUFF:storage_upload_by_filebuff1
  3. FDFS_UPLOAD_BY_CALLBACK: storage_upload_by_callback1

在这里插入图片描述

在这里插入图片描述

⽂件上传函数层次接⼝

#define storage_upload_by_filename1(pTrackerServer, // tracker server的地址信息   pStorageServer, // storage server的地址信息   store_path_index, // 具体path,⽐如0、1 对应配置⽂件的store_path0、store_path1   local_filename, // 要上传的⽂件名   file_ext_name, // ⽂件类型,⽐如txt、jpg   meta_list, //⽐如 "width"  "160" 参考:client\fdfs_test1.c 201⾏   meta_count, // meta_list列表的元素个数   group_name, // 所属的group名   file_id) // 上传成功后返回file_id实际上传调⽤的函数storage_upload_by_filename1_ex(pTrackerServer, pStorageServer, \   store_path_index,     STORAGE_PROTO_CMD_UPLOAD_FILE, \ // 服务器响应的命令   local_filename, file_ext_name, meta_list, meta_count, \   group_name, file_id)    继续往下调⽤int storage_upload_by_filename_ex(ConnectionInfo *pTrackerServer, \ ConnectionInfo *pStorageServer, const int store_path_index, \ const char cmd, const char *local_filename, \ const char *file_ext_name, const FDFSMetaData *meta_list, \ const int meta_count, char *group_name, char *remote_filename)        在继续storage_do_upload_file(pTrackerServer, pStorageServer, \ store_path_index, cmd, \ FDFS_UPLOAD_BY_FILE, // 以⽂件的⽅式上传内容,还有FDFS_UPLOAD_BY_BUFF以内存的载体⽅式上传 local_filename, \ // 作为⽂件名或者 内存数据的起始地址 NULL, // arg   stat_buf.st_size, // file_size NULL, // master_filename NULL, // prefix_name file_ext_name, \ // file_ext_name meta_list, meta_count, group_name, remote_filename // file_id )

调试

对应命令:/usr/bin/fdfs_upload_file /etc/fdfs/client.conf /etc/fdfs/client.conf

怎么调试:

(1) gdb启动上传⽂件程序:

gdb /usr/bin/fdfs_upload_file

(2) 设置参数:

set args /etc/fdfs/client.conf    /etc/fdfs/client.conf

(3) 在main函数打断点:

b main

(4) 在上传函数断点:

b storage_do_upload_file

(5) 开始运行:

r

在这里插入图片描述

(6) 令程序进行执行,其会在下一个断点处停止: c
在这里插入图片描述

⽂件下载

client\fdfs_test1.c client\fdfs_download_file.c

  • FDFS_DOWNLOAD_TO_FILE:storage_do_download_file1_ex
  • FDFS_DOWNLOAD_TO_BUFF:storage_download_file1
  • FDFS_DOWNLOAD_TO_CALLBACK:storage_download_file_ex

在这里插入图片描述

在这里插入图片描述

对应命令:fdfs_download_file /etc/fdfs/client.conf group1/M00/00/00/wKgAO2IgGsaAepcnAAAHdc51W4U54.conf

怎么调试:

(1) gdb启动上传⽂件程序:

gdb /usr/bin/fdfs_download_file

(2) 设置参数:

set args /etc/fdfs/client.conf  group1/M00/00/00/wKgAO2InXbSAF9vpAAAHdc51W4U06.conf

(3) 打断点:

b mainb storage_do_download_file1_ex

(4) 开始运行:

r

断点续传

对应命令:

  1. 准备
echo hello > test1.txtecho world > test2.txt
  1. 上传第一部分
fdfs_upload_appender /etc/fdfs/client.conf test1.txt

得到:group1/M00/00/00/rBMYd2Id2FmEay2-AAAAADY6MCA286.txt ,在fdfs_append_file的时候需要

  1. 上传第二部分
fdfs_append_file /etc/fdfs/client.conf group1/M00/00/00/rBMYd2Id2FmEay2-AAAAADY6MCA286.txt test2.txt
  1. 在服务器相应的⽬录下查找对应的⽂件,⽤cat读取⽂件内容。
root@iZbp1h2l856zgoegc8rvnhZ:/home/fastdfs/storage/data/00/00# catrBMYd2Id2FmEay2-AAAAADY6MCA286.txthelloworld

可以看出,断点续传文件分为两个阶段:

  1. fdfs_upload_appender 上传第⼀部分⽂件,以STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE命令
  2. fdfs_append_file 上传其他部分的⽂件,以STORAGE_PROTO_CMD_APPEND_FILE命令

需要注意:

  1. 注意断点续传的顺序性
  2. fastdfs支持断点续传,但是不支持多线程分片上传同一个文件

网络IO模型

对应配置项

# accept thread count# default value is 1 which is recommended# since V4.07accept_threads = 1# work thread count# work threads to deal network io# default value is 4# since V2.00work_threads = 4# if disk read / write separated## false for mixed read and write## true for separated read and write# default value is true# since V2.00disk_rw_separated = true# disk reader thread count per store path# for mixed read / write, this parameter can be 0# default value is 1# since V2.00disk_reader_threads = 1# disk writer thread count per store path# for mixed read / write, this parameter can be 0# default value is 1# since V2.00disk_writer_threads = 1

线程初始化

默认:

g_accept_threads 1g_work_threads 4g_disk_reader_threads默认1g_disk_writer_threads 1

⽂件操作线程: 根据读写线程数量,path数量确定 ⽂件操作线程数量

threads_count_per_path = g_disk_reader_threads + g_disk_writer_threads;context_count = threads_count_per_path * g_fdfs_store_paths.count;
文件名 作用 初始化函数 工作线程
storage\storage_service.c ⽹络IO任务处理 storage_service_init work_thread_entrance
storage\storage_service.c accept线程 storage_accept_loop accept_thread_entrance
storage\storage_dio.c ⽂件操作相关初始化 storage_dio_init dio_thread_entrance

队列:

  • storage_dio_queue ⽂件处理队列
  • task_queue 任务对象池队列

管道:

  • thread_data.pipe_fds[2]:IO⼯作线程的触发
  • storage_nio_notify 触发取读取⽹络io数据

accept_thread_entrance:

  • 本身是一个线程
  • 调用accept获取新的连接:incomesock = accept(server_sock, (struct sockaddr*)&inaddr, &sockaddr_len);
  • 获取对方IP地址:client_addr = getPeerIpaddr(incomesock, szClientIp, IP_ADDRESS_SIZE);
  • 从对象池取⼀个task对象:pTask = free_queue_pop()
  • task对象里面有client的封装信息,需要设置:
    • pTask->event.fd = incomesock
    • pClientInfo = (StorageClientInfo *)pTask->arg;
    • pClientInfo->stage = FDFS_STORAGE_STAGE_NIO_INIT;
    • 轮询线程:pClientInfo->nio_thread_index = pTask->event.fd % g_work_threads;`
    • 通知IO线程有新的连接:write(pThreadData->thread_data.pipe_fds[1], &task_addr, sizeof(task_addr)) != sizeof(task_addr)

work_thread_entrance:

  • 本身是一个线程
  • 核⼼调⽤ ioevent_loop(&pThreadData->thread_data, storage_recv_notify_read, task_finish_clean_up, &g_continue_flag);
    • storage_recv_notify_read 当数据可读时触发
  • 进⼊到ioevent_loop核⼼:
    • 实际是调⽤epoll_wait:pThreadData->ev_puller.iterator.count = ioevent_poll(&pThreadData->ev_puller); 返回可处理事件
    • 循环处理事件:deal_ioevents
      • 调⽤storage_recv_notify_read

⽂件IO线程dio_thread_entrance:

  • 本身是一个线程
  • 任务由storage_dio_queue_push 投递
  • 从blocked_queue_pop读取任务
  • 通过回调写⼊⽂件dio_write_file 或者 读取⽂件dio_read_file
(gdb) b storage_dio.c:748Breakpoint 1 at 0x55c62441f084: file storage_dio.c, line 748.(gdb) b client_sock_readBreakpoint 2 at 0x55c62441e852: file storage_nio.c, line 245.(gdb) b client_sock_writeBreakpoint 3 at 0x55c62441eb80: file storage_nio.c, line 434.(gdb) b storage_recv_notify_readBreakpoint 4 at 0x55c62441ee7f: file storage_nio.c, line 121.(gdb) b dio_write_fileBreakpoint 5 at 0x55c62441fa46: file storage_dio.c, line 405.(gdb) b storage_nio_notifyBreakpoint 6 at 0x55c62440adf1: file storage_service.c, line 1918.(gdb) b storage_upload_file_done_callbackBreakpoint 7 at 0x55c624416da4: file storage_service.c, line 1131.

框架

核⼼函数:

  • accept_thread_entrance accept线程⼊⼝
  • work_thread_entrance nio线程⼊⼝
  • dio_thread_entrance 数据处理线程⼊⼝

在这里插入图片描述

dio线程不会直接给nio线程设置各种读写事件,⽽是通过FDFS_STORAGE_STAGE_NIO_INIT、FDFS_STORAGE_STAGE_NIO_RECV、FDFS_STORAGE_STAGE_NIO_SEND、FDFS_STORAGE_STAGE_NIO_CLOSE、FDFS_STORAGE_STAGE_DIO_THREAD等状态 + 通过pipe通知nio线程响应storage_recv_notify_read进⾏io事件的处理。

数据流程

在这里插入图片描述

文章目录

转载地址:https://blog.csdn.net/zhizhengguan/article/details/123244728 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:gdb:使用总结
下一篇:log4cpp源码阅读:Category组件学习

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2024年03月24日 13时38分03秒