Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1714395
  • 博文数量: 177
  • 博客积分: 9416
  • 博客等级: 中将
  • 技术积分: 2513
  • 用 户 组: 普通用户
  • 注册时间: 2006-01-06 16:08
文章分类

全部博文(177)

文章存档

2013年(4)

2012年(13)

2011年(9)

2010年(71)

2009年(12)

2008年(11)

2007年(32)

2006年(25)

分类:

2008-02-29 22:29:01

很多系统调用都需要操纵进程的virtual地址空间,如fork(),exec(),brk(),exit()等。fork()创建子进程,因此需要将父进程的地址空间进行拷贝;exec()需要做的事情最多……“UNIX内核(12):进程的结构——上下文”中提到了区(region)的概念。实际上,内核是通过对region表项(以下简称region)的操作来实现对进程virtual地址空间的操纵。下面就讲讲region的结构和操作。
 
Region的结构
1、指向要加载文件的inode的指针;
2、类型,如text、data之类;
3、大小;
4、该region在物理内存中的位置(通过一些辅助的地址映射表来使之与virtual地址关联);
5、状态:可用、已加载、请求、正在加载;
6、引用计数;
 
对于region的操作有加/解锁、分配、附加region到进程的内存空间、改变大小、从一个文件加载region到进程的内存空间、释放、从进程的内存空间分离region、复制。下面就逐一讨论,在理解时,要时刻记住“UNIX内核(12):进程的结构——上下文”中的模型,以及与inode的类比。
 
分配
region存放内核的region表中,在由内核中有空闲/活动region链表,这些链表包含指向region表中项目的指针。为了分配region,首先从free链表头取出一个region置入活动链表中并锁住。由于大部分进程都与可执行文件相关联,因此,设置inode指针指向可执行文件。inode用来标识region,这样其他进程就可以共享该region。此时需要增加inode引用计数是得可执行文件不会被意外删除。
Region * AllocateRegion(INode * pINode, RegionType aType)
{
    Region * pReg = pFreeRegionList->GetRegion();
    pReg->type = aType;
    pReg->inode = pINode;
    if (pINode == NULL)
    {
        pINode->refCount++;
    }
    pActiveRegionList->PutRegion(pReg);
    return pReg->Lock();
}
 
附加region到进程
首先在pregion中找到一个空闲slot,将region指针置入其中,并记录下该region在进程中的virtual地址。注意新的region的virtual地址不能与已有的regionvirtual地址重合,也不能超过virtual地址上限。
PRegionEntry * AttachRegion(Region * pLockedReg, Process * pTargetProc, VirtualAddr * startingAddr, RegionType aType)
{
    PRegionEntry * pre = pPRegion->GetFreeEntry();
    pre->pRegion = pLockedReg;
    pre->type = aType;
    pre->virtualAddr = startingAddr;
    assert((startingAddr + pLockedReg->size) < limit);
    pre->pRegion->refCount++;
    pTargetProc->size += pLockedReg->size;
    初始化寄存器三元组; // 如果该region已经附加到另一个进程,则使用已有的页表,否则使用新的页表。
    return pre;
}
 
改变大小
进程可以修改virtual地址空间的大小,比如stack。为了修改大小,最终是由改变region大小来实现。但对于共享的region,是不可能修改大小的。另外就是要注意进程大小限制及地址空间覆盖问题。改变大小之后,内核将分配页表来适应更大的region并分配物理内存(当然,这是针对不支持请求式内存管理的平台)。如果需要分配物理内存,则需要保证在改变大小前有足够的可用内存……再说下去就是内存管理的内容了,日后再议。
void GrowRegion(PRegion * pre, Size * pSize)
{
    if (pSize->Positive())
    {
        检查大小是否合法;
        分配内存管理页表;
        if (!SupportDemandPaging())
        {
            分配物理内存;
            创建辅助表;
        }
    }
    else // 减小region大小
    {
        释放相应的物理内存;
        释放相应的辅助表;
    }
    根据需要初始化辅助表;
    修改进程的大小;
}
 
加载
void LoadRegion(PRegion * pre, VirtualAddr startingAddr, INode * pFileForLoad, Offset * offsetInFileOfStartOfRegion, Size * amountOfData)
{
    GrowRegion(pre, size);
    pre->pRegion->state = BeingLoaded;
    Unlock(pre->pRegion);
    为读取文件设置u area参数:目的虚地址、从offsetInFileOfStartOfRegion处开始、要读取的数量;
    将文件读到region(内部的read()函数);
    Lock(pre->pRegion);
    pre->pRegion->state = LoadComplete;
    唤醒所有等待加载region的进程;
}
 
释放
void FreeRegion(Region * pLockedReg)
{
    if (pRegion->refCount != 0)
    {
        Unlock(pRegion);
        if (pRegion->inode != null)
        {
            Unlock(pRegion->inode);
        }
        return;
    }
    if (pRegion->inode != null)
    {
        iput(pRegion->inode);
    }
    释放物理内存;
    释放辅助表;
    清除pRegion的各字段;
    pFreeRegionList->PutRegion(pRegion);
    Unlock(pRegion);
}
 
分离(detach)
void DetachRegion(PRegion * pre)
{
    释放相应的辅助的内存管理表;
    减小进程大小;
    减少Region的引用计数;
    if(Region的引用计数为0且没有设置sticky)
    {
        FreeRegion(pre->pRegion);
    }
    else
    {
        解锁inode;
        解锁region;
    }
}
 
复制
Region * DupRegion(PRegion * pre)
{
    if (region是共享的)
    {
        pre->pRegion->refCount++;
        return pre->pRegion;
    }
    Region * pReg = AllocateRegion(pre->pRegion->inode, pre->pRegion->type);
    根据当前的Region创建内存管理的辅助结构;
    分配物理内存; // 注:copy-on-write技术并不要求此时就分配物理内存
    将pre->pRegion的物理内存中的内容考到新的Region中;
    return pReg;
}
 
PS:写得有点简单:-)
 
参考:
The Design of The UNIX Operation System, by Maurice J. Bach
Understanding The Linux Kernel, 3rd edition, by Daniel P. Bovet, Marco Cesati
 
Copyleft (C) 2007, 2008 raof01. 本文可以用于除商业用途外的所有用途。若要用于商业用途,请与作者联系。
阅读(2848) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2008-03-03 10:57:02

PS:来投诉你