免费注册 查看新帖 |

Chinaunix

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

linux 1.0 内核注解 linux/kernel/module.c [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-03-11 13:48 |只看该作者 |倒序浏览
/********************************************
*Created By: 陶治江
*Date:       2009-3-7
*Blog:   
http://taozhijiangscu.cublog.cn
********************************************/

//内核模块,应该是驱动开发者最关注的~~
//但是这个程序写的简直很糟糕 :-(
#include
#include
#include
#include   /* defines GFP_KERNEL */
#include
#include
#include
#include
//struct module {
// struct module *next;
// char *name;
// int size;   /* size of module in pages */
// void* addr;   /* address of module */
// int state;
// void (*cleanup)(void);  /* cleanup routine,卸载例程 */
//};
//struct mod_routines {
// int (*init)(void);  /* initialization routine */
// void (*cleanup)(void);  /* cleanup routine */
//};
struct module *module_list = NULL;
int freeing_modules;  // true if some modules are marked for deletion
       //卸载同真正的资源释放不再同一步
struct module *find_module( const char *name);
int get_mod_name( char *user_name, char *buf);
int free_modules( void);
//创建模块
asmlinkage int sys_create_module(char *module_name, unsigned long size)
{
int npages;
void* addr;
int len;
char name[MOD_MAX_NAME];  //64
char *savename;
struct module *mp;
int error;
if (!suser())
  return -EPERM;
if (module_name == NULL || size == 0)
  return -EINVAL;

//将用户空间的module_name -> name
if ((error = get_mod_name(module_name, name)) != 0)
  return error;
  
if (find_module(name) != NULL) {  //指定的模块名已经存在了
  return -EEXIST;
}

len = strlen(name) + 1;
if ((savename = (char*) kmalloc(len, GFP_KERNEL)) == NULL)
  return -ENOMEM;
memcpy(savename, name, len);
if ((mp = (struct module*) kmalloc(sizeof *mp, GFP_KERNEL)) == NULL) {
  kfree(savename);
  return -ENOMEM;
}

//npages向页取整
npages = (size + sizeof (int) + 4095) / 4096;
if ((addr = vmalloc(npages * 4096)) == 0) {
  kfree_s(mp, sizeof *mp);
  kfree(savename);
  return -ENOMEM;
}
mp->name = savename;
mp->size = npages;
mp->addr = addr;
mp->state = MOD_UNINITIALIZED;
* (int *) addr = 0;  /* set use count to zero */
       //这里的位置是模块结构根据size分配的页内存,可能
       //开头用来保存了引用计数吧
mp->cleanup = NULL;
mp->next = module_list;
module_list = mp;
printk("module `%s' (%lu pages @ 0x%08lx) created\n",
  mp->name, (unsigned long) mp->size, (unsigned long) mp->addr);
return (int) addr;
}
// Initialize a module
asmlinkage int sys_init_module(char *module_name, char *code, unsigned codesize,
     struct mod_routines *routines)
{
struct module *mp;
char name[MOD_MAX_NAME];
int error;
struct mod_routines rt;
if (!suser())
  return -EPERM;
/*
  * First reclaim any memory from dead modules that where not
  * freed when deleted. Should I think be done by timers when
  * the module was deleted - Jon.
  */
free_modules();
if ((error = get_mod_name(module_name, name)) != 0)
  return error;
printk( "initializing module `%s', %d (0x%x) bytes\n",
  name, codesize, codesize);
memcpy_fromfs(&rt, routines, sizeof rt);

if ((mp = find_module(name)) == NULL)
  return -ENOENT;
  
if ((codesize + sizeof (int) + 4095) / 4096 > mp->size)
  return -EINVAL;
  
memcpy_fromfs((char *)mp->addr + sizeof (int), code, codesize);
memset((char *)mp->addr + sizeof (int) + codesize, 0,
  mp->size * 4096 - (codesize + sizeof (int)));  //除了开头的int和code之外全部清零
  
printk( "  init entry @ 0x%08lx, cleanup entry @ 0x%08lx\n",
  (unsigned long) rt.init, (unsigned long) rt.cleanup);
mp->cleanup = rt.cleanup;
if ((*rt.init)() != 0)   //调用特定的模块初始化函数,初始化函数
         //只调用一次,没有保存在模块结构中
  return -EBUSY;
mp->state = MOD_RUNNING;
return 0;
}
asmlinkage int sys_delete_module(char *module_name)
{
struct module *mp;
char name[MOD_MAX_NAME];
int error;
if (!suser())
  return -EPERM;
if (module_name != NULL) {
  if ((error = get_mod_name(module_name, name)) != 0)
   return error;
  if ((mp = find_module(name)) == NULL)
   return -ENOENT;
  if (mp->state == MOD_RUNNING)
   (*mp->cleanup)();  //调用自己的历程
  mp->state = MOD_DELETED;
}
free_modules();
return 0;
}
// Copy the kernel symbol table to user space.  If the argument is null,
// just return the size of the table.
//struct kernel_sym {
// unsigned long value;  /* value of symbol */
// char name[SYM_MAX_NAME]; /* name of symbol */  //60
//};
asmlinkage int sys_get_kernel_syms(struct kernel_sym *table)
{
struct symbol {
  unsigned long addr;
  char *name;
};
extern int symbol_table_size;
extern struct symbol symbol_table[];
int i;
struct symbol *from;
struct kernel_sym *to;
struct kernel_sym sym;
if (table != NULL) {
  from = symbol_table;
  to = table;
  i = verify_area(VERIFY_WRITE, to, symbol_table_size * sizeof *table);
  if (i)
   return i;
  for (i = symbol_table_size ; --i >= 0 ; ) {
   sym.value = from->addr;   
   strncpy(sym.name, from->name, sizeof sym.name);
   memcpy_tofs(to, &sym, sizeof sym);   //结构的拷贝
   from++, to++;
  }
}
return symbol_table_size;
}
//从用户空间把模块名拷贝到内核空间 ->
//0 indicates success
int get_mod_name(char *user_name, char *buf)
{
int i;
i = 0;
for (i = 0 ; (buf = get_fs_byte(user_name + i)) != '\0' ; ) {
  if (++i >= MOD_MAX_NAME)
   return -E2BIG;
}
return 0;
}
// Look for a module by name, ignoring modules marked for deletion
struct module * find_module( const char *name)
{
struct module *mp;
for (mp = module_list ; mp ; mp = mp->next) {
  if (mp->state == MOD_DELETED)
   continue;
  if (!strcmp(mp->name, name))  //相等,跳出
   break;
}
return mp;
}
//只有调用这个函数才会真正的把要删除的模块的资源进行
//回收,所以应该在模块改动的时候尽量调用这个函数
int free_modules( void)
{
struct module *mp;
struct module **mpp;
int did_deletion;
did_deletion = 0;   //标记,非零表示真的删除了
freeing_modules = 0;
mpp = &module_list;
while ((mp = *mpp) != NULL) {
  if (mp->state != MOD_DELETED) {
   mpp = &mp->next;
//mp->state == MOD_DELETED
//#define GET_USE_COUNT(module) (* (int *) (module)->addr)  //获得使用计数
  } else if (GET_USE_COUNT(mp) != 0) {
   freeing_modules = 1;
   mpp = &mp->next;  
  //这里mp->state == MOD_DELETED 而且资源的引用次数也是0
  //于是可以进行资源的回收了
  } else { /* delete it */
   *mpp = mp->next;  //记录了下面一个,这个mp可以安全的删除了
   vfree(mp->addr);
   kfree(mp->name);
   kfree_s(mp, sizeof *mp);
   did_deletion = 1;
  }
}
return did_deletion;
}
// Called by the /proc file system to return a current list of modules.
int get_module_list(char *buf)
{
char *p;
char *q;
int i;
struct module *mp;
char size[32];
p = buf;
for (mp = module_list ; mp ; mp = mp->next) {
  if (p - buf > 4096 - 100)
   break;   /* avoid overflowing buffer */
  q = mp->name;
  i = 20;
  while (*q) {
   *p++ = *q++;  //复制名字
   i--;
  }
  sprintf(size, "%d", mp->size);  //格式化字符串
  i -= strlen(size);
  if (i = 0)
   *p++ = ' ';   //填补空格
  q = size;
  while (*q)
   *p++ = *q++;
  if (mp->state == MOD_UNINITIALIZED)
   q = "  (uninitialized)";
  else if (mp->state == MOD_RUNNING)
   q = "";
  else if (mp->state == MOD_DELETED)
   q = "  (deleted)";
  else
   q = "  (bad state)";
  while (*q)
   *p++ = *q++;
  *p++ = '\n';
}
return p - buf;
}

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


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

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP