linux中request_region()函数的分析

struct resource ioport_resource = {
.name = "PCI IO",
.start = 0,
.end = IO_SPACE_LIMIT, //IO_SPACE_LIMIT = 0xffffffff
.flags = IORESOURCE_IO,
};

request_region(iobase, 2, dev->name)
      __request_region(&ioport_resource, (start), (n), (name), 0)
              struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
              res->name = name;
              res->start = start;
              res->end = start + n - 1;
              res->flags = IORESOURCE_BUSY;
              res->flags |= flags;                //以上是将资源的信息记录在res中
              write_lock(&resource_lock);//关于这个锁详见注释1
              conflict = __request_resource(parent, res);//请求资源,返回值为0表示请求成功,详见注释2
如果申请成功的话,就保留res空间,因为这是已经形成了注释2里面的链表了。如果申请失败的话,回进行如下处理:
判断返回值是否是parent,是parent则表示是资源本身就有问题。如果没有问题的话,判断与本次申请相冲突的资源是否真的处于繁忙状态,如果不是真的繁忙,就会重新申请,否则向下执行。
如果资源真的繁忙的话,会判断该资源是否是多路复用的,如果是的话,就会将当前进程挂起,调度其他进程来执行!当本进程重新被调度时,又会循环去判断是否可以获得资源。所以如果资源可以多路复用,得不到该资源就不会返回。如果该资源不可多路复用,则立即会释放空间,返回NULL!

注释1:
read_lock()和write_lock()
锁变量的初值为RW_LOCK_UNLOCKED(0x01000000),锁变量为正时为未锁状态反之为上锁状态。 
read_lock()对锁变量减1,如果结果为负,则说明已被某个write_lock()上锁。然后read_lock()对锁变量加1,释 放read_lock状态,接着等待锁变量的值变为1;一旦锁变量变为1,read_lock()再次对锁变量减1 ,如果非负则成功,否则重复上述过程。 
write_lock()对锁变量减0x01000000,如果结果非零,则说明已被write_lock()或read_lock()上锁。然 后write_lock()对锁变量加0x01000000,释放write_lock()状态,接着等待锁变量的值变为0x01000000;一旦锁变 量变为0x01000000,write_lock()再次对锁变量减0x01000000,如果为零则成功,否则重复上述过程。 

由此可以实现多个同时读,但是读----写和写-----写是互斥的!
那么针对上面的程序,就是说,当一个进程没有释放写锁之前,另一个进程无法对write_lock(&resource_lock);和write_unlock(&resource_lock);之间的代码进行操作!

注释2:
static struct resource * __request_resource(struct resource *root, struct resource *new)
{
resource_size_t start = new->start;
resource_size_t end = new->end;
struct resource *tmp, **p;
        //以下三个判断是出错处理,不必关心
if (end < start)
return root;
if (start < root->start)
return root;
if (end > root->end)
return root;
p = &root->child; 
for (;;) {
tmp = *p;
if (!tmp || tmp->start > end) {
new->sibling = tmp;  
*p = new;                   
new->parent = root;
return NULL;    
}
p = &tmp->sibling;
if (tmp->end < start) 
continue;
return tmp;
}
}
我们用个例子来说明一下上面的程序:
如果有四个资源的申请,前三次申请的资源都没有出现交集,那么前三次的资源就会形成如下的关系:每个资源的parent都指向root,root的child指向第三次申请的资源,第三次申请的资源的sibling指向第二次申请的资源,第二次申请的资源的sibling指向第一次申请的资源,第一次申请的资源的sibling指向null。如下图所示:

现在开始第四次申请资源,判断res3->start是否大于本次申请资源的结束地址,如果是的话,说明没有交集,就会重复以上工作,然后返回!如果不成立的话,说明可能有交集,会让p指向res2,并判断res3->end是否小于本次资源的起始地址,如果是的话,说明没有交集就会结束本次循环,开始下一次循环。下一次循环会跟res2比较有无交集,如果没有交集会跟res1比较,如果还是没有交集的话,下一次的循环tmp=NULL,就会成功返回,一旦发现申请的资源跟之前申请的资源存在交集的话,就会出错返回,返回值是与本次申请出现交集的资源的地址!

经过上面的分析就很清楚了,request_region这个函数实际上就是为了保证对资源的互斥访问!

linux中request_region()函数的分析相关推荐

  1. Linux中fork()函数详解

    Linux中fork()函数详解 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事, ...

  2. linux中probe函数传递参数的寻找(下)

    点击打开链接 linux中probe函数传递参数的寻找(下) 通过追寻driver的脚步,我们有了努力的方向:只有找到spi_bus_type的填充device即可,下面该从device去打通,当两个 ...

  3. linux中 probe函数的何时调用的?

    点击打开链接 linux中 probe函数何时调用的 所以的驱动教程上都说:只有设备和驱动的名字匹配,BUS就会调用驱动的probe函数,但是有时我们要看看probe函数里面到底做了什么,还有传递给p ...

  4. 每天学一点儿shell:linux中时间函数的date的用法

    文章目录 1.linux中date函数格式 2.date日期函数的具体用法 2.1.获取相应格式的日期 2.2.获取相隔时间段的日期 2.2.1.获取今天的日期 2.2.2.获取昨天的日期 2.2.3 ...

  5. caffe中loss函数代码分析--caffe学习(16)

    接上篇:caffe中样本的label一定要从序号0开始标注吗?–caffe学习(15) A: 1:数学上来说,损失函数loss值和label从0开始还是从1或者100开始是没有直接联系的,以欧式距离损 ...

  6. linux内核sock_sendmsg,为什么linux中sendto函数中的msg.msg_iovlen=1;

    为什么linux中sendto函数中的msg.msg_iovlen=1; | 内核中定义的sys_sendto的源码吗? 这个属于sendmsg中struct msghdr的用法问题, sys_sen ...

  7. Linux中pthread_create函数的实现

    转:http://blog.sina.com.cn/s/blog_6abf2c040101fpca.html 原文地址:[原]Linux中pthread_create函数的实现作者:jiq408694 ...

  8. Linux中popen函数的作用小结

    概述 popen()函数通过创建一个管道,调用fork()产生一个子进程,执行一个shell以运行命令来开启一个进程.这篇文章重点给大家介绍Linux中popen函数的作用,感兴趣的朋友一起看看吧 p ...

  9. linux 内核 fget,fgets函数 linux中fgets函数怎么用

    一个函数该如何使用?我们最先要了解的就是这个函数的语法以及具体的含义是什么,所以今天我们就来看一看fgets函数在实际的运用过程当中是如何使用的,希望能给大家带来一定的帮助. fgets函数--lin ...

最新文章

  1. webSocket浏览器握手不成功(解决)
  2. 声音定位的距离误差到底有多高?
  3. VirtualBox快照(Snapshot)功能使用及注意事项
  4. asp access的安全:不要认为简单的改后缀mdb为asp就能防下载
  5. Elasticsearch——Search的基本介绍
  6. 卸载mysql 安装mariadb_centos7卸载mariadb并安装mysql8
  7. c语言输入一串字符辨别奇偶,c语言设计输入一个正整数判断其中各个数字是否奇数偶数交替出现是输出yes不是输出no...
  8. 看到抖音上 Python 工程师晒的工资条,我沉默了.....
  9. 我应关注的AEC算法细分
  10. 别人的一句话影响了我好几年
  11. c语言求信源的信息熵,第二章-信源与信息熵(三)
  12. python第二版答案第六章_Python语言程序设计基础(第2版) 课后题 第六章
  13. TCP/IP指南(RFC1180)
  14. 我对TCP协议的一点形而上的看法
  15. excel单元格内容拆分_Excel分列解决不了的问题,VBA轻松搞定之拆分单元格
  16. 规则引擎 - (二)XOM工程
  17. iOS-苹果应用商店审核指南中文翻译
  18. 今日头条面试——iOS开发面试题
  19. OSI体系结构——数据链路层详解
  20. 新iPhone9月登场, 5大特色浮出水!

热门文章

  1. 中移4G模块-ML302-OpenCpu开发-(MQTT连接阿里云-接收和发送数据)
  2. Linux 通过命令行下载、上传文件到百度网盘(bypy)
  3. Linux shell 对话框,如何在 Bash Shell 脚本中显示对话框
  4. Bootstrap学习(二)
  5. [10.2模拟] book
  6. app开发第二次总结
  7. maven pom.xml详解
  8. C# 基础知识和VS2010的小技巧总汇(2)[转]
  9. iframe多层嵌套时获取元素总结
  10. HTC ThunderBolt无法打开3G问题解决方法