当前位置:首页>Linux>谈一谈Linux设备驱动中的各种并发控制

谈一谈Linux设备驱动中的各种并发控制

  • 2026-06-28 16:54:10
谈一谈Linux设备驱动中的各种并发控制
在为操作系统编写驱动设备时,因为涉及到中断、多任务和多处理器SMP的处理,所以内核提供了诸如原子操作、自旋锁、信号量、互斥体、读写锁、完成量等几种并发控制机制,对公用资源进行保护。本文将分别予以阐述。首先了解几个基本概念。
  • 并发:多个执行单元(进程、线程、SMP对称多处理器)同时被执行,并发的这种情况就有可能会导致竞态(同时操作临界区,访问临界资源)。

  • 临界区:能够被多个执行单元同时执行的代码区。

  • 临界资源:能够被多个执行单元同时访问操作的资源(软件资源和硬件资源)

  • 导致竞态的具体原因

    • 进程和抢占它的进程之间会有可能产生竞态;

    • 进程和中断之间有可能产生竞态;

    • 对称多处理器

  • 解决竞态的方法

    • 同步:强调的是顺序性

    • 互斥:强调的是排他性

1、原子变量

  • 原子变量就是,在对其进行操作时不会被其它任务或中断打断,最简单的原子操作就是一条条的汇编指令(不包括一些伪指令,伪指令会被汇编器解释成多条汇编指令)。

  • 原子操作需要硬件的支持,因此是架构相关的,其API和原子类型的定义在内核include/asm/atomic.h文件中,都是用汇编语言实现的。它的优点是使用简单,但缺点是功能单一,只能做计数操作,保护的东西太少。

  • 在Linux中,原子变量对应的数据结构为 atomic_t,其的定义如下:

typedef struct {    volatile int counter;}atomic_t;
  • 原子变量本质上是一个整型变量,且因为volatile的修饰,编译器不会对原子变量的值进行访问优化,以确保对它的访问都是对真实内存地址的访问,而非缓存(寄存器)。

在Linux中定义了两种原子变量操作方法,一是原子整型操作,二是原子位操作

1.1 原子整型操作

  • 定义并初始化atomic_t变量atomic_t counter = ATOMIC_INIT(0); //定义并初始化原子变量counter为0.

  • 设置atomic_t变量的值atomic_set(&counter, 2); //设置原子变量counter的值为2.

  • 读atomic_t变量的值var = atomic_read(&counter); // 读原子变量counter的值到var中。

  • 原子变量的加减法atomic_add(2, &counter); //将原子变量counter加2.atomic_sub(2, &counter); //将原子变量counter减2.

  • 原子变量的自增/自减atomic_inc(&counter); //将原子变量counter自增1atomic_dec(&counter); //将原子变量counter自减1

  • 原子变量的加减测试atomic_inc_and_test(&counter); //将原子变量counter自增1,若结果为0返回真,否则返回假。atomic_dec_and_test(&counter); //将原子变量counter自减1,若结果为0返回真,否则返回假。

  • 原子变量的加减返回

    atomic_sub_return(i, &counter); //将原子变量counter减i,并返回减去i后的counter。

    atomic_add_return(i,&counter); //将原子变量counter加i,并返回加上i后的counter。

1.2 原子位操作

函数原型:static inline void set_bit(int nr, volatile unsigned long *addr)

  • 设置atomic_t变量的某一位set_bit(nr, &addr); //设置原子变量addr的第nr位.

  • 清除atomic_t变量的某一位clear_bit(nr, &addr); //清除原子变量addr的第nr位.

  • 取反atomic_t变量的某一位change_bit(nr, &addr); //取反原子变量addr的第nr位.

  • 测试及设置atomic_t变量的某一位test_and_set_bit(nr, &addr); //返回原子变量addr的第nr位,然后设置该位.

  • 测试及清除atomic_t变量的某一位test_and_clear_bit(nr, &addr); //返回原子变量addr的第nr位,然后清除该位.

  • 测试及取反atomic_t变量的某一位test_and_change_bit(nr, &addr); //返回原子变量addr的第nr位,然后取反该位.

  • 在linux中还定义了一组与原子位操作函数功能相同的函数,其函数名是在原子位操作函数名前加两个下划线。区别在于他们不会保证是一个原子操作。

2、自旋锁

