当前位置:首页>Linux>深入理解 Linux 文件锁:内核数据结构、死锁检测及 NFS 陷阱

深入理解 Linux 文件锁:内核数据结构、死锁检测及 NFS 陷阱

  • 2026-07-01 17:35:30
深入理解 Linux 文件锁:内核数据结构、死锁检测及 NFS 陷阱

有两个进程要同时写一个日志文件。进程 A 写 "[start] 处理订单 1001",进程 B 写 "[start] 处理订单 1002"。你期望的日志是:

[start] 处理订单 1001
[end]   处理订单 1001
[start] 处理订单 1002
[end]   处理订单 1002

但跑起来经常变成:

[start] 处理订单 1002
[start] 处理订单 1001
[end]   处理订单 1001
[end]   处理订单 1002

两个进程的写操作交叉了。不是 write() 线程不安全——write() 本身是原子的(在一次系统调用内),问题是两次 write() 之间,内核调度了另一个进程,它也调了 write(),内容就交叉了。

加文件锁,就是告诉内核:"这两行 write() 之间,别让别的进程插进来。"

最简单的用法

#include <fcntl.h>
#include <unistd.h>

int fd = open("/var/log/app.log", O_WRONLY | O_APPEND);

struct flock lock = {
    .l_type   = F_WRLCK,   // 写锁
    .l_whence = SEEK_SET,
    .l_start  = 0,
    .l_len    = 0,         // 0 表示锁整个文件
};

// 阻塞等锁
fcntl(fd, F_SETLKW, &lock);

// 临界区:这两行 write 不会被其他进程打断
write(fd, "[start] 处理订单 1001\n"29);
write(fd, "[end]   处理订单 1001\n"27);

// 解锁
lock.l_type = F_UNLCK;
fcntl(fd, F_SETLKW, &lock);

close(fd);

F_SETLKWWwait——拿不到锁就等。如果是 F_SETLK(不带 W),拿不到锁就立刻返回 -1,errnoEAGAIN

关于 l_len = 0 的精确含义:按照 POSIX 标准,l_len = 0 表示从 l_start 开始一直锁到文件的最大偏移量(即锁的范围是 [l_start, 文件末尾]),并且会随着文件增长而增长。如果文件后来追加了数据(比如 O_APPEND),新数据也会落在锁的范围内。

能锁整个文件,也能锁文件的一部分:

struct flock lock = {
    .l_type   = F_WRLCK,
    .l_whence = SEEK_SET,
    .l_start  = 4096,   // 从第 4096 字节开始
    .l_len    = 1024,   // 锁 1024 字节
};

这个"字节范围锁"是 POSIX 锁最有用的特性——多个进程可以同时锁同一个文件的不同区域,互不影响。

内核里锁是怎么存的

你调了 fcntl(F_SETLKW),内核拿到这个请求,第一步是找到这个文件对应的 inode。

每个文件的 inode 里有一个指针 i_flctx,指向一个 struct file_lock_context

// include/linux/fs.h
struct file_lock_context {
    spinlock_t        flc_lock;     // 保护下面三根链表的自旋锁
    struct list_head  flc_posix;    // POSIX 锁挂这里
    struct list_head  flc_flock;    // flock 锁挂这里
    struct list_head  flc_lease;    // lease 锁挂这里
};

你加的每把锁,内核分配一个 struct file_lock

struct file_lock {
    struct file_lock_context *fl_ctx; // 反向指针,指向所属的 context
    struct list_head   fl_list;       // 挂到 flc_posix 链表的节点
    struct hlist_node  fl_link;       // 挂到全局哈希表的节点
    fl_owner_t         fl_owner;       // 这把锁属于谁(POSIX:进程的文件表)
    unsigned int       fl_flags;       // FL_POSIX / FL_FLOCK / FL_OFD
    unsigned char      fl_type;        // F_RDLCK / F_WRLCK / F_UNLCK
    loff_t             fl_start;       // 锁定起始字节
    loff_t             fl_end;         // 锁定结束字节(OFFSET_MAX = 整个文件)
    struct list_head   fl_blocked;     // 被这把锁阻塞的锁,挂在这个链表上
    struct list_head   fl_blocked_requests; // 阻塞请求链表
};

图里的关系很清晰:一个 inode 对应一个 file_lock_context,context 里三根链表分别挂不同类型的锁,每把锁除了挂链表,还挂在全局的 file_lock_hashtable 上(用来做死锁检测,后面会讲)。

加锁时内核在做什么

fcntl() 系统调用开始,调用链是:

sys_fcntl() → do_fcntl() → fcntl_setlk() → locks_lock_inode() → posix_lock_inode()

核心逻辑全在 posix_lock_inode() 里,这个函数大概 200 行,但核心就三件事。

第一件:查冲突

遍历 flc_posix 链表,对每一把已存在的锁,判断"我要加的锁"和"这把已存在的锁"是否有冲突。

冲突的判断条件:

// fs/locks.c 里的简化逻辑
static int locks_conflict(struct file_lock *caller, struct file_lock *blocker)
{
    // 1. 范围不重叠 → 不冲突
    if (caller->fl_end < blocker->fl_start ||
        blocker->fl_end < caller->fl_start)
        return 0;

    // 2. 同一个 owner → 不冲突(自己加的锁,自己可以再碰)
    if (caller->fl_owner == blocker->fl_owner)
        return 0;

    // 3. 都是读锁 → 不冲突
    if (caller->fl_type == F_RDLCK && blocker->fl_type == F_RDLCK)
        return 0;

    // 4. 其他情况 → 冲突
    return 1;
}

注意第 2 条:同一个进程,先加了读锁,再加写锁,不会冲突。内核会帮你把读锁"升级"成写锁(实际上是在链表上再插一把写锁,范围重叠的读锁还在)。

第二件:没冲突 → 插入链表

把新锁按 fl_start 排序,插入 flc_posix 链表。fl_start 小的在前,相同的按 fl_owner 排。

插入后返回 0,fcntl() 返回 0,你的进程拿到锁,继续往下走。

第三件:有冲突 → 阻塞或返回错误

如果调用的是 F_SETLK(非阻塞),直接返回 -EAGAIN,你的 fcntl() 返回 -1,errno = EAGAIN

如果调用的是 F_SETLKW(阻塞),把你挂到冲突锁的 fl_blocked 链表上,然后调用 wait_event()

// 简化版
long __locks_lock_inode_wait(struct inode *inode, struct file_lock *fl)
{
    int error;
    might_sleep();
    for (;;) {
        error = posix_lock_inode(inode, fl, NULL);
        if (error != FILE_LOCK_DEFERRED)
            break;
        // 挂到等待队列,等锁释放时被唤醒
        wait_event(fl->fl_wait, !locks_is_locked(fl));
    }
    return error;
}

wait_event() 会让出 CPU,进程状态变成 TASK_INTERRUPTIBLE。锁持有者调用 F_UNLCK 释放锁时,内核遍历 fl_blocked 链表,调用 wake_up() 唤醒所有等这把锁的进程。被唤醒的进程重新调 posix_lock_inode() 尝试加锁。

解锁时内核在做什么

解锁(F_UNLCK)走的是同一个 posix_lock_inode(),但参数 fl_type = F_UNLCK

流程:

  1. flc_posix 链表里找到和 fl_owner + fl_start + fl_end 匹配的锁
  2. 从链表里移除
  3. 调用 locks_wake_up_blocks(),遍历这把锁的 fl_blocked 链表
  4. fl_blocked 链表上的每一把等待锁,调用 wake_up() 唤醒对应的进程

被唤醒的进程从 wait_event() 返回,重新进入 posix_lock_inode() 尝试加锁。这次大概率能成功(除非又被新来的锁挡住)。

进程崩溃了,锁怎么办

这是 POSIX 文件锁最巧妙的地方。

每个进程的 struct files_struct(文件描述符表)里有一个指针 file_lock_ctx。进程退出时,内核调用:

// fs/locks.c
void locks_remove_posix(struct files_struct *files, struct file *filp)
{
    struct file_lock_context *ctx;
    struct file_lock *fl, *tmp;

    ctx = file_inode(filp)->i_flctx;
    if (!ctx)
        return;

    spin_lock(&ctx->flc_lock);
    list_for_each_entry_safe(fl, tmp, &ctx->flc_posix, fl_list) {
        if (fl->fl_owner == files) {
            // 找到属于这个进程的锁
            fl->fl_type = F_UNLCK;
            posix_lock_inode(file_inode(filp), fl, NULL); // 解锁
            locks_delete_lock(fl); // 从链表移除
        }
    }
    spin_unlock(&ctx->flc_lock);
}

exit_files() → close_files() → locks_remove_posix(),这条路径在进程退出时一定会被调用——不管进程是正常退出、被 kill -9、还是 OOM killer 杀的。

所以你不用担心"进程崩了锁没释放"的问题。这是 POSIX 锁比 pthread mutex 更"崩溃安全"的地方——pthread mutex 需要 ROBUST 属性才能处理这种情况,POSIX 锁是内核自动处理的。

死锁检测

两个进程互相等对方的锁,就死锁了:

// 进程 A
lock_range(fd, 0100);     // 锁 [0, 100]
sleep(1);
lock_range(fd, 200100);   // 等进程 B 释放 [200, 300] → 死锁!

// 进程 B
lock_range(fd, 200100);   // 锁 [200, 300]
sleep(1);
lock_range(fd, 0100);     // 等进程 A 释放 [0, 100] → 死锁!

POSIX 标准要求 F_SETLKW 必须检测死锁。posix_lock_inode() 里调用 posix_locks_deadlock() 做检测:

// 简化版死锁检测
static int posix_locks_deadlock(struct file_lock *caller, struct file_lock *blocker)
{
    struct file_lock *fl = blocker;

    // 沿着阻塞链往上走
    do {
        if (fl->fl_owner == caller->fl_owner)
            return 1;   // 环路!死锁了
        fl = fl->fl_blocked_by;   // 我看谁的锁,继续往上走
    } while (fl);

    return 0;
}

检测到了,fcntl() 返回 -1,errno = EDEADLK

但检测有局限posix_locks_deadlock() 沿着 fl_blocked_by 指针链一直往上遍历,只要形成了环路(A 等 B,B 等 C,C 等 A,不管涉及几个进程、是否跨多个文件),内核都能检测到。

真正的局限是:如果你混用了不同类型的锁(POSIX 锁 + OFD 锁,或者 POSIX 锁 + flock()),它们的等待链表是分开的(flc_posixflc_flock 是独立的),内核无法检测这种混合死锁。

所以不要依赖死锁检测来做应用层的死锁避免——正确的做法是在应用层约定"所有进程按同样的顺序加锁",并且项目中统一使用同一种锁协议(要么全用 POSIX,要么全用 OFD,要么全用 flock()),从根源上避免死锁。

致命陷阱:flock() 与 fcntl() 互不兼容

Linux 里,POSIX 锁(fcntl)和 BSD 锁(flock)是两套完全独立的锁系统。它们在内核里挂在不同的链表上(flc_posix vs flc_flock),互相不可见。

这意味着:如果进程 A 用 fcntl() 加了一把写锁,进程 B 用 flock() 加锁,进程 B 会成功拿到锁,完全绕过进程 A 的锁

这是一个非常常见的并发 Bug——两个进程各自用了不同的锁协议,以为锁能保护临界区,结果根本没保护到。

/proc/locks 里能看到这种现象:

$ cat /proc/locks
1: POSIX  ADVISORY  WRITE 12345 08:03:174325 0 100
2: FLOCK  ADVISORY  WRITE 12346 08:03:174325 0 EOF

POSIXFLOCK 条目挂在不同的链路上,内核不会帮它们做冲突检测。

所以,在项目中必须统一锁协议:要么全用 fcntl()(POSIX 或 OFD),要么全用 flock(),不能混用。

还有一个补充:flock() 在 NFS 上通常只是本地伪锁(早期实现),不能跨越 NFS 服务器限制其他客户端。只有使用 fcntl() 的 POSIX 锁,才会通过 rpc.lockd 真正发往 NFS 服务器,实现多机互斥。

一个真实的坑:读锁饿死写锁

POSIX 锁允许同一段范围上有多把读锁。如果读者一直不停来,写锁可能永远拿不到。

// 进程 A(读者)
while (1) {
    lock_range(fd, 0100, F_RDLCK);
    read(fd, buf, 100);
    unlock_range(fd, 0100);
}

// 进程 B(写者)
lock_range(fd, 0100, F_WRLCK);   // 等 A 释放读锁

// 如果 A 的循环很快,每次只持有读锁很短时间,
// 但一直有读者进来 → B 永远拿不到写锁

