Linux内核API read_seqretry

函数read_seqretry():读者在访问完被顺序锁s1保护的共享资源后需要调用该函数来检查,在读访问期间是否有写者访问了该共享资源,该检查是通过判断当前顺序锁sl的顺序号与初始顺序号start是否相等实现的。如果不相等,则读访问期间有写者访问了共享资源,读者就需要重新进行读操作,否则,读者成功完成了读操作。

read_seqretry文件包含

#include <linux/seqlock.h>

read_seqretry函数定义

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

函数定义格式:

static inline unsigned read_seqretry(const seqlock_t *sl, unsigned start)

read_seqretry输入参数说明

  • sl:指向顺序锁结构体的指针。关于顺序锁结构体seqlock _t的定义及顺序锁的概念参考极客笔记中宏seqlock_init()的分析。
  • start:表示顺序锁的初始顺序号。

read_seqretry返回参数说明

  • 函数read_seqretry()返回一个无符号整型值,该值一般为1或者0,如果返回1,则读者需要重新进行读操作,返回0,则读者成功完成了读操作。

read_seqretry实例解析

编写测试文件:read_seqretry.c

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

#include <linux/seqlock.h>
#include <linux/init.h>
#include <linux/module.h>

MODULE_LICENSE("GPL");
static int __init read_seqretry_init(void);
static void __exit read_seqretry_exit(void);
seqlock_t seqlock ;

模块初始化函数:

int __init read_seqretry_init(void)
{
    int ret;
    seqlock_init( &seqlock );                      //初始化顺序锁

    /*一下两行输出顺序锁中自旋锁字段值和顺序锁当前的顺序号*/
    printk("after seqlock_init, sequence: %d\n\n", seqlock.seqcount.sequence);

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

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

    do{
        ret = read_seqbegin( &seqlock );
        printk("ret = %d\n", ret );
    }while( read_seqretry(&seqlock, ret) );        //读操作代码块
    return 0;
}

模块退出函数:

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

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

module_init(read_seqretry_init);
module_exit(read_seqretry_exit);

实例运行结果及分析:

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

Linux内核API read_seqretry

结果分析:

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

读者使用顺序锁的模式一般为:

do{
    ret = read_seqbegin( &seqlock );
    printk("ret = %d\n", ret );
    // 在这里执行读操作…
}while( read_seqretry(&seqlock, ret) );

读者从ret_seqbegin()返回后,得到顺序锁的当前顺序号,并开始执行对共享资源的读操作。如果期间有写者修改了共享资源,则read_seqretry()将返回真,从而使读者重新执行读操作以确保数据的一致性。

在测试程序中读操作代码块缺省,即没有共享资源会被写者获取,因此read_seqretry()返回假,即读者执行一次读操作即成功。另外,对于单处理器体系结构的机器,在执行程序代码中的do…while循环体时,不会出现其他写者修改共享资源的情况,read_seqretry()返回假,读者执行一次读操作即成功。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程