免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 850 | 回复: 0
打印 上一主题 下一主题

linux 1.0 内核注解 linux/mm/kmalloc.c [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-19 14:51 |只看该作者 |倒序浏览
/********************************************
*Created By: 陶治江
*Date:       2009-3-16
********************************************/
//呃,编码风格真是糟糕
#include
#include
#include
#define GFP_LEVEL_MASK 0xf
#define MAX_KMALLOC_K 4
#define MAX_GET_FREE_PAGE_TRIES 4
#define MF_USED 0xffaa0055
#define MF_FREE 0x0055ffaa
struct block_header {
unsigned long bh_flags;
union {
  unsigned long ubh_length;
  struct block_header *fbh_next;
} vp;
};
#define bh_length vp.ubh_length
#define bh_next   vp.fbh_next
#define BH(p) ((struct block_header *)(p))
//malloc使用页的前段描述结构,存在于每个页面的前部
struct page_descriptor {
struct page_descriptor *next;
struct block_header *firstfree;
int order;
int nfree;
};
//果真是前端
#define PAGE_DESC(p) ((struct page_descriptor *)(((unsigned long)(p)) & PAGE_MASK))
struct size_descriptor {
struct page_descriptor *firstfree;
int size;   // size*nblocks+16==4K
int nblocks;
int nmallocs;
int nfrees;
int nbytesmalloced;
int npages;
};
//注意最后的一个空项
struct size_descriptor sizes[] = {
{ NULL,  32,127, 0,0,0,0 },
{ NULL,  64, 63, 0,0,0,0 },
{ NULL, 128, 31, 0,0,0,0 },
{ NULL, 252, 16, 0,0,0,0 },
{ NULL, 508,  8, 0,0,0,0 },
{ NULL,1020,  4, 0,0,0,0 },
{ NULL,2040,  2, 0,0,0,0 },
{ NULL,4080,  1, 0,0,0,0 },
{ NULL,   0,  0, 0,0,0,0 }
};
#define NBLOCKS(order)          (sizes[order].nblocks)
#define BLOCKSIZE(order)        (sizes[order].size)
//只是一个宏定义的检查
long kmalloc_init (long start_mem,long end_mem)
{
int order;
  for (order = 0;BLOCKSIZE(order);order++)
     {
      //对一个页的结构进行分析,头大小加上空余的空间应该小于一页内存大的
      if ((NBLOCKS (order)*BLOCKSIZE(order) + sizeof (struct page_descriptor)) >
          PAGE_SIZE)
      {
          printk ("Cannot use %d bytes out of %d in order = %d block mallocs\n",
                  NBLOCKS (order) * BLOCKSIZE(order) +
                          sizeof (struct page_descriptor),
                  (int) PAGE_SIZE,
                  BLOCKSIZE (order));
          panic ("This only happens if someone messes with kmalloc");
      }
     }
     
return start_mem;
}
int get_order (int size)
{
int order;
/* Add the size of the header */
size += sizeof (struct block_header);

for (order = 0;BLOCKSIZE(order);order++)
   //注意,size是不断增加的,所以这里的逻辑没有错的哦
  if (size
return -1;
}
void * kmalloc (size_t size, int priority)
{
unsigned long flags;
int order,tries,i,sz;
struct block_header *p;
struct page_descriptor *page;
extern unsigned long intr_count;
/* Sanity check... */
if (intr_count && priority != GFP_ATOMIC) {
  printk("kmalloc called nonatomically from interrupt %08lx\n",
   ((unsigned long *)&size)[-1]);
  priority = GFP_ATOMIC;
}

if (size > MAX_KMALLOC_K * 1024)  //4K
     {
      printk ("kmalloc: I refuse to allocate %d bytes (for now max = %d).\n",
                 size,MAX_KMALLOC_K*1024);
      return (NULL);
     }
order = get_order (size);
if (order firstfree))
     {
         if (p->bh_flags == MF_FREE)  //必定应该是这样的
         {
             page->firstfree = p->bh_next;  //p=p->bh_next;
             page->nfree--;
            
             if (!page->nfree)  //呃,没了
             {
                 sizes[order].firstfree = page->next;
                 page->next = NULL;
             }
            
             restore_flags(flags);

             sizes [order].nmallocs++;
             sizes [order].nbytesmalloced += size;
            
             p->bh_flags =  MF_USED; /* As of now this block is officially in use */
             p->bh_length = size;
             return p+1; /* Pointer arithmetic: increments past header (块头)*/
         }

         printk ("Problem: block on freelist at %08lx isn't free.\n",(long)p);
         return (NULL);
     }
     
     restore_flags(flags);


     /* Now we're in trouble: We need to get a new free page..... */

     sz = BLOCKSIZE(order); /* sz is the size of the blocks we're dealing with */

     /* This can be done with ints on: This is private to this invocation */
     page = (struct page_descriptor *) __get_free_page (priority & GFP_LEVEL_MASK);
     
     if (!page)
     {
         printk ("Couldn't get a free page.....\n");
         return NULL;
     }

     sizes[order].npages++;

     /* Loop for all but last block: */
     for (i=NBLOCKS(order),p=BH (page+1);
       i > 1;
       i--,p=p->bh_next)
     {
         p->bh_flags = MF_FREE;
         p->bh_next = BH ( ((long)p)+sz);
     }
     
     /* Last block: */
     p->bh_flags = MF_FREE;
     p->bh_next = NULL;   //腾了一个就是为了这个NULL吧

     page->order = order;
     page->nfree = NBLOCKS(order);
     page->firstfree = BH(page+1);
     
     /* Now we're going to muck with the "global" freelist for this size:
        this should be uniterruptible */
     cli ();
     /*
      * sizes[order].firstfree used to be NULL, otherwise we wouldn't be
      * here, but you never know....
      */
     page->next = sizes[order].firstfree;
     sizes[order].firstfree = page;
     restore_flags(flags);
}

//失败
/* Pray that printk won't cause this to happen again :-) */

printk ("Hey. This is very funny. I tried %d times to allocate a whole\n"
         "new page for an object only %d bytes long, but some other process\n"
         "beat me to actually allocating it. Also note that this 'error'\n"
         "message is soooo very long to catch your attention. I'd appreciate\n"
         "it if you'd be so kind as to report what conditions caused this to\n"
         "the author of this kmalloc:
[email=wolff@dutecai.et.tudelft.nl.\n]wolff@dutecai.et.tudelft.nl.\n[/email]
"
         "(Executive summary: This can't happen)\n",
                 MAX_GET_FREE_PAGE_TRIES,
                 size);
return NULL;
}
void kfree_s (void *ptr,int size)
{
  unsigned long flags;
  int order;
  register struct block_header *p=((struct block_header *)ptr) -1;
  struct page_descriptor *page,*pg2;
  page = PAGE_DESC (p);
  order = page->order;
  
  if ((order  sizeof (sizes)/sizeof (sizes[0])) ||
      (((long)(page->next)) & ~PAGE_MASK) ||
      (p->bh_flags != MF_USED))
  {
       printk ("kfree of non-kmalloced memory: %p, next= %p, order=%d\n",
                   p, page->next, page->order);
       return;
  }
  
  if (size &&
      size != p->bh_length)
  {
      printk ("Trying to free pointer at %p with wrong size: %d instead of %lu.\n",
          p,size,p->bh_length);
      return;
  }
  
  size = p->bh_length;
  p->bh_flags = MF_FREE; /* As of now this block is officially free */
  
  save_flags(flags);
  cli ();
  p->bh_next = page->firstfree;  //队列插入进来
  page->firstfree = p;
  page->nfree ++;
  
  if (page->nfree == 1)
  { /* Page went from full to one free block: put it on the freelist */
     if (page->next)
     {
          printk ("Page %p already on freelist dazed and confused....\n", page);
     }
     else
     {
          page->next = sizes[order].firstfree;
          sizes[order].firstfree = page;
     }
  }
  
  /* If page is completely free, free it */
  if (page->nfree == NBLOCKS (page->order))
  {
      if (sizes[order].firstfree == page)
      {
          sizes[order].firstfree = page->next;
      }
      else
      {
          for (pg2=sizes[order].firstfree;
                  (pg2 != NULL) && (pg2->next != page);  //pg2->next==page跳出
                          pg2=pg2->next)
              /* Nothing */;
          if (pg2 != NULL)
              pg2->next = page->next;
          else
              printk ("Ooops. page %p doesn't show on freelist.\n", page);
      }
      free_page ((long)page);
  }
  
  restore_flags(flags);
  
  sizes[order].nfrees++;      /* Noncritical (monitoring) admin stuff */
  sizes[order].nbytesmalloced -= size;
}

文档地址:
http://blogimg.chinaunix.net/blog/upfile2/090319144933.pdf


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u3/90306/showart_1868659.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP