第二十章 linux-资源分配
第二十章 linux-资源分配
资源管理
先掌握用于管理资源的数据结构和函数:
数据结构
Linux提供通用的构架,用于在内存中构建数据结构。这些结构描述了系统中可用的资源,使得内核代码能够管理和分配资源。具中关键的数据结构resource源码如下:
//树数据结构定义
struct resource {
resource_size_t start;
resource_size_t end;//start end指定一般性区域,通常表示某个地址空间的一个区域
const char *name;//存储一个字符串,以便给资源赋予一个有意义的名称,资源名称实际与内核无关 proc文件系统z2
unsigned long flags;//用于描述资源及其当前状态
struct resource *parent, *sibling, *child;
};
用于连接parent,child,sibling成员规则如下:
- 每个子结点只有一个父结点
- 一个父结点可以有任意数目的子结点
- 同一个父结点的所有子结点,会迕接到兄弟结点链表上面。
在内存中表示数据结构时,我们必须要注意几个问题:
- 尽管每个子结点都有一个指针指向父结点,但父结点只有一个指针指向第一个子结点。所有其它子结点都通过兄弟结点链表访问
- 指向父结点的指针同样可以为NULL。
请求和释放资源
为确保可靠地配詈资源(无论何种类型),内核必须提供一种机制来分配和释放资源。一旦资源已经分配,则不能由任何其他驱动程序使用。
请求资源
内核提供了_request_resource函数,用于请求一个资源区域。
request_resource->request_resource_conflict->__request_resource
/* Return the conflict entry if you can't request it */
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;
}
}
该函数用于分配个reqeust实例,在此函数当中也会进行检查(起始地址大于结束地址,请求无法使用),则放弃操作。request_resource这个函数负责必要的锁操作,主要工作还是由__request_resource。
request_resource
/**
* request_resource - request and reserve an I/O or memory resource
* @root: root resource descriptor
* @new: resource descriptor desired by caller
*
* Returns 0 for success, negative error code on error.
*/
int request_resource(struct resource *root, struct resource *new)
{
struct resource *conflict;
conflict = request_resource_conflict(root, new);
return conflict ? -EBUSY : 0;
}
request_resource_conflict
struct resource *request_resource_conflict(struct resource *root, struct resource *new)
{
struct resource *conflict;
write_lock(&resource_lock);
conflict = __request_resource(root, new);
write_unlock(&resource_lock);
return conflict;
}
__request_resource它连接扫描现存的资源,将新资源添加到正确的位置,或发现与已经分配区域的冲突。完成所有操作之后,需要遍历兄中弟结点的链表。如果所需的资源区域是空闲的,则插入新的resource实例,这样就可以完成资源分析。如果区域不是空闲的,则分配失败。
在扫描特定父结点的子结点时,只会在一个层次上扫描兄弟结点链表。内核不会扫描更底层子结点的链表。
释放资源
调用release_resource函数释放使用中的资源源码如下:
release_resource
int release_resource(struct resource *old)
{
int retval;
write_lock(&resource_lock);
retval = __release_resource(old);
write_unlock(&resource_lock);
return retval;
}
__release_resource
static int __release_resource(struct resource *old)
{
struct resource *tmp, **p;
p = &old->parent->child;
for (;;) {
tmp = *p;
if (!tmp)
break;
if (tmp == old) {
*p = tmp->sibling;
old->parent = NULL;
return 0;
}
p = &tmp->sibling;
}
return -EINVAL;
}
I/O内存
资源、管理还有一个很重要的方面是I/O内存的分配方式,因为在所有平台上都是与外设通信的主要方法(IA一32除外,其中I/O端口更为重要)。I/O内存不仅包括与扩展设备通信自接使用的内存区域,还包括系统中可用的物理内存和ROM存储器,以及包含在资源列表中的内存(可以使用proc文件系统中的iomem文件,显示所有的I/O内存)。
所有分配的I/O内存地址,它们都要通过一棵资源树管理,树的根结点是全局内核变量iomem_resource。
用I/O内存时,分配内存区域并不是所需唯一操作。主要取决于总线系统和处理器类型,可能必需拓展设备的地址空间映射到内核地址空间之后,才可以访问此设备(称为软件I/O映射)。这是通过使用ioremap内核函数适当设备系统页表而实现的。同样也可以使用体系结构当中的iounmap函数解除映射操作。
将一个物理地址映射到处理器的虚扌以地址空间中,使得内核可以使用该地址,就设备驱动程序而言,意味着拓展总线的地址空间映射到CPU的地址空间中,使得能够用普通内存访问函数来操作总线/设备。
I/O端口
I/O端口是一种与设和总线通信的流行方法,特别是在IA一32平台上。类似于I/O内存,按良好范例编写的驱动程序在访问所需的区域之前,相应的区域必须已经注册。糟糕的是,处理无法检查注册是否经完成。
kernel/resource.c中的ioport_resource充当资源树的根节点。proc文件系统中的ioports文件可以显示已经分配的端口地址。
ioport_resource
struct resource ioport_resource = {
.name = "PCI IO",
.start = 0,
.end = IO_SPACE_LIMIT,
.flags = IORESOURCE_IO,
};
相关文章
- Linux下面使用端口631打开打印服务(linux端口631)
- 深入理解Linux系统中的PATH变量(linuxpath变量)
- 如何在Linux中打开命令窗口(linux怎么打开命令窗口)
- Linux 主机快速安装指南(linux主机安装)
- 系统令人惊叹的N9:Linux系统的神奇之处(n9linux)
- Linux 内置函数atoi的作用(linuxatoi)
- 调试Linux后台程序调试指南(linux后台程序)
- Linux下实现LS命令的智慧方式(linux实现ls命令)
- Linux嵌入式开发:拓展编程技能的新突破(linux嵌入式开发培训)
- Linux下安装磁盘分区的指南(linux安装创建分区)
- Linux:轻松跨越多个平台(linux跨平台)
- 数据探索Linux环境下DB2数据的机会(linux查看db2)
- Linux的分支:开放源码的丰富可选择(linux的分支)
- 轻松玩转Linux:文件挪动的小技巧(linux挪动文件)
- 「备份Linux文件,轻松保障数据安全!」(linux文件备份命令)
- 挂载Linux:一步步完成MNT(linuxmnt)
- 练就Linux精通:练习题解析(linux练习题)
- 搭建大规模的linux VPN——给加速你的网络(linux批量搭建vpn)
- 搭建Linux虚拟机服务器,轻松实现强大效能(linux虚拟机服务器)
- Linux 更改系统时区的快速攻略(linux修改系统时区)
- 快捷键轻松打开Linux命令(linux快捷键打开命令)
- Linux网络设置:轻松管理多个网关(linux多个网关)
- 快速掌握 Linux 操作系统基础知识(linux操作系统知识)