Linux 内核没有"读锁优先"或"写锁优先"的策略,就是 FIFO——谁先被阻塞,谁先被唤醒。但读者可以叠加(因为多个读锁彼此不冲突),所以实际上读者更容易拿到锁。当写锁被阻塞时,后续如果再来一个读者,只要中间没有写锁插入,它就能立刻拿到读锁。

对策:如果写锁很重要,用 F_SETLK 非阻塞模式,拿不到就重试(带退避)。但注意:如果项目中其他地方用了 flock(),就不能用 fcntl(),见上一节的致命陷阱。

OFD 锁:解决 POSIX 锁的一个设计缺陷

POSIX 锁的 fl_owner 是进程的 files_struct。这意味着:同一个进程,不管多少个线程、多少个 fd,加的锁都算"同一个 owner"。

// 线程 1
int fd1 = open("/data/file", O_RDWR);
lock_range(fd1, 0100, F_WRLCK);

// 线程 2(同一个进程)
int fd2 = open("/data/file", O_RDWR); // 同一个文件,不同 fd
lock_range(fd2, 0100, F_WRLCK);     // 不冲突!因为同一个 owner

上面这个行为,有时候是你想要的(进程内部的锁共享),有时候不是(你想让不同线程独立加锁)。

Linux 3.15 引入了 OFD(Open File Description)锁,API 和 POSIX 锁几乎一样,但 fl_ownerstruct file *(打开文件描述):

struct flock lock = {
    .l_type   = F_WRLCK,
    .l_whence = SEEK_SET,
    .l_start  = 0,
    .l_len    = 100,
    .l_pid    = -1,   // -1 表示 OFD 锁
};
fcntl(fd, F_OFD_SETLK, &lock);

l_pid = -1 不是随便写的。传统 POSIX 锁依靠 l_pid 来标识属主(PID),但 OFD 锁的属主是文件描述符 struct file *。使用 fcntl()F_OFD_SETLK 命令时,内核会忽略 l_pid,将其设为 -1 是一种显式标记,表示不依赖 PID。

行为上的关键区别:

  • 如果两个线程都执行 open() 同一个文件,拿到两个不同的 fd,使用 OFD 锁可以互相独立加锁(互不冲突)——因为每个 open() 都分配一个新的 struct file *
  • 如果是同一个 fd(比如线程 A 把 fd 传给了线程 B),即使不同线程加 OFD 锁,它们依然是同一个 struct file * 属主,因此不会冲突

在多线程模型下,这个区别值得注意。

怎么观察系统里的文件锁

/proc/locks 导出了内核里所有 POSIX/flock/OFD 锁:

$ cat /proc/locks
1: POSIX  ADVISORY  WRITE 12345 08:03:174325 0 100
2: POSIX  ADVISORY  READ  12346 08:03:174325 4096 5120
3: FLOCK  ADVISORY  WRITE 12347 08:03:174325 0 EOF

每一行的含义:

字段 含义
1: 锁的序号
POSIX 锁类型(POSIX/FLOCK/OFDLCK)
ADVISORY 锁模式(advisory/mandatory,Linux 5.14 后 mandatory 已删除)
WRITE 锁的读写类型(READ/WRITE)
12345 持有锁的进程 PID
08:03:174325 设备号:inode 号
0 100 锁的范围(字节 0~100)
EOF 锁的范围(0 到文件末尾)

要追踪某个文件的锁,先查文件的 inode:

$ stat /var/log/app.log
  File: /var/log/app.log
Device: 803h/2051d   Inode: 174325

$ grep 174325 /proc/locks
1: POSIX  ADVISORY  WRITE 12345 08:03:174325 0 100

在 NFS 上用文件锁

NFS 的文件锁不是本地概念——锁的状态存在 NFS 服务器上。

Linux NFS 客户端用 rpc.lockd 和服务器通信。加锁时,客户端发 NLM_LOCK 请求到服务器;释放锁时,发 NLM_UNLOCK

问题来了:如果客户端崩溃了(网络断了、机器宕机),服务器上的锁不会自动释放——因为服务器没收到 NLM_UNLOCK

NFS 用 lease 机制解决这个问题:服务器给每个锁一个 lease 时间(默认 45 秒),客户端必须定期续租。客户端崩溃了,续租停止,45 秒后服务器自动释放锁。

