core/ngx_file.h头文件分析
本节我们讲述一下nginx中对所涉及到的文件操作的封装。
1. ngx_file_s数据结构
/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */
#ifndef _NGX_FILE_H_INCLUDED_
#define _NGX_FILE_H_INCLUDED_
#include <ngx_config.h>
#include <ngx_core.h>
struct ngx_file_s {
    ngx_fd_t                   fd;
    ngx_str_t                  name;
    ngx_file_info_t            info;
    off_t                      offset;
    off_t                      sys_offset;
    ngx_log_t                 *log;
#if (NGX_THREADS)
    ngx_int_t                (*thread_handler)(ngx_thread_task_t *task,
                                               ngx_file_t *file);
    void                      *thread_ctx;
    ngx_thread_task_t         *thread_task;
#endif
#if (NGX_HAVE_FILE_AIO)
    ngx_event_aio_t           *aio;
#endif
    unsigned                   valid_info:1;
    unsigned                   directio:1;
};ngx_file_s数据结构是对打开的文件的一个封装:
- 
    fd: 所打开文件对应的句柄
- 
    name: 所打开文件的名称
- 
    info: 所打开文件所对应的struct stat信息
- 
    offset: 当前要操作的文件指针偏移
- 
    sys_offset: 当前该打开文件的实际指针偏移
- 
    log: 该打开文件所对应的log
- 
    thread_handler/thread_ctx/thread_task: 当前我们并不支持多线程操作文件,这里暂不介绍
- 
    aio: 这里我们暂不支持NGX_HAVE_FILE_AIO
- 
    valid_info: 本字段暂时未能用到
- 
    directio: 对于当前文件是否使用directio
2. ngx_path_t相关数据结构
#define NGX_MAX_PATH_LEVEL  3
typedef time_t (*ngx_path_manager_pt) (void *data);
typedef void (*ngx_path_loader_pt) (void *data);
typedef struct {
    ngx_str_t                  name;        //文件名
    size_t                     len;         //level中3个数据之和
    size_t                     level[3];    //每一层子目录的长度
    //以下字段只在文件缓冲管理模块被使用
    ngx_path_manager_pt        manager;     //文件缓冲管理回调     
    ngx_path_loader_pt         loader;      //文件缓冲loader回调
    void                      *data;        //回调上下文
    u_char                    *conf_file;   //所关联的配置文件名称
    ngx_uint_t                 line;        //所在配置文件的行数
} ngx_path_t;
typedef struct {
    ngx_str_t                  name;
    size_t                     level[3];
} ngx_path_init_t;ngx_path_t是一个目录对象结构:

上图是nginx创建的临时文件结构。nginx在根目录下最多创建3层目录结构。例如:
/home/nginx/tmpfile/9/32/198
其中home/nginx/tmpfile为根目录,9/32/198``则为3层子目录结构。
ngx_path_t是用于初始时候的一个路径。
3. ngx_temp_file_t数据结构
typedef struct {
    ngx_file_t                 file;        //文件结构
    off_t                      offset;      //当前操作偏移
    ngx_path_t                *path;        //临时文件所对应的路径
    ngx_pool_t                *pool;        //所对应的缓冲池
    char                      *warn;        //岁对应的警告信息
    ngx_uint_t                 access;      //临时文件的访问权限
    unsigned                   log_level:8;  //所对应的日志级别
    unsigned                   persistent:1;  //是否需要对当前临时文件进行持久化
    unsigned                   clean:1;       //退出时,临时文件是否要删除
    unsigned                   thread_write:1; //是否开启多线程写
} ngx_temp_file_t;ngx_temp_file_t代表一个临时文件结构。
4. ngx_ext_rename_file_t数据结构
typedef struct {
    ngx_uint_t                 access;        //文件访问权限
    ngx_uint_t                 path_access;   //路径访问权限
    time_t                     time;          //重命名时间
    ngx_fd_t                   fd;            //对应的文件句柄
    unsigned                   create_path:1;  //是否创建路径
    unsigned                   delete_file:1;  //如果重命名失败,是否要删除文件
    ngx_log_t                 *log;            //所对应的日志
} ngx_ext_rename_file_t;重命名文件所对应相关数据结构
5. ngx_copy_file_t数据结构
typedef struct {
    off_t                      size;           //要拷贝的文件大小
    size_t                     buf_size;       //拷贝时新开临时缓冲区大小
    ngx_uint_t                 access;         //新拷贝文件的访问权限
    time_t                     time;           //新拷贝文件的最近访问时间和最近修改时间
    ngx_log_t                 *log;
} ngx_copy_file_t;6. ngx_tree_ctx_s数据结构
typedef struct ngx_tree_ctx_s  ngx_tree_ctx_t;
typedef ngx_int_t (*ngx_tree_init_handler_pt) (void *ctx, void *prev);
typedef ngx_int_t (*ngx_tree_handler_pt) (ngx_tree_ctx_t *ctx, ngx_str_t *name);
struct ngx_tree_ctx_s {
    off_t                      size;
    off_t                      fs_size;
    ngx_uint_t                 access;
    time_t                     mtime;
    ngx_tree_init_handler_pt   init_handler;
    ngx_tree_handler_pt        file_handler;
    ngx_tree_handler_pt        pre_tree_handler;
    ngx_tree_handler_pt        post_tree_handler;
    ngx_tree_handler_pt        spec_handler;
    void                      *data;
    size_t                     alloc;
    ngx_log_t                 *log;
};这里是nginx遍历目录的相关数据结构,下面我们简要介绍一下其中的各个字段:
- 
    size: 遍历到的文件的大小
