core/ngx_open_file_cache.h头文件分析
本节主要讲述一下nginx对静态文件的缓存相关操作。
1. directio_off宏定义
/*
 * Copyright (C) Igor Sysoev
 * Copyright (C) Nginx, Inc.
 */
#include <ngx_config.h>
#include <ngx_core.h>
#ifndef _NGX_OPEN_FILE_CACHE_H_INCLUDED_
#define _NGX_OPEN_FILE_CACHE_H_INCLUDED_
#define NGX_OPEN_FILE_DIRECTIO_OFF  NGX_MAX_OFF_T_VALUE在objs/ngx_auto_config.h头文件中,有如下定义:
#ifndef NGX_MAX_OFF_T_VALUE #define NGX_MAX_OFF_T_VALUE 9223372036854775807LL #endif
这里定义NGX_OPEN_FILE_DIRECTIO_OFF为long long的最大值,一般文件大小都不会超过此值,因此可以将此值作为directio_off来用。
2. ngx_open_file_info_t数据结构
typedef struct {
    ngx_fd_t                 fd;
    ngx_file_uniq_t          uniq;
    time_t                   mtime;
    off_t                    size;
    off_t                    fs_size;
    off_t                    directio;
    size_t                   read_ahead;
    ngx_err_t                err;
    char                    *failed;
    time_t                   valid;
    ngx_uint_t               min_uses;
#if (NGX_HAVE_OPENAT)
    size_t                   disable_symlinks_from;
    unsigned                 disable_symlinks:2;
#endif
    unsigned                 test_dir:1;
    unsigned                 test_only:1;
    unsigned                 log:1;
    unsigned                 errors:1;
    unsigned                 events:1;
    unsigned                 is_dir:1;
    unsigned                 is_file:1;
    unsigned                 is_link:1;
    unsigned                 is_exec:1;
    unsigned                 is_directio:1;
} ngx_open_file_info_t;ngx_open_file_info_t用于nginx中描述一个打开的缓存文件, 下面我们简要分析一下各字段的含义:
- 
    fd: 该文件所对应的文件句柄
- 
    uniq: 该文件所对应的全局唯一标识, 一般取值为inode节点号
- 
    mtime: 该文件的最后修改时间
- 
    size: 该文件的大小
- 
    fs_size: 该文件所占用的硬盘层面的块数block * 512
这里关于size与fs_size的区别,简单说明一下。 首先执行如下命令:
# man 2 stat
struct stat {
   dev_t     st_dev;     /* ID of device containing file */
   ino_t     st_ino;     /* inode number */
   mode_t    st_mode;    /* protection */
   nlink_t   st_nlink;   /* number of hard links */
   uid_t     st_uid;     /* user ID of owner */
   gid_t     st_gid;     /* group ID of owner */
   dev_t     st_rdev;    /* device ID (if special file) */
   off_t     st_size;    /* total size, in bytes */
   blksize_t st_blksize; /* blocksize for file system I/O */
   blkcnt_t  st_blocks;  /* number of 512B blocks allocated */
   time_t    st_atime;   /* time of last access */
   time_t    st_mtime;   /* time of last modification */
   time_t    st_ctime;   /* time of last status change */
};
The st_size field gives the size of the file (if it is a regular file or a symbolic link) in bytes.  The size of a symbolic
link is the length of the  pathname it contains, without a terminating null byte.
The st_blocks field indicates the number of blocks allocated to the file, 512-byte units.  (This may be smaller than st_size/512 
when the file has holes.)这里求fs_size一般采用如下宏:
#define ngx_file_fs_size(sb) ngx_max((sb)->st_size, (sb)->st_blocks * 512)
一般在文件有hole的情况下, 文件的size大于fs_size, 否则fs_size小于等于size。
- 
    directio: 文件对应的directio大小值, 小于该值采用sendfile来发送, 大于该值采用aio来发送, 这样可以防止进程被阻塞。
- 
    read_ahead: 预先由内核读取的字节数。关于read_ahead, 有如下一段说明:
Syntax: read_ahead size; Default: read_ahead 0; Context: http, server, location Sets the amount of pre-reading for the kernel when working with file. On Linux, the posix_fadvise(0, 0, 0, POSIX_FADV_SEQUENTIAL) system call is used, and so the size parameter is ignored. On FreeBSD, the fcntl(O_READAHEAD, size) system call, supported since FreeBSD 9.0-CURRENT, is used. FreeBSD 7 has to be patched.
- 
    err: 该打开的文件所关联的错误信息码
- 
    failed: 所关联的错误信息
- 
    valid: 文件的有效时间
- 
    min_uses: 本字段牵扯到open_file_cache指令,指令中inactive参数时间内文件的最少访问次数,如果超过这个数字,该打开的文件描述符将会一直
关于disable_symlinks_from与disable_symlinks字段,主要用于决定当打开文件的时候如何处理符号链接(symbolic links)。其中前一个字段用于指定从哪一个字段开始检查符号链接, 而后一个字段用于指定是否禁止符号链接。在objs/ngx_auto_config.h头文件中有如下定义:
#ifndef NGX_HAVE_OPENAT #define NGX_HAVE_OPENAT 1 #endif
- 
    test_dir: 有时可能在程序运行过程中,一个directory变成了一个file, 通过此字段控制是否需要再进行dir的检测
- 
    test_only: 只用于测试nginx中某一个特定的文件,以了解相关信息,并不会真正把其放入到nginx的静态文件cache中
- 
    log: 本字段当前主要用于指示是否只以非阻塞只读方式打开一个文件
- 
    errors: 主要用于指示当操作缓存文件出现错误时,如何处理。 当此字段为0, 则出现错误时返回失败; 当此字段为1, 则出现错误时可能会进行重建操作。本字段主要用于指示是否能够忍受errors
- 
    events: 主要用于指示是否为打开的文件绑定相应的事件。在有些操作系统上如删除文件等都会产生相应的事件
- 
    is_dir: 用于指示此文件是否是一个目录
- 
    is_file: 用于指示此文件是否是一个普通的文件
- 
    is_link: 用于指示此文件是否是一个链接文件
- 
    is_exec: 用于支持此文件是否是一个可执行文件
- 
    is_directio: 主要用于指示此文件是否已经开启了directio
2. ngx_cached_open_file_t数据结构
typedef struct ngx_cached_open_file_s  ngx_cached_open_file_t;
struct ngx_cached_open_file_s {
    ngx_rbtree_node_t        node;
    ngx_queue_t              queue;
    u_char                  *name;
    time_t                   created;
    time_t                   accessed;
    ngx_fd_t                 fd;
    ngx_file_uniq_t          uniq;
    time_t                   mtime;
    off_t                    size;
    ngx_err_t                err;
    uint32_t                 uses;
#if (NGX_HAVE_OPENAT)
    size_t                   disable_symlinks_from;
    unsigned                 disable_symlinks:2;
#endif
    unsigned                 count:24;
    unsigned                 close:1;
    unsigned                 use_event:1;
    unsigned                 is_dir:1;
    unsigned                 is_file:1;
    unsigned                 is_link:1;
    unsigned                 is_exec:1;
    unsigned                 is_directio:1;
    ngx_event_t             *event;
};本数据结构用于表示一个需要被cached的打开文件。下面我们简要介绍一下该数据结构:
- 
    node: 用于表示该ngx_cached_open_file_s结构在nginx静态缓存红黑树的哪一个节点上
- 
    queue: 用于表示该ngx_cached_open_file_s结构所在的队列
- 
    name: 用于表示该缓冲的文件的名称
- 
    created: 用于指明该文件是最先是在什么时候被放入静态缓存的
- 
    accessed: 用于指示该缓存文件最近访问时间
- 
    fd: 该缓存文件的文件句柄
- 
    uniq: 该缓存文件的inode节点号,用作唯一标识
- 
    mtime: 对该缓存文件的最近更新时间
- 
    uses: 当前该缓存文件自从被添加到缓存红黑树之后被使用到的次数
关于disable_symlinks_from与disable_symlinks字段,主要用于决定当打开文件的时候如何处理符号链接(symbolic links)。其中前一个字段用于指定从哪一个字段开始检查符号链接, 而后一个字段用于指定是否禁止符号链接。在objs/ngx_auto_config.h头文件中有如下定义:
#ifndef NGX_HAVE_OPENAT #define NGX_HAVE_OPENAT 1 #endif
- 
    count: 是文件的引用计数,表示现在文件被几个请求使用中
- 
    close: 用于指示是否需要真正被关闭
- 
    use_event: 指示是否使用event
- 
    is_dir: 用于指示此文件是否是一个目录
- 
    is_file: 用于指示此文件是否是一个普通的文件
- 
    is_link: 用于指示此文件是否是一个链接文件
- 
    is_exec: 用于支持此文件是否是一个可执行文件
- 
    is_directio: 主要用于指示此文件是否已经开启了directio
- 
    event: 该打开的缓存文件所关联的事件
注意:
结构体ngx_open_file_info_t与ngx_cached_open_file_t的不同主要表现在:前者用于描述一个打开 的缓存文件;而后者用于描述一个需要打开的缓冲文件,因此其要存储文件名等相关信息。
3. ngx_open_file_cache_t结构
typedef struct {
    ngx_rbtree_t             rbtree;
    ngx_rbtree_node_t        sentinel;
    ngx_queue_t              expire_queue;
    ngx_uint_t               current;
    ngx_uint_t               max;
    time_t                   inactive;
} ngx_open_file_cache_t;本结构用于缓存nginx中的静态文件。下面简要介绍一下本数据结构:
- 
    rbtree: 缓存文件红黑树的根,主要是为了方便查找
- 
    sentinel: 红黑树sentinel节点
- 
    expire_queue: 缓存文件过期队列
- 
    current: 当前缓存元素的个数
- 
    max: 最大的缓存个数
- 
    inactive: 缓存的过期时间
4. ngx_open_file_cache_cleanup_t结构
typedef struct {
    ngx_open_file_cache_t   *cache;
    ngx_cached_open_file_t  *file;
    ngx_uint_t               min_uses;
    ngx_log_t               *log;
} ngx_open_file_cache_cleanup_t;本数据结构指示当前要清除的缓存文件结构。下面我们简要介绍一下各字段的含义:
- 
    cache: 用于指示当前要cleanup的cache
- 
    file: 用于指示当前要cleanup的文件
- 
    min_uses: 低于此值则会cleanup
- 
    log: 所对应的日志
5. ngx_open_file_cache_event_t结构
typedef struct {
    /* ngx_connection_t stub to allow use c->fd as event ident */
    void                    *data;
    ngx_event_t             *read;
    ngx_event_t             *write;
    ngx_fd_t                 fd;
    ngx_cached_open_file_t  *file;
    ngx_open_file_cache_t   *cache;
} ngx_open_file_cache_event_t;本数据结构用于指示nginx静态缓存所对应的事件。下面简要介绍一下各字段的含义:
- 
    data: 可以是任何内容
- 
    read: 读事件
- 
    write: 写事件
- 
    fd: 所关联的文件句柄
- 
    file: 所关联的静态缓冲文件
- 
    cache: 所关联的缓存
6. 相关函数声明
//1) 初始化一个nginx静态文件缓存
ngx_open_file_cache_t *ngx_open_file_cache_init(ngx_pool_t *pool,
    ngx_uint_t max, time_t inactive);
//2) 打开一个缓存文件
ngx_int_t ngx_open_cached_file(ngx_open_file_cache_t *cache, ngx_str_t *name,
    ngx_open_file_info_t *of, ngx_pool_t *pool);
#endif /* _NGX_OPEN_FILE_CACHE_H_INCLUDED_ */
[参看]

