Linux内核API seqlock_init

seqlock_init():初始化顺序锁x,同时对顺序锁的顺序号进行初始化。

seqlock_init文件包含

#include <linux/seqlock.h>

seqlock_init宏定义:

在内核源码中的位置:linux-3.19.3/include/linux/seqlock.h

宏定义格式:

#define seqlock_init(x)                          \
    do {                                         \
        seqcount_init(&(x)->seqcount);           \
        spin_lock_init(&(x)->lock);              \
    } while (0)

seqlock_init输入参数说明

  • seqlock_init()的参数x表示指向顺序锁结构体的指针。顺序锁结构体seqlock_t在内核文件linux-3.19.3/include/linux/seqlock.h中定义:
typedef struct {
    struct seqcount seqcount;
    spinlock_t lock;
} seqlock_t;

结构体中包括以下两个字段:

  • seqcount:用来记录申请顺序锁的顺序号,定义见linux-3.19.3/include/linux/seqlock.h,格式如下:
typedef struct seqcount {
    unsigned sequence;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
    struct lockdep_map dep_map;
#endif
} seqcount_t;
  • lock:自旋锁结构体。

顺序锁是对自旋锁的一种优化,对于顺序锁,读者不会被写者阻塞,也即是说,读者可以在写者对被顺序锁保护的共享资源进行写操作时继续读操作,而不必自旋在那里等待写者完成写操作,写者也不必等待所有读者完成读操作后再执行写操作。但是,写者与写者之间仍然是互斥的,即如果有写者在进行写操作,其他写者必须自旋在那里,直到该写者释放了顺序锁。

seqlock_init返回参数说明

  • 该宏无返回值。

seqlock_init实例解析

编写测试文件:seqlock_init.c

头文件及全局变量声明如下:

#include <linux/seqlock.h>
#include <linux/init.h>
#include <linux/module.h>
MODULE_LICENSE("GPL");
static int __init seqlock_init_init(void);
static void __exit seqlock_init_exit(void);

seqlock_t seqlock ;

模块初始化函数:

int __init seqlock_init_init(void)
{
    seqlock_init( &seqlock );       //初始化顺序锁
    printk("after seqlock_init, sequence: %d\n\n", seqlock.seqcount.sequence);

    write_seqlock( &seqlock );      //写者第一次申请顺序锁
    printk("first write_seqlock, sequence: %d\n\n", seqlock.seqcount.sequence);

    write_sequnlock( &seqlock );    //写者第一次释放顺序锁
    printk("first write_sequnlock, sequence: %d\n\n", seqlock.seqcount.sequence);

    write_seqlock( &seqlock );      //写者第二次申请顺序锁
    printk("second write_seqlock, sequence: %d\n\n", seqlock.seqcount.sequence);

    write_sequnlock( &seqlock );    //写者第二次申请顺序锁
    printk("second write_sequnlock, sequence: %d\n\n", seqlock.seqcount.sequence);
    return 0;
}

模块退出函数:

void __exit seqlock_init_exit(void)
{
    printk("exit! \n");
}

模块初始化及退出函数调用:

module_init(seqlock_init_init);
module_exit(seqlock_init_exit);

实例运行结果及分析:

首先编译模块,执行命令insmod seqlock_init.ko插入模块,然后执行命令dmesg -c,会出现如图所示的结果。

Linux内核API seqlock_init

结果分析:

测试程序中调用了函数write_seqlock()和write_sequnlock(),其功能参考极客笔记关于它们的分析。

宏seqlock_init()以及函数write_seqlock()、write_sequnlock()的功能分别与宏spin_lock_init()、spin_lock()、spin_unlock()的功能相似,只是增加了对结构体seqlock_t中顺序号sequence的操作。顺序锁通过seqlock_init()初始化后,sequence也被初始化为0,以后的每次申请或释放锁操作,sequence都会在原有数值上执行加1操作。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程