当前位置:  技术问答>linux和unix

linux 关于rw_semaphore 结构体内的count,到底是如何记录信息的?

    来源: 互联网  发布时间:2017-05-24

    本文导语:  linux 3.10 在include/linux/Rwsem.h中有关于rw_semaphore结构体的定义: #ifdef CONFIG_RWSEM_GENERIC_SPINLOCK #include  /* use a generic implementation */ #else /* All arch specific implementations share the same struct */ struct rw_semaphore { long coun...

linux 3.10
在include/linux/Rwsem.h中有关于rw_semaphore结构体的定义:
#ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
#include  /* use a generic implementation */
#else
/* All arch specific implementations share the same struct */
struct rw_semaphore {
long count;
raw_spinlock_t wait_lock;
struct list_head wait_list;
#ifdef CONFIG_DEBUG_LOCK_ALLOC
struct lockdep_map dep_map;
#endif
};

Understanding the Linux Kernel, 3rd Edition 里面对 count 的定义是:
count
Stores two 16-bit counters. The counter in the most significant word encodes in two's complement form the sum of the number of nonwaiting writers (either 0 or 1) and the number of waiting kernel control paths. The counter in the less significant word encodes the total number of nonwaiting readers and writers.

我对应了lib/rwsem.c的实现函数:rwsem_down_read_failed,rwsem_down_write_failed 还是看不懂count的意义。
我的理解是比如有1个read占有信号,而一个write阻塞,这样的话count应该是0xffff 0001 ;而1个write占有信号,1个read被阻塞应该是0x fffe 0001 
实际情况不是这样的,有没有谁可以帮忙解释下,谢谢了
另外x86 下,arch/x86/include/asm/Rwsem.h中的几个宏为什么这样定义?
#ifdef CONFIG_X86_64
# define RWSEM_ACTIVE_MASK 0xffffffffL
#else
# define RWSEM_ACTIVE_MASK 0x0000ffffL
#endif

#define RWSEM_UNLOCKED_VALUE 0x00000000L
#define RWSEM_ACTIVE_BIAS 0x00000001L
#define RWSEM_WAITING_BIAS (-RWSEM_ACTIVE_MASK-1)
#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)

|
我用如下的模块试了一下,根据log推断,count的变化应该和之前想的一样。

[ 6312.206759] Hello, world
[ 6312.208982] reader_1 is running
[ 6312.209347] reader_2 is running
[ 6312.209724] writer is running
[ 6312.222916] writer is waiting for write
[ 6312.222924] writer got write lock
[ 6312.222926] sem.count=0xffffffff00000001
[ 6312.222928] writer is sleeping 200
[ 6312.313546] reader_1 is waiting for read
[ 6312.313559] reader_2 is waiting for read
[ 6312.314651] writer_2 is running
[ 6312.327622] writer_2 is waiting for write
[ 6312.424645] sem.count=0xfffffffe00000001
[ 6312.424651] writer releses write lock
[ 6312.424697] reader_1 got read lock
[ 6312.424700] sem.count=0xffffffff00000002
[ 6312.424701] reader_1 is sleeping 200
[ 6312.424705] reader_2 got read lock
[ 6312.424707] sem.count=0xffffffff00000002
[ 6312.424708] reader_2 is sleeping 200
[ 6312.627648] reader_2 releses read lock
[ 6312.627747] reader_1 releses read lock
[ 6312.627867] writer_2 got write lock
[ 6312.627872] sem.count=0xffffffff00000001
[ 6312.627874] writer_2 is sleeping 200
[ 6312.831732] sem.count=0xffffffff00000001
[ 6312.831739] writer_2 releses write lock

#include 
#include 
#include 
#include 
#include 
#include 
MODULE_LICENSE("Dual BSD/GPL");

static struct rw_semaphore sem;

static void print_sem(struct rw_semaphore *sem)
{
    printk(KERN_DEBUG "sem.count=0x%016lxn", sem->count);
}

static void get_read_lock(struct rw_semaphore *sem, char *name)
{
    printk(KERN_DEBUG "%s is waiting for readn", name);
    down_read(sem);
    printk(KERN_DEBUG "%s got read lockn", name);
}

static void release_read_lock(struct rw_semaphore *sem, char *name)
{
    printk(KERN_DEBUG "%s releses read lockn", name);
    up_read(sem);
}

static void get_write_lock(struct rw_semaphore *sem, char *name)
{
    printk(KERN_DEBUG "%s is waiting for writen", name);
    down_write(sem);
    printk(KERN_DEBUG "%s got write lockn", name);
}

static void release_write_lock(struct rw_semaphore *sem, char *name)
{
    printk(KERN_DEBUG "%s releses write lockn", name);
    up_write(sem);
}

int reader(void *data)
{
    char *name = (char *)data;
    printk(KERN_DEBUG "%s is runningn", name);
    msleep(100);

    get_read_lock(&sem, name);
    print_sem(&sem);

    printk(KERN_DEBUG "%s is sleeping 200n", name);
    msleep(200);

    release_read_lock(&sem, name);
    do_exit(0);
}
int writer(void *data)
{
    char *name = (char *)data;
    printk(KERN_DEBUG "%s is runningn", name);
    msleep(10);

    get_write_lock(&sem, name);
    print_sem(&sem);

    printk(KERN_DEBUG "%s is sleeping 200n", name);
    msleep(200);

    print_sem(&sem);
    release_write_lock(&sem, name);
    do_exit(0);
}

static int hello_init(void)
{
    struct task_struct *task = NULL;
    printk(KERN_ALERT "Hello, worldn");

    init_rwsem(&sem);

    task = kthread_create(reader, "reader_1", "reader");
    if (IS_ERR(task)) {
        printk(KERN_DEBUG "failed to create taskn");
        return 1;
    }
    wake_up_process(task);

    task = kthread_create(reader, "reader_2", "reader");
    if (IS_ERR(task)) {
        printk(KERN_DEBUG "failed to create taskn");
        return 1;
    }
    wake_up_process(task);

   task = kthread_create(writer, "writer", "reader");
    if (IS_ERR(task)) {
        printk(KERN_DEBUG "failed to create taskn");
        return 1;
    }
    wake_up_process(task);

    msleep(100);
    task = kthread_create(writer, "writer_2", "reader");
    if (IS_ERR(task)) {
        printk(KERN_DEBUG "failed to create taskn");
        return 1;
    }
    wake_up_process(task);

    return 0;
}

static void hello_exit(void)
{
    printk(KERN_ALERT"Goodbye, cruel worldn");
}

module_init(hello_init);
module_exit(hello_exit);


|
我的理解基本和楼主一样。区别就是count的上半部分等于当前获得锁的写者数目(0或1)加上等待列表是否为空(0或1)的补码。

例如:
1. 当前有一个获得锁的写者且等待链表为空,则count=0xffff0001
2. 当前有一个获得锁的写者且等待链表非空,则count=0xfffe0001
3. 当前有多个获得锁的读者且等待链表为空,则count=0x0000000X
4. 当前有多个获得锁的读者且等待链表非空,则count=0xffff000X

楼主实际测试过并且发现不是这样?

    
 
 

您可能感兴趣的文章:

  • 各位高人,关于IDE的驱动程序,我看蒙了,谁能告诉我到底linux源文件中到底那些是跟IDE硬盘驱动有关的?
  • 学linux到底是学些什么?
  • 到底怎么样调试linux内核啊?
  • linux菜鸟,求大神指点,linux学的到底是什么?
  • 红旗linux下到底怎么安装opera呀?
  • 在LINUX下编网络设备驱动到底用什么工具比较好?
  • Linux内核的源文件到底在哪个目录下啊?
  • 到底现在Linux好些还是Windows好些?
  • linux下的应用软件开发到底都用什么语言啊??
  • 到底如何从硬盘装linux?
  • 对于一个程序员来说,学习linux程序设计和unix编程到底有什么好处
  • 菜鸟问题:Linux下 ioctl 函数到底在哪?
  • unix,Linux,redhat,redflag这么多,到底该学哪个?
  • FreeBSD与Linux到底有什么不同啊?
  • linux下到底如何设置环境变量?在哪设置?详细具体点
  • 到底在linux那里是用什么命令解压zip文档的?各位高手告诉我!!
  • linux下的math.h到底怎么回事啊
  • linux到底怎么学?
  • Red Hat Enterprise Linux AS release 4到底是什么版本?
  • 大家帮帮忙----linux下的编程到底要学哪些东西?
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 强人,linux下驱动相关数据结构和usb设备数据结构之间的功能分析
  • 有一个win32的结构体,大伙看看能否转换成linux下的基本等价的结构体?
  • linux 结构体
  • 在Linux下用socket编程能直接传送结构体吗
  • linux中有没有这个结构体 struct _pool_st
  • linux meminfo结构体的不理解
  • 请问有关linux底层网络数据结构sk_buff相关知识
  • Linux文件系统结构的疑问
  • 想问问问linux的文件系统结构的问题
  • 最简单的问题,linux下怎么查看某个结构体的定义。
  • 讨论一下:linux和lwip中的接收缓冲区结构哪个好呢?
  • linux中大量的全局变量怎么体现结构化的程序设计?
  • linux下如何查看结构体类型的成员
  • 请教linux驱动复杂,庞大的结构
  • linux 下结构struct ethhdr,struct iphdr在那个头文件下;谢谢!!
  • 两种不同的Linux能不能使用同一套分区结构进行安装?
  • 看LINUX的内核要不要硬件、数据结构、算法、汇编
  • linux下编程,若要查看一个库变量的结构信息,用man命令可以么?该怎么做?
  • 请问哪里有比较全的Linux内核编程API和数据结构的文档?
  • Linux2.4防火墙模块编程__u32结构的IP地址怎么算?
  • linux c/c++ IP字符串转换成可比较大小的数字
  • 在win分区上安装linux和独立分区安装linux有什么区别?可以同时安装吗?(两个linux系统)
  • linux哪个版本好?linux操作系统版本详细介绍及选择方案推荐
  • 在虚拟机上安装的linux上,能像真的linux系统一样开发linux程序么?
  • secureCRT下Linux终端汉字乱码解决方法
  • 我重装window后,把linux的引导区覆盖了,进不了linux怎么办?急啊,望热心的人帮助 (现在有linux的盘)
  • Linux c字符串中不可打印字符转换成16进制
  • 安装vmware软件,不用再安装linux系统,就可以模拟linux系统了,然后可以在其上学习一下LINUX下的基本操作 了?
  • Linux常用命令介绍:更改所属用户群组或档案属性
  • 红旗Linux主机可以通过127.0.0.1访问,但如何是连网的Win2000机器通过Linux的IP去访问Linux
  • linux命令大全详细分类介绍及常用linux命令文档手册下载


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3