但在这 45 秒内,其他客户端看不到这个文件被锁了(因为服务器还认为锁有效)。如果你的应用对锁的实时性要求很高,NFS 文件锁不是一个好选择。

本地文件系统(ext4、XFS、btrfs)没有这个问题——锁状态在内存里,进程退出时 locks_remove_posix() 立刻清理。

回到开头的问题

文章开头说的那个审计日志交叉问题,最终是怎么解决的?

最开始用了 fcntl() 范围锁,每次只锁要写的那个区域。后来发现审计日志的写入都是 append 模式(只在文件末尾追加),根本不需要范围锁——直接用 flock() 锁整个文件就够了,而且 flock() 的语义更简单,不会因为范围计算错误导致锁冲突。

但有一个前提:项目中所有进程都必须用 flock(),不能有的用 fcntl() 有的用 flock(),否则就会出现前面说的"致命陷阱"——锁根本没生效,两个进程以为各自锁住了,实际上谁也没锁住。

另一个教训:如果你的应用是多线程的,用 POSIX 锁要小心——同一进程的不同线程加的锁共享 owner,可能导致你以为"线程 A 的锁不会和线程 B 的锁冲突",结果两个线程同时写,数据还是乱了。这种场景用 OFD 锁(F_OFD_SETLK)更合适,每个 open() 的文件描述符有独立的锁 owner。

文件锁不是万能的。如果你的并发场景很复杂(比如多个进程同时写同一个文件的随机位置),文件锁的粒度可能不够——这时候应该考虑用数据库(SQLite 支持并发读、串行写,而且有 WAL 模式),或者把数据拆成多个文件,每个文件只由一个进程写。

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 12:01:10 HTTP/2.0 GET : https://f.mffb.com.cn/a/501283.html
  2. 运行时间 : 0.252501s [ 吞吐率:3.96req/s ] 内存消耗:4,661.71kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=6b68f54802512a3034c6ed7a15c69108
  1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
  2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
  3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
  4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
  5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
  6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
  7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
  8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
  9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
  10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
  11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
  12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
  13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
  14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
  15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
  16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
  17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
  18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
  19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
  20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
  21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
  22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
  23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
  24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
  25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
  26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
  27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
  28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
  29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
  30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
  31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
  32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
  33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
  34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
  35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
  36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
  37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
  38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
  39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
  40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
  41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
  42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
  43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
  44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
  45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
  46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
  47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
  48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
  49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
  50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
  51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
  52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
  53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
  54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
  55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
  56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
  57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
  58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
  59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
  60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
  61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
  62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
  63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
  64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
  65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
  66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
  67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
  68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
  69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
  70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
  71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
  72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
  73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
  74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
  75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
  76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
  77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
  78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
  79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
  80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
  81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
  82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
  83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
  84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
  85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
  86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
  87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
  88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
  89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
  90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
  91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
  92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
  93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
  94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
  95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
  96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
  97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
  98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
  99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
  100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
  101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
  102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
  103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
  104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
  105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
  106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
  107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
  108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
  109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
  110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
  111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
  112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
  113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
  114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
  115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
  116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
  117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
  118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
  119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
  120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
  121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
  122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
  123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
  124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
  125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
  126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
  127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
  128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
  129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
  130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
  131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
  132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
  133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
  134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
  135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
  136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
  137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
  138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
  139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
  140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
  1. CONNECT:[ UseTime:0.000506s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000870s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.005840s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.003651s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000790s ]
  6. SELECT * FROM `set` [ RunTime:0.000273s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000784s ]
  8. SELECT * FROM `article` WHERE `id` = 501283 LIMIT 1 [ RunTime:0.017358s ]
  9. UPDATE `article` SET `lasttime` = 1783051270 WHERE `id` = 501283 [ RunTime:0.010639s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.006803s ]
  11. SELECT * FROM `article` WHERE `id` < 501283 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.002438s ]
  12. SELECT * FROM `article` WHERE `id` > 501283 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.012106s ]
  13. SELECT * FROM `article` WHERE `id` < 501283 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.046612s ]
  14. SELECT * FROM `article` WHERE `id` < 501283 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.033831s ]
  15. SELECT * FROM `article` WHERE `id` < 501283 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.031112s ]
0.254091s