📄 86.html
字号:
<a name='L246'> bdesc->refcnt = 0;
<a name='L247'> bdesc->bucket_size = bdir->size;
<a name='L248'> bdesc->page = bdesc->freeptr = (<b>void</b> *) cp = <a href='../S/94.html#L101' title='Defined at 101 in mm/memory.c.'>get_free_page</a> ();
<a name='L249'><i><font color='green'>// 如果申请内存页面操作失败,则显示出错信息,死机。</font></i>
<a name='L250'> <b>if</b> (!cp)
<a name='L251'> <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("Out of memory in kernel malloc()");
<a name='L252'><i><font color='green'>/* Set up the chain of free objects */</font></i>
<a name='L253'><i><font color='green'>/* 在该页空闲内存中建立空闲对象链表 */</font></i>
<a name='L254'><i><font color='green'>// 以该桶目录项指定的桶大小为对象长度,对该页内存进行划分,并使每个对象的开始4 字节设置</font></i>
<a name='L255'><i><font color='green'>// 成指向下一对象的指针。</font></i>
<a name='L256'> <b>for</b> (<a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> = <a href='../D/324.html' title='Multiple defined in 4 places.'>PAGE_SIZE</a> / bdir->size; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a> > 1; <a href='../D/839.html' title='Multiple defined in 4 places.'>i</a>--)
<a name='L257'> <font color='red'>{</font>
<a name='L258'> *((<b>char</b> **) cp) = cp + bdir->size;
<a name='L259'> cp += bdir->size;
<a name='L260'> <font color='red'>}</font>
<a name='L261'><i><font color='green'>// 最后一个对象开始处的指针设置为0(NULL)。</font></i>
<a name='L262'><i><font color='green'>// 然后让该桶描述符的下一描述符指针字段指向对应桶目录项指针chain 所指的描述符,而桶目录的</font></i>
<a name='L263'><i><font color='green'>// chain 指向该桶描述符,也即将该描述符插入到描述符链链头处。</font></i>
<a name='L264'> *((<b>char</b> **) cp) = 0;
<a name='L265'> bdesc->next = bdir->chain; <i><font color='green'>/* OK, link it in! */</font></i><i><font color='green'>/* OK,将其链入! */</font></i>
<a name='L266'> bdir->chain = bdesc;
<a name='L267'> <font color='red'>}</font>
<a name='L268'><i><font color='green'>// 返回指针即等于该描述符对应页面的当前空闲指针。然后调整该空闲空间指针指向下一个空闲对象,</font></i>
<a name='L269'><i><font color='green'>// 并使描述符中对应页面中对象引用计数增1。</font></i>
<a name='L270'> retval = (<b>void</b> *) bdesc->freeptr;
<a name='L271'> bdesc->freeptr = *((<b>void</b> **) retval);
<a name='L272'> bdesc->refcnt++;
<a name='L273'><i><font color='green'>// 最后开放中断,并返回指向空闲内存对象的指针。</font></i>
<a name='L274'> <a href='../S/25.html#L14' title='Defined at 14 in include/asm/system.h.'>sti</a> (); <i><font color='green'>/* OK, we're safe again */</font></i><i><font color='green'>/* OK,现在我们又安全了 */</font></i>
<a name='L275'> <b>return</b> (retval);
<a name='L276'><font color='red'>}</font>
<a name='L277'>
<a name='L278'><i><font color='green'>/*</font></i>
<a name='L279'><i><font color='green'>* Here is the free routine. If you know the size of the object that you</font></i>
<a name='L280'><i><font color='green'>* are freeing, then free_s() will use that information to speed up the</font></i>
<a name='L281'><i><font color='green'>* search for the bucket descriptor.</font></i>
<a name='L282'><i><font color='green'>*</font></i>
<a name='L283'><i><font color='green'>* We will #define a macro so that "free(x)" is becomes "free_s(x, 0)"</font></i>
<a name='L284'><i><font color='green'>*/</font></i>
<a name='L285'><i><font color='green'>/*</font></i>
<a name='L286'><i><font color='green'>* 下面是释放子程序。如果你知道释放对象的大小,则free_s()将使用该信息加速</font></i>
<a name='L287'><i><font color='green'>* 搜寻对应桶描述符的速度。</font></i>
<a name='L288'><i><font color='green'>*</font></i>
<a name='L289'><i><font color='green'></font></i>
<a name='L290'><i><font color='green'>* 我们将定义一个宏,使得"free(x)"成为"free_s(x, 0)"。</font></i>
<a name='L291'><i><font color='green'>*/</font></i>
<a name='L292'><i><font color='green'>//// 释放存储桶对象。</font></i>
<a name='L293'><i><font color='green'>// 参数:obj - 对应对象指针;size - 大小。</font></i>
<a name='L294'><b>void</b>
<a name='L295'><a href='../R/470.html' title='Multiple refered from 2 places.'>free_s</a> (<b>void</b> *obj, <b>int</b> size)
<a name='L296'><font color='red'>{</font>
<a name='L297'> <b>void</b> *page;
<a name='L298'> <b>struct</b> _bucket_dir *bdir;
<a name='L299'> <b>struct</b> bucket_desc *bdesc, *prev;
<a name='L300'>
<a name='L301'><i><font color='green'>/* Calculate what page this object lives in */</font></i>
<a name='L302'><i><font color='green'>/* 计算该对象所在的页面 */</font></i>
<a name='L303'> page = (<b>void</b> *) ((<b>unsigned</b> <b>long</b>) obj & 0xfffff000);
<a name='L304'><i><font color='green'>/* Now search the buckets looking for that page */</font></i>
<a name='L305'><i><font color='green'>/* 现在搜索存储桶目录项所链接的桶描述符,寻找该页面 */</font></i>
<a name='L306'><i><font color='green'>//</font></i>
<a name='L307'> <b>for</b> (bdir = bucket_dir; bdir->size; bdir++)
<a name='L308'> <font color='red'>{</font>
<a name='L309'> prev = 0;
<a name='L310'><i><font color='green'>/* If size is zero then this conditional is always false */</font></i>
<a name='L311'><i><font color='green'>/* 如果参数size 是0,则下面条件肯定是false */</font></i>
<a name='L312'> <b>if</b> (bdir->size < size)
<a name='L313'> <b>continue</b>;
<a name='L314'><i><font color='green'>// 搜索对应目录项中链接的所有描述符,查找对应页面。如果某描述符页面指针等于page 则表示找到</font></i>
<a name='L315'><i><font color='green'>// 了相应的描述符,跳转到found。如果描述符不含有对应page,则让描述符指针prev 指向该描述符。</font></i>
<a name='L316'> <b>for</b> (bdesc = bdir->chain; bdesc; bdesc = bdesc->next)
<a name='L317'> <font color='red'>{</font>
<a name='L318'> <b>if</b> (bdesc->page == page)
<a name='L319'> <b>goto</b> found;
<a name='L320'> prev = bdesc;
<a name='L321'> <font color='red'>}</font>
<a name='L322'> <font color='red'>}</font>
<a name='L323'><i><font color='green'>// 若搜索了对应目录项的所有描述符都没有找到指定的页面,则显示出错信息,死机。</font></i>
<a name='L324'> <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("Bad address passed to kernel free_s()");
<a name='L325'>found:
<a name='L326'><i><font color='green'>// 找到对应的桶描述符后,首先关中断。然后将该对象内存块链入空闲块对象链表中,并使该描述符</font></i>
<a name='L327'><i><font color='green'>// 的对象引用计数减1。</font></i>
<a name='L328'> <a href='../S/25.html#L15' title='Defined at 15 in include/asm/system.h.'>cli</a> (); <i><font color='green'>/* To avoid race conditions */</font></i><i><font color='green'>/* 为了避免竞争条件 */</font></i>
<a name='L329'> *((<b>void</b> **) obj) = bdesc->freeptr;
<a name='L330'> bdesc->freeptr = obj;
<a name='L331'> bdesc->refcnt--;
<a name='L332'><i><font color='green'>// 如果引用计数已等于0,则我们就可以释放对应的内存页面和该桶描述符。</font></i>
<a name='L333'> <b>if</b> (bdesc->refcnt == 0)
<a name='L334'> <font color='red'>{</font>
<a name='L335'><i><font color='green'>/*</font></i>
<a name='L336'><i><font color='green'>* We need to make sure that prev is still accurate. It</font></i>
<a name='L337'><i><font color='green'>* may not be, if someone rudely interrupted us....</font></i>
<a name='L338'><i><font color='green'>*/</font></i>
<a name='L339'><i><font color='green'>/*</font></i>
<a name='L340'><i><font color='green'>* 我们需要确信prev 仍然是正确的,若某程序粗鲁地中断了我们</font></i>
<a name='L341'><i><font color='green'>* 就有可能不是了。</font></i>
<a name='L342'><i><font color='green'>*/</font></i>
<a name='L343'><i><font color='green'>// 如果prev 已经不是搜索到的描述符的前一个描述符,则重新搜索当前描述符的前一个描述符。</font></i>
<a name='L344'> <b>if</b> ((prev && (prev->next != bdesc)) ||
<a name='L345'> (!prev && (bdir->chain != bdesc)))
<a name='L346'> <b>for</b> (prev = bdir->chain; prev; prev = prev->next)
<a name='L347'>
<a name='L348'> <b>if</b> (prev->next == bdesc)
<a name='L349'> <b>break</b>;
<a name='L350'><i><font color='green'>// 如果找到该前一个描述符,则从描述符链中删除当前描述符。</font></i>
<a name='L351'> <b>if</b> (prev)
<a name='L352'> prev->next = bdesc->next;
<a name='L353'><i><font color='green'>// 如果prev==NULL,则说明当前一个描述符是该目录项首个描述符,也即目录项中chain 应该直接</font></i>
<a name='L354'><i><font color='green'>// 指向当前描述符bdesc,否则表示链表有问题,则显示出错信息,死机。因此,为了将当前描述符</font></i>
<a name='L355'><i><font color='green'>// 从链表中删除,应该让chain 指向下一个描述符。</font></i>
<a name='L356'> <b>else</b>
<a name='L357'> <font color='red'>{</font>
<a name='L358'> <b>if</b> (bdir->chain != bdesc)
<a name='L359'> <a href='../S/72.html#L24' title='Defined at 24 in kernel/panic.c.'>panic</a> ("malloc bucket chains corrupted");
<a name='L360'> bdir->chain = bdesc->next;
<a name='L361'> <font color='red'>}</font>
<a name='L362'><i><font color='green'>// 释放当前描述符所操作的内存页面,并将该描述符插入空闲描述符链表开始处。</font></i>
<a name='L363'> <a href='../S/94.html#L130' title='Defined at 130 in mm/memory.c.'>free_page</a> ((<b>unsigned</b> <b>long</b>) bdesc->page);
<a name='L364'> bdesc->next = free_bucket_desc;
<a name='L365'> free_bucket_desc = bdesc;
<a name='L366'> <font color='red'>}</font>
<a name='L367'><i><font color='green'>// 开中断,返回。</font></i>
<a name='L368'> <a href='../S/25.html#L14' title='Defined at 14 in include/asm/system.h.'>sti</a> ();
<a name='L369'> <b>return</b>;
<a name='L370'><font color='red'>}</font>
</pre>
<hr>
<a name='BOTTOM'>
<i><font color='green'>/* [<][>]<a href='#L154'>[^]</a><a href='#L295'>[v]</a><a href='#TOP'>[top]</a>[bottom]<a href='../mains.html'>[index]</a><a href='../help.html'>[help]</a> */</font></i>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -