开发nginx模块时对普通文件的操作

在开发nginx http模块时,为了实现文件操作并确保资源回收,可以利用nginx提供的内建文件函数,如ngx_open_file(),结合资源管理池在请求结束时自动回收资源。这种方法既符合nginx的异步回调风格,又能避免文件句柄未关闭的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

序言

开发nginx http模块时,有时候需要从指定的文件读取信息,这个时候,如果是新手,则肯定用操作系统文件系统函数来操作文件,比如用fopen打开文件,用fseek,fread等读取文件信息,最后用fclose关闭文件。这样操作文件也是可以工作的,但是如果代码中间有return的时候,我们需要确保打开的文件关闭,否则会造成文件句柄没有关闭,资源浪费,而且这种方式和nginx的异步回调风格有点不符。所以我们可以利用nginx提供的文件函数来操作文件,而在请求结束的时候一并关闭打开的文件。

使用nginx自带的机制操作文件

参考fopen函数,那么肯定需要用到nginx的file结构体(src/core/ngx_file.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_HAVE_FILE_AIO)
    ngx_event_aio_t           *aio;
#endif

    unsigned                   valid_info:1;
    unsigned                   directio:1;
};

通常我们用到的字段有,fd,name,info, log。其他的字段nginx框架会自动赋值并使用。
nginx 定义了一个宏用来打开文件(src/os/unix/ngx_files.h)

 #define ngx_open_file(name, mode, create, access)                            \
    open((const char *) name, mode|create|O_BINARY, access)

另外,nginx的资源管理池会在请求结束时,一并回收所有资源。结果如下

struct ngx_pool_cleanup_s {
    ngx_pool_cleanup_pt   handler;
    void                 *data;
    ngx_pool_cleanup_t   *next;
};

其中data域存放要回收资源的关键信息,handler是回收资源的函数,next是只想下一个带回收的资源。
因为我们要回收的资源是文件,所以nginx定义要回收的文件资源结构为

typedef struct {
    ngx_fd_t              fd;
    u_char               *name;
    ngx_log_t            *log;
} ngx_pool_cleanup_file_t;

可以看到有fd这一项。顺便也可以看看nginx自带的关闭文件的回调函数

void
ngx_pool_cleanup_file(void *data)
{
    ngx_pool_cleanup_file_t  *c = data;

    ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, c->log, 0, "file cleanup: fd:%d",
                   c->fd);

    if (ngx_close_file(c->fd) == NGX_FILE_ERROR) {
        ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno,
                      ngx_close_file_n " \"%s\" failed", c->name);
    }
}

有了以上的分析,那么我们操作文件的代码就是如下了

    ngx_pool_cleanup_t             *cln;
    ngx_pool_cleanup_file_t        *clfn;
    ngx_file_t                     *file;
    file = ngx_palloc(r->pool, sizeof(ngx_file_t));
    if (file == NULL ) {
        return NGX_ERROR;
    }

    char *realfilename = "/path/to/your/input.info";
    file->fd = ngx_open_file(realfilename, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
    file->name.len = ngx_strlen(realfilename);
    file->name.data = realfilename;
    file->log = r->pool->log;

    cln = ngx_pool_cleanup_add(r->pool, sizeof(ngx_pool_cleanup_file_t));
    if (cln == NULL) {
        return NGX_ERROR;
    }
    clfn = cln->data;//此处要特别注意,让clfn指针指向上面ngx_pool_cleanup_add函数内分配的存放ngx_pool_cleanup_file_t的空间。
    clfn->fd = file->fd;
    clfn->name = realfilename;
    clfn->log = r->pool->log;
    cln->handler = ngx_pool_cleanup_file;

经过上面短短的代码,文件操作就完成了,重要的是,不管你的代码,由于什么原因中途return,也不用担心文件句柄没有关闭。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值