自旋锁是一种阻塞结构(忙等待),这样会对系统的性能有所影响,所以不应该长时间持有,他是一种适合短时间锁定的轻量级的加锁机制,另外,自旋锁不能递归使用。自旋锁的类型也是一个结构体,即struct spinlock_t。下面对它的操作函数进行介绍:

2.1 定义和初始化自旋锁

  • 定义时初始化spinlock_t lock = SPIN_LOCK_UNLOCKED; //大写字母表示的是一个初始化宏

  • 动态初始化

spinlock_t  lock;
spin_lock_init(lock);
  • 锁定自旋锁spin_lock(lock); //这个宏一直等待,直到获得自旋锁

  • 释放自旋锁spin_unlock(lock); //这个宏立刻释放自旋锁

  • 自旋锁的使用举例在驱动程序中,有些设备只允许打开一次,那么就需要一个自旋锁保护表示设备打开次数的count变量。如果不对count变量进行保护,当该设备被频繁打开的话,容易出现错误的count计数。

int count = 0;spinlock_t lock;intxxx_init(void){    ...        spin_lock_init(&lock);        ...}/* 设备打开函数 */intxxx_open(structinode*inode, structfile*filp){    ...    spin_lock(&lock);    /* 临界代码 */    if(count)    /*已经被其它程序打开过了*/    {        spin_unlock(&lock);        return-EBUSY;    }    count++;    spin_unlock(&lock);    ...}/* 设备释放函数 */intxxx_open(struct inode *inode, structfile *filp){    ...    spin_lock(&lock);    count--;    spin_unlock(&lock);    ...}

3、信号量

  • Linux中实现了两种信号量,一种用于内核程序中,另一种应用于应用程序中,本文仅介绍内核中的信号量

  • 信号量与自旋锁的不同点在于:当一个进程或线程试图去获取一个已经被锁定的信号量时,它不会向自旋锁一样在原地忙等待,而是将自身加入到系统的一个等待队列中去睡眠,直到拥有信号量的进程释放该信号量后,才会被系统唤醒并再次尝试获取该信号量。此处也提醒我们,只有能够睡眠的进程(函数)才能使用信号量,像中断处理函数和可延迟函数那样需要立刻执行的函数是不能使用信号量的。

  • 信号量适用于锁会被长时间持有的情况;相反,当锁只需要被短时间持有时,因为睡眠、维护等待队列以及唤醒所花费的开销可能比锁占用的全部时间表还要长,再使用信号量就不合适了。此时可能采用自旋锁更合适!

3.1 信号量的定义

在不同的实现中,信号量的实现可能不同。在Linux中其定义如下:

struct semaphore {    spinlock_t lock;    //用来对count起保护作用    unsigned int count;    struct list_head wait_list;};
  • 关于count:等于0时,表示信号量正在被一个进程使用,现在不可以获取,且等待队列wait_list中没有进程在等待信号量;小于0时,代表wait_list中还有-count个进程在等待信号量;大于0时,表示可以获取该信号量。count初始化的值代表该信号量可以同时被多少进程持有。

  • 关于wait_list:它是一个链表,将所有等待该信号量的正在睡眠的进程组成一个链表结构。 

3.2 信号量的原理

  • 一个任务要想访问共享资源,首先必须得到信号量,获取信号量的操作将把信号量的值减1

    • 若当前信号量的值为负数,表明无法获得信号量,该任务必须挂起在该信号量的等待队列等待该信号量可用;

    • 若当前信号量的值为非负数,表示能获得信号量,因而能即时访问被该信号量保护的共享资源。

  • 当任务访问完被信号量保护的共享资源后,必须释放信号量,释放信号量通过把信号量的值加1实现

    • 如果信号量的值为非正数,表明有任务等待当前信号量,因此他也唤醒所有等待该信号量的任务。

3.3 信号量的接口

3.3.1 定义

  • 内核信号量是struct semaphore类型的对象,在内核源码中位于include\linux\semaphore.h文件

struct semaphore{    raw_spinlock_t lock;        unsigned int count;        struct list_head wait_list;}
    • 大于0,资源空闲;

    • 等于0,资源忙,但没有进程等待这个保护的资源;

    • 小于0,资源不可用,并至少有一个进程等待资源

    • count:相当于信号量的值,

    • wait_list:内核链表,当前未获得信号量的任务会被注册到该等待链表中

3.3.2 初始化

  • 静态定义并初始化一个信号量DEFINE_SEMAPHORE(name);——定义一个信号量name,并赋初值1

  • 动态初始化一个信号量

  • sema_init(&sema, val);——初始化信号量sema为val

当sema中的count为1时,我们称为互斥体(同一时间仅有一个进程持有该信号量),他有专门的宏来进行初始化:init_MUTEX(struct semaphore *sema); //初始化sema信号量为1。init_MUTEX_LOCKED(struct semaphore *sema);//初始化sema信号量为0。

3.3.3 获取信号量

  • void down(struct semaphore * sem);

    • 该函数将把sem的值减1,如果信号量sem的值非负,就直接返回,否则调用者将被挂起,直到别的任务释放该信号量才能继续运行,故不能用于中断上下文中(包括IRQ上下文和softirq上下文);

  • int down_interruptible(struct semaphore * sem);

    • 该函数功能和down类似,不同之处为,down不会被信号(signal)打断,但down_interruptible能被信号打断,因此该函数用返回值来区分是正常返回还是被信号中断(如果返回0,表示获得信号量正常返回,如果被信号打断,返回-EINTR)。

    • 使用可被中断的信号量版本的意思是,万一出现了semaphore的死锁,还有机会用ctrl+c发出软中断,让等待这个内核驱动返回的用户态进程退出。而不是把整个系统都锁住了。在休眠时,能被中断信号终止,这个进程是可以接受中断信号的!

  • int down_trylock(struct semaphore * sem);

    • 该函数试着获得信号量sem,如果能够即时获得,他就获得该信号量并返回0,否则,表示不能获得信号量sem,返回值为非0值。因此,他不会导致调用者睡眠,能在中断上下文使用。

  • int down_killable(struct semaphore *sem);

  • int down_timeout(struct semaphore *sem, long jiffies);

  • int down_timeout_interruptible(struct semaphore *sem, long jiffies);

3.3.4 释放信号量

  • void up(struct semaphore * sem);

  • 该函数释放信号量sem,即把sem的值加1,如果sem的值为非正数,表明有任务等待该信号量,因此唤醒这些等待者。

3.3.5 信号量的使用场景

  • 信号量用于保护临界资源

//定义一个信号量struct semaphoresema;//初始化一个二值信号量intxxx_init(void){    ...    init_MUTEX(&sema);    ...}intxxx_open(struct inode *inode, structfile* filp){    ...        //获取一个信号量    if(down_interruptible(&sema))        {                return -ERESATRTSYS;        }    ...    return0;}intxxx_release(struct inode *inode, structfile *filp){    ...    //获取一个信号量    up(&sema);    ...    return0;}
  • 信号量用于同步当信号量被初始化为0时,可以用来保证两个进程的执行顺序,如下图所示:

  • 总结:信号了用于在多个进程之间互斥,但信号量的执行会引起进程的睡眠,而睡眠需要进程上下文的切换,是很耗费时间的。所以,只有在一个进程对其保护的资源占用时间要比进程切换的时间长很多时,才划算!

4、互斥体

  • mutex用于互斥操作。信号量的count初始化为1,down()/up()也可以实现类似mutex的作用。mutex的语义相对于信号量要简单轻便一些,在锁争用激烈的测试场景下,mutex比信号量执行速度更快,可扩展性更好,另外mutex数据结构的定义比信号量小。所以,除非mutex的某个约束妨碍你使用,否则相比信号量要优先使用mutex。

  • mutex的使用注意事项

    • 同一时刻只有一个线程可以持有mutex。

    • 只有锁持有者可以解锁。也就是说不能在进程间同步(A进程中持有mutex,而在B进程中释放mutex),也不能在内核空间和用户空间进行同步,所以一般是在同一上下文中上锁和解锁。

    • 不允许递归地加锁和解锁(不能重复持有和重复解锁),也不能被重新初始化,其所使用的内存区域更是不能被释放的。

    • 当进程持有mutex时,进程不可以退出

    • mutex必须使用官方API来初始化,而不能手动赋值、使用memset和重复初始化。

    • mutex可以睡眠,所以不允许用在中断上下文中,例如tasklet、定时器等。

4.1互斥体的接口

  • 初始化

    • 静态初始化——DEFINE_MUTEX(name);DEFINE_MUTEX_LOCKED(name);

    • 动态初始化——mutex_init(&mutex);

  • 互斥锁的申请和释放

    • mutex_lock(struct mutex*)——为指定的mutex上锁,如果不可用则进入不可中断睡眠;

    • mutex_unlock(struct mutex*)——为指定的mutex解锁;

    • mutex_lock_interruptible(struct mutex*)——为指定的mutex上锁,如果不可用则进入可中断睡眠,如果在睡眠时被信号打断,则返回_EINIR;

    • mutex_unlock_interruptible(struct mutex*)——为指定的mutex解锁;

    • mutex_trylock(struct mutex*)——非阻塞的获取mutex锁,成功返回1,否则返回0;

    • mutex_is_lock(struct mutex*)——判断锁是否可用,不可用返回1,否则返回0。

  • 使用示例

struct mutex mutex;    //定义mutex_init(&mutex);    //初始化mutex_lock(&mutex);    //加锁...                    //临界区mutex_unlock(&mutex);  //解锁

    4.2互斥体和自旋锁的使用比较

    • 在中断上下文中只能使用自旋锁,而在任务可能睡眠时只能使用互斥体或信号量。

    • 短期锁定时使用自旋锁,长期锁定使用互斥体或信号量;

    • 多进程同步使用信号量。

    5、读写自旋锁

    • 因为自旋锁毫无线程并发性可言,使得多处理器系统的性能受到限制。通过观察线程在临界区的访问行为,发现有些线程只是简单地读取信息,并不修改任何东西,所以即使它们同时进入临界区也不会有任何危险,反而能大大提高系统的并发性。这种将线程区分为读者和写者、多个读者允许同时访问共享资源、申请线程在等待期内依然使用忙等待方式的锁,我们称之为读写自旋锁(Reader-Writer Spinlock)。

    • 读/写自旋锁是在保护SMP体系下的共享数据结构而引入的,只要没有对数据结构进行修改,读/写自旋锁就允许多个线程同时读同一数据结构。但如果一个线程想对这个结构进行写操作,那么它必须首先获取读/写锁的写锁,写锁授权独占访问这个资源。

    5.1读写自旋锁的特点

    • 互斥:任意时刻读者和写者不能同时访问共享资源(即获得锁),即任意时刻只能有至多一个写者访问共享资源。

    • 读者并发:在满足“互斥”的前提下,多个读者可以同时访问共享资源。

    • 无死锁(Freedom from Deadlock):如果线程 A 试图获取锁,那么某个线程必将获得锁,这个线程可能是 A 自己;如果线程 A 试图但是却永远没有获得锁,那么某个或某些线程必定无限次地获得锁。意思就是,从全局来看一定会有申请线程获得锁,但对于某个或某些申请线程而言,它们可能永远无法获得锁,这种现象也称为饥饿(Starvation)。一种原因源于计算机体系结构的特点,一种原因源于设计策略(读者优先、写者优先、)。

    • 忙等待:申请锁的线程必须不断地查询是否发生退出等待的事件,而不能进入睡眠状态。

    5.2读写锁的接口

    • 初始化

      • 动态初始化——rwlock_init (&rw_lock);

      • 静态初始化——DEFINE_RWLOCK(rwlock);

    • 读临界区

      • read_lock(rw_lock);

      • read_lock_irqsave(rw_lock,flags);= read_lock() + local_irq_save()

      • read_lock_irq(rw_lock); = read_lock() + local_irq_disable()

      • read_lock_bh(rw_lock);= read_lock() + local_bh_disable()

      • read_unlock(rw_lock);

      • read_unlock_irqstore(rw_lock,flags);read_unlock()+ local_irq_restore()

      • read_unlock_irq(rw_lock);= read_unlock()+ local_irq_enable()

      • read_unlock_bh(rw_lock);= read_unlock()+ local_bh_enable()

    • 写临界区

      • write_lock(rw_lock);

      • write_lock_irqsave(rw_lock, flags);= write_lock() + local_irq_save()

      • write_lock_irq(rw_lock);= write_lock() + local_irq_disable()

      • write_lock_bh(rw_lock);= write_lock() + local_bh_disable()

      • write_trylock(rw_lock);

      • write_unlock(rw_lock);

      • write_unlock_irqsave(rw_lock, flags);= write_unlock()+ local_irq_restore()

      • write_unlock_irq(rw_lock);= write_unlock()+ local_irq_enable()

      • write_unlock_bh(rw_lock);= write_unlock()+ local_bh_enable()

    可通过如下函数禁用所有处理器上的中断:

    disable_irq(void);——在2.6内核之后才有这个函数,之前是没有方法全局禁用整个系统的所有中断。

    可通过如下函数禁用当前处理器上的中断:

    local_irq_disable(void);—— 仅仅是禁用当前CPU的中断;

    local_irq_save(unsigned long flags);——把当前中断状态保存到flags中,然后禁用当前处理器上的中断;

    可通过如下函数打开当前处理器上的中断:

    void local_irq_enable(void);——将local_irq_save保存的flags状态值恢复后,打开中断。

    void local_irq_restore(unsigned long flags);——无条件打开中断。

    可通过如下函数判断当前进程是否在硬件中断上下文中:

    in_irq(void);

    可通过如下函数判断当前进程是否处于中断上下文(包括中断底半部和硬件中断处理过程):

    in_interrupt(void);

    5.3读写锁的使用示例

    rwlock_t lock/* 定义 rwlock */rwlock_init(&lock); /* 初始化 rwlock *//* 读时获取锁 */read_lock(&lock);... /* 临界资源 */read_unlock(&lock);/* 写时获取锁 */write_lock_irqsave(&lock, flags);... /* 临界资源 */    write_unlock_irqrestore(&lock, flags);
    • 更多关于读写锁的内核实现细节参考读写自旋锁详解DarkMagician_Potter的博客-CSDN博客读写自旋锁

    6、完成量

    上节中讲的进程间的同步(一个线程等待另一个线程完成某操作后才能继续执行),在Linux中有专门的机制(虽然使用信号量也可以实现)叫完成量,即一个线程发送一个信号通知另一个线程开始完成某个任务。

    6.1完成量的定义

    struct completion{    unsigned int done;    wait_queue_head_t wait;};

    done:维护一个计数,其被初始化为1。当done为0时,会将拥有完成量的线程置于等待状态;当其值大于1时,表示等待完成量的函数可以立刻执行!wait:存放所有等待该完成量的正在睡眠的进程组成的链表

    6.2完成量的接口

    • 定义一个完成量struct completion com;

    • 初始化一个完成量init_completion(&com);//将done设置为0

    • 定义并初始化一个完成量DECLARE_COMPLETION(com);

    • 等待完成量wait_for_completion(&com);//线程将一直等待,且不会被中断打断。

    • 释放完成量complete(&com);//只唤醒一个等待的进程complete_all(&com);//唤醒所有等待的进程

    • 完成量的使用

    struct completioncom;intxxx_init(void){    ...    init_completion(&com);    ...}intxxx_A(void){    ...    /* 代码1 */    wait_for_completion(&com);    /* 代码3 */    return0;}intxxx_B(void){    ...    /* 代码2 */    complete(&com);    ...    return0;}

    初始化后com中的done值为0,此时若xxx_A先执行,则当执行完成代码1 后便会进入睡眠,等待进程xxx_B执行完代码2,并释放完成量(使done加1),此时系统会唤醒处于完成量com中的等待队列里正在睡觉的进程A,然后进程A继续执行完代码3.

    最新文章

    随机文章

    基本 文件 流程 错误 SQL 调试
    1. 请求信息 : 2026-07-03 09:45:09 HTTP/2.0 GET : https://f.mffb.com.cn/a/487175.html
    2. 运行时间 : 0.230473s [ 吞吐率:4.34req/s ] 内存消耗:4,495.18kb 文件加载:140
    3. 缓存信息 : 0 reads,0 writes
    4. 会话信息 : SESSION_ID=0845c9fd54112f433ced1f8a472217cc
    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.000494s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
    2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.000537s ]
    3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.006618s ]
    4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.009568s ]
    5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.000589s ]
    6. SELECT * FROM `set` [ RunTime:0.014353s ]
    7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.000720s ]
    8. SELECT * FROM `article` WHERE `id` = 487175 LIMIT 1 [ RunTime:0.016167s ]
    9. UPDATE `article` SET `lasttime` = 1783043109 WHERE `id` = 487175 [ RunTime:0.029022s ]
    10. SELECT * FROM `fenlei` WHERE `id` = 67 LIMIT 1 [ RunTime:0.000504s ]
    11. SELECT * FROM `article` WHERE `id` < 487175 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.009161s ]
    12. SELECT * FROM `article` WHERE `id` > 487175 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.020378s ]
    13. SELECT * FROM `article` WHERE `id` < 487175 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.006112s ]
    14. SELECT * FROM `article` WHERE `id` < 487175 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.029233s ]
    15. SELECT * FROM `article` WHERE `id` < 487175 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.002426s ]
    0.232074s