- 
    fs_size: 指的是遍历到的文件所占磁盘块数目乘以512的值与size中的最大值,即fs_size = ngx_max(size,st_blocks*512)
- 
    access: 指的是遍历到的文件的访问权限
- 
    mtime: 指的是遍历到的文件上次被修改的时间
- 
    init_handler: 与下面的data、alloc字段相关,用于初始化遍历过程中的相关数据结构。一般如果alloc字段不为0的话,表示要分配alloc大小的空间,此时会调用init_handler回调函数初始化。
- 
    file_handler: 处理普通文件的回调函数
- 
    pre_tree_handler: 进入一个目录前的回调函数
- 
    post_tree_handler: 离开一个目录后的回调函数
- 
    spec_handler: 处理特殊文件的回调函数,比如socket、FIFO等
- 
    data: 传递一些数据结构,可以在不同的目录下使用相同的数据结构,或者也可以重新分配,前提是alloc不为0
- 
    alloc: 如果需要分配一些数据结构,这里指定分配数据结构的大小,并由init_handler进行初始化
- 
    log: 主要用于日志的记录
7. 相关函数声明
//获得某个文件的全路径
ngx_int_t ngx_get_full_name(ngx_pool_t *pool, ngx_str_t *prefix,
    ngx_str_t *name);
//将buffer chain写入到temp文件
ssize_t ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain);
//创建temp文件
ngx_int_t ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path,
    ngx_pool_t *pool, ngx_uint_t persistent, ngx_uint_t clean,
    ngx_uint_t access);
//创建hash文件名
void ngx_create_hashed_filename(ngx_path_t *path, u_char *file, size_t len);
//创建路径
ngx_int_t ngx_create_path(ngx_file_t *file, ngx_path_t *path);
//创建全路径
ngx_err_t ngx_create_full_path(u_char *dir, ngx_uint_t access);
//添加路径到cf->cycle->paths数组中
ngx_int_t ngx_add_path(ngx_conf_t *cf, ngx_path_t **slot);
//创建cycle->paths数组中的所有路径
ngx_int_t ngx_create_paths(ngx_cycle_t *cycle, ngx_uid_t user);
//重命名文件
ngx_int_t ngx_ext_rename_file(ngx_str_t *src, ngx_str_t *to,
    ngx_ext_rename_file_t *ext);
//拷贝文件
ngx_int_t ngx_copy_file(u_char *from, u_char *to, ngx_copy_file_t *cf);
//遍历某一目录下(tree目录)的文件
ngx_int_t ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_str_t *tree);
//获得下一个临时number值
ngx_atomic_uint_t ngx_next_temp_number(ngx_uint_t collision);
//设置某一模块中的路径指令
char *ngx_conf_set_path_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
//合并路径值
char *ngx_conf_merge_path_value(ngx_conf_t *cf, ngx_path_t **path,
    ngx_path_t *prev, ngx_path_init_t *init);
//设置某一个文件的所有者、所属组、其他人的访问权限
char *ngx_conf_set_access_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);8. 相关变量声明
//全局的临时值变量,主要用于产生临时文件名使用
extern ngx_atomic_t      *ngx_temp_number;
//nginx内部维持的一个随机值变量
extern ngx_atomic_int_t   ngx_random_number;
[参考]

