GitCode 开源社区
linux中request_region()函数的分析
linux中request_region()函数的分析
linux-dash
A beautiful web dashboard for Linux
项目地址:https://gitcode.com/gh_mirrors/li/linux-dash
免费下载资源
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);
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这个函数实际上就是为了保证对资源的互斥访问!
GitHub 加速计划 / li / linux-dash
10.39 K
1.2 K
下载
A beautiful web dashboard for Linux
最近提交(Master分支:2 个月前 )
186a802e
added ecosystem file for PM2 4 年前
5def40a3
Add host customization support for the NodeJS version 4 年前
更多推荐
- 6326
- 0
- 0
- 0
扫一扫分享内容
- 分享
已为社区贡献12条内容
回到
顶部
顶部
所有评论(0)