zoukankan      html  css  js  c++  java
  • kernel/module.c

    #include <linux/errno.h>
    #include <linux/kernel.h>
    #include <asm/segment.h>
    #include <linux/mm.h>        /* defines GFP_KERNEL */
    #include <linux/string.h>
    #include <linux/module.h>
    #include <linux/sched.h>
    #include <linux/malloc.h>

    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);

    /*
     * Allocate space for a module.
     */
    //系统调用,创建module,为module分配空间
    asmlinkage int
    sys_create_module(char *module_name, unsigned long size)
    {
        int npages;
        void* addr;
        int len;
        char name[MOD_MAX_NAME];
        char *savename;
        struct module *mp;
        int error;

        //如果不是超级用户root,则退出
        if (!suser())
            return -EPERM;
        //如果模块的名称为空或者长度为0,则退出
        if (module_name == NULL || size == 0)
            return -EINVAL;
        //根据模块的名称,获取name
        if ((error = get_mod_name(module_name, name)) != 0)
            return error;
        //搜索module
        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 = (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 */
        mp->cleanup = NULL;
        mp->next = module_list;
        module_list = mp;
        printk("module `%s' (%lu pages @ 0x%08lx) created ",
            mp->name, (unsigned long) mp->size, (unsigned long) mp->addr);
        return (int) addr;
    }

    /*
     * Initialize a module.
     */
    //初始化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 ",
            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)));
        printk( "  init entry @ 0x%08lx, cleanup entry @ 0x%08lx ",
            (unsigned long) rt.init, (unsigned long) rt.cleanup);
        mp->cleanup = rt.cleanup;
        if ((*rt.init)() != 0)
            return -EBUSY;
        mp->state = MOD_RUNNING;
        return 0;
    }

    //删除module
    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.
     */
    //获取内核符号表
    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;
    }


    /*
     * Copy the name of a module from user space.
     */
     //获取mod的名称
    int
    get_mod_name(char *user_name, char *buf)
    {
        int i;

        i = 0;
        for (i = 0 ; (buf[i] = get_fs_byte(user_name + i)) != '' ; ) {
            if (++i >= MOD_MAX_NAME)
                return -E2BIG;
        }
        return 0;
    }


    /*
     * Look for a module by name, ignoring modules marked for deletion.
     */
     //搜索module
    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;
    }


    /*
     * Try to free modules which have been marked for deletion.  Returns nonzero
     * if a module was actually freed.
     */
     //释放module
    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;
            } else if (GET_USE_COUNT(mp) != 0) {
                freeing_modules = 1;
                mpp = &mp->next;
            } else {    /* delete it */
                *mpp = mp->next;
                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.
     */
     //获取所有的module
    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)
                i = 1;
            while (--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++ = ' ';
        }
        return p - buf;
    }

  • 相关阅读:
    PDF文档生成缩略图
    zTree数据回显
    window.showModalDialog基础
    Java获取两个时间段内的所有日期
    CSS设置超出表格的内容用省略号显示
    Ajax提交form表单
    普通java类在Tomcat启动时获取ServletContext
    mysql中sql优化和合理使用索引
    mysql数据类型详解系列
    如何干净的清除slave同步信息
  • 原文地址:https://www.cnblogs.com/xiaofengwei/p/3774754.html
Copyright © 2011-2022 走看看