⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 malloc.c

📁 带中文注释的 linux 0.11 源代码0.11,很好的
💻 C
📖 第 1 页 / 共 2 页
字号:
malloc (unsigned int len){  struct _bucket_dir *bdir;  struct bucket_desc *bdesc;  void *retval;/** First we search the bucket_dir to find the right bucket change* for this request.*//** 首先我们搜索存储桶目录bucket_dir 来寻找适合请求的桶大小。*/// 搜索存储桶目录,寻找适合申请内存块大小的桶描述符链表。如果目录项的桶字节数大于请求的字节// 数,就找到了对应的桶目录项。  for (bdir = bucket_dir; bdir->size; bdir++)    if (bdir->size >= len)      break;// 如果搜索完整个目录都没有找到合适大小的目录项,则表明所请求的内存块大小太大,超出了该// 程序的分配限制(最长为1 个页面)。于是显示出错信息,死机。  if (!bdir->size)    {      printk ("malloc called with impossibly large argument (%d)\n", len);      panic ("malloc: bad arg");    }/** Now we search for a bucket descriptor which has free space*//** 现在我们来搜索具有空闲空间的桶描述符。*/  cli ();			/* Avoid race conditions *//* 为了避免出现竞争条件,首先关中断 */// 搜索对应桶目录项中描述符链表,查找具有空闲空间的桶描述符。如果桶描述符的空闲内存指针// freeptr 不为空,则表示找到了相应的桶描述符。  for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next)    if (bdesc->freeptr)      break;/** If we didn't find a bucket with free space, then we'll* allocate a new one.*//** 如果没有找到具有空闲空间的桶描述符,那么我们就要新建立一个该目录项的描述符。*/  if (!bdesc)    {      char *cp;      int i;// 若free_bucket_desc 还为空时,表示第一次调用该程序,则对描述符链表进行初始化。// free_bucket_desc 指向第一个空闲桶描述符。      if (!free_bucket_desc)	init_bucket_desc ();// 取free_bucket_desc 指向的空闲桶描述符,并让free_bucket_desc 指向下一个空闲桶描述符。      bdesc = free_bucket_desc;      free_bucket_desc = bdesc->next;// 初始化该新的桶描述符。令其引用数量等于0;桶的大小等于对应桶目录的大小;申请一内存页面,// 让描述符的页面指针page 指向该页面;空闲内存指针也指向该页开头,因为此时全为空闲。      bdesc->refcnt = 0;      bdesc->bucket_size = bdir->size;      bdesc->page = bdesc->freeptr = (void *) cp = get_free_page ();// 如果申请内存页面操作失败,则显示出错信息,死机。      if (!cp)	panic ("Out of memory in kernel malloc()");/* Set up the chain of free objects *//* 在该页空闲内存中建立空闲对象链表 */// 以该桶目录项指定的桶大小为对象长度,对该页内存进行划分,并使每个对象的开始4 字节设置// 成指向下一对象的指针。      for (i = PAGE_SIZE / bdir->size; i > 1; i--)	{	  *((char **) cp) = cp + bdir->size;	  cp += bdir->size;	}// 最后一个对象开始处的指针设置为0(NULL)。// 然后让该桶描述符的下一描述符指针字段指向对应桶目录项指针chain 所指的描述符,而桶目录的// chain 指向该桶描述符,也即将该描述符插入到描述符链链头处。      *((char **) cp) = 0;      bdesc->next = bdir->chain;	/* OK, link it in! *//* OK,将其链入! */      bdir->chain = bdesc;    }// 返回指针即等于该描述符对应页面的当前空闲指针。然后调整该空闲空间指针指向下一个空闲对象,// 并使描述符中对应页面中对象引用计数增1。  retval = (void *) bdesc->freeptr;  bdesc->freeptr = *((void **) retval);  bdesc->refcnt++;// 最后开放中断,并返回指向空闲内存对象的指针。  sti ();			/* OK, we're safe again *//* OK,现在我们又安全了 */  return (retval);}/** Here is the free routine. If you know the size of the object that you* are freeing, then free_s() will use that information to speed up the* search for the bucket descriptor.** We will #define a macro so that "free(x)" is becomes "free_s(x, 0)"*//** 下面是释放子程序。如果你知道释放对象的大小,则free_s()将使用该信息加速* 搜寻对应桶描述符的速度。** 我们将定义一个宏,使得"free(x)"成为"free_s(x, 0)"。*///// 释放存储桶对象。// 参数:obj - 对应对象指针;size - 大小。voidfree_s (void *obj, int size){  void *page;  struct _bucket_dir *bdir;  struct bucket_desc *bdesc, *prev;/* Calculate what page this object lives in *//* 计算该对象所在的页面 */  page = (void *) ((unsigned long) obj & 0xfffff000);/* Now search the buckets looking for that page *//* 现在搜索存储桶目录项所链接的桶描述符,寻找该页面 *///  for (bdir = bucket_dir; bdir->size; bdir++)    {      prev = 0;/* If size is zero then this conditional is always false *//* 如果参数size 是0,则下面条件肯定是false */      if (bdir->size < size)	continue;// 搜索对应目录项中链接的所有描述符,查找对应页面。如果某描述符页面指针等于page 则表示找到// 了相应的描述符,跳转到found。如果描述符不含有对应page,则让描述符指针prev 指向该描述符。      for (bdesc = bdir->chain; bdesc; bdesc = bdesc->next)	{	  if (bdesc->page == page)	    goto found;	  prev = bdesc;	}    }// 若搜索了对应目录项的所有描述符都没有找到指定的页面,则显示出错信息,死机。  panic ("Bad address passed to kernel free_s()");found:// 找到对应的桶描述符后,首先关中断。然后将该对象内存块链入空闲块对象链表中,并使该描述符// 的对象引用计数减1。  cli ();			/* To avoid race conditions *//* 为了避免竞争条件 */  *((void **) obj) = bdesc->freeptr;  bdesc->freeptr = obj;  bdesc->refcnt--;// 如果引用计数已等于0,则我们就可以释放对应的内存页面和该桶描述符。  if (bdesc->refcnt == 0)    {/** We need to make sure that prev is still accurate. It* may not be, if someone rudely interrupted us....*//** 我们需要确信prev 仍然是正确的,若某程序粗鲁地中断了我们* 就有可能不是了。*/// 如果prev 已经不是搜索到的描述符的前一个描述符,则重新搜索当前描述符的前一个描述符。      if ((prev && (prev->next != bdesc)) ||	  (!prev && (bdir->chain != bdesc)))	for (prev = bdir->chain; prev; prev = prev->next)	  if (prev->next == bdesc)	    break;// 如果找到该前一个描述符,则从描述符链中删除当前描述符。      if (prev)	prev->next = bdesc->next;// 如果prev==NULL,则说明当前一个描述符是该目录项首个描述符,也即目录项中chain 应该直接// 指向当前描述符bdesc,否则表示链表有问题,则显示出错信息,死机。因此,为了将当前描述符// 从链表中删除,应该让chain 指向下一个描述符。      else	{	  if (bdir->chain != bdesc)	    panic ("malloc bucket chains corrupted");	  bdir->chain = bdesc->next;	}// 释放当前描述符所操作的内存页面,并将该描述符插入空闲描述符链表开始处。      free_page ((unsigned long) bdesc->page);      bdesc->next = free_bucket_desc;      free_bucket_desc = bdesc;    }// 开中断,返回。  sti ();  return;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -