[转] 小议同步IO :fsync与fdatasync

原文链接:

http://www.cnblogs.com/promise6522/archive/2012/05/27/2520028.html

写的很棒也很详细. 摘要:

fsync需要sync文件修改和 metadata; fdatasync则只在必要的时候才sync metadata, 可以节省一次文件sync操作.

berkeley db通过预先设置 log文件大小, 从而保证fdatasync不会去sync metadata.

这里简单的列一下对应的bdb 代码:

os/os_fsync.c:

__os_fsync()
    if (DB_GLOBAL(j_fsync) != NULL)
        ret = DB_GLOBAL(j_fsync)(fhp->fd); //用户自定义sync函数
    else {
#if defined(F_FULLFSYNC) // MAC OS X
        RETRY_CHK((fcntl(fhp->fd, F_FULLFSYNC, 0)), ret);
        if (ret == ENOTSUP)
            RETRY_CHK((fsync(fhp->fd)), ret);
#elif defined(HAVE_QNX) // QNX实时OS
        ret = __qnx_fsync(fhp);
#elif defined(HAVE_FDATASYNC) // 优先使用fdatasync
        RETRY_CHK((fdatasync(fhp->fd)), ret);
#else
        RETRY_CHK((fsync(fhp->fd)), ret);
#endif
    }

log/log_put.c:

__log_write()
#ifdef HAVE_FILESYSTEM_NOTZERO
    if (lp->w_off == 0 && !__os_fs_notzero()) {
#else
    if (lp->w_off == 0) { // lp->w_off为当前log文件的write offset
#endif // lp->w_off为0, 标识第一次写 此log文件
        (void)__db_file_extend(env, dblp->lfhp, lp->log_size);
        if (F_ISSET(dblp, DBLOG_ZERO))
            (void)__db_zero_extend(env, dblp->lfhp,
                 0, lp->log_size/lp->buffer_size, lp->buffer_size);
    }

env/env_file.c:

__db_file_extend() // size为log文件大小, 写文件的最后一个byte为0
    buf = '\0';
    pages = (db_pgno_t)((size - sizeof(buf)) / MEGABYTE);
    relative = (u_int32_t)((size - sizeof(buf)) % MEGABYTE);
    if ((ret = __os_seek(env, fhp, pages, MEGABYTE, relative)) == 0)
        ret = __os_write(env, fhp, &buf, sizeof(buf), &nw);

 

posted @ 2016-02-29 11:35  brayden  阅读(605)  评论(0编辑  收藏  举报