#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\n",
        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\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)));
    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;
}

//删除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)) != '\0' ; ) {
        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++ = '\n';
    }
    return p - buf;
}

kernel/module.c的更多相关文章

  1. The vboxdrv kernel module is not loaded

    背景: 在没有关虚拟机的情况下, 直接关了电脑, 我的电脑系统是Centos 6 错误的提示: 在终端执行virtualbox -v 时提示 The vboxdrv kernel module is ...

  2. Xamarin.Android模拟器提示HAX kernel module is not Installed

    Xamarin.Android模拟器提示HAX kernel module is not Installed 错误信息:emulator : ERROR : x86 emulation current ...

  3. HAX kernel module is not installed

    dev.android.emulator.haxm 运行emulator -avd xxx来启动名为xxx的模拟器,但报如下错误: emulator: ERROR: x86 emulation cur ...

  4. emulator: ERROR: x86 emulation currently requires hardware acceleration!Please ensure Intel HAXM is properly installed and usable.CPU acceleration status: HAX kernel module is not installed!

    Android Studio 1.0 已经放出来了,以后的Android平台开发激昂逐步从Eclipse向Android Studio迁移,为了能不落伍我也特意从Google下载了Android St ...

  5. Compiling a kernel module for the raspberry pi 2 via Ubuntu host

    Compiling a kernel module for the raspberry pi 2 via Ubuntu host Normally compiling a kernel module ...

  6. Virtualbox报错------>make sure the kernel module has been loaded successfully

    错误描述 很久没有用virtualbox了,今天打算在virtualbox上安装一个Ubuntu系统的时候,新建好Ubuntu后启动的时候,直接报错: Cannot access the kernel ...

  7. qemu 出现Could not access KVM kernel module: No such file or directory failed to initialize KVM: No such file or directory

    使用qemu命令 qemu-system-x86_64 -hda image/ubuntu-test.img -cdrom ubuntu-16.04.2-server-amd64.iso -m 102 ...

  8. 如何处理VirtualBox启动错误消息:The vboxdrv kernel module is not loaded

    我在启动minikube时,遇到如下错误消息: Starting local Kubernetes v1.10.0 cluster... Starting VM... E1010 03:27:37.9 ...

  9. OpenWrt Kernel Module Creation Howto

    OpenWrt Kernel Module Creation Howto About OpenWrt Kernel Module Compilation You are planning to com ...

随机推荐

  1. 第四章· ucos系统及其任务

    来自为知笔记(Wiz)

  2. 当一个类、一个实例域、方法被定义为private、public 时意味着什么

    1.设计private public的原因 2.当一个类.一个实例域.方法被定义为private.public 时意味着什么

  3. VMware技巧01

    1.20160930 VMware® Workstation 10.0.4 build-2249910,使用中遇到问题(WinXP sp3):网卡 桥接模式,NAT模式 都连不上网... 今天,尝试了 ...

  4. FormData、Blob、File、ArrayBuffer数据类型

    XMLHttpRequest 1.0 1.0 中xmlhttpRequest有2个重要的返回属性,reposeText,reposeXml.下面的数据类型都是2.0新增的 FormData对象 我们应 ...

  5. Android系统架构-----Android的系统体系架构

    一.Android的系统体系结构 在入门了一个简单的Android的Hello World以后,我们首先来看一下我们Android的整体系统架构图: 这个就是我们Android的整体系统架构图了,我们 ...

  6. idea首次提交项目

    http://www.cnblogs.com/exmyth/p/6133289.html

  7. 动态规划(一)——最长公共子序列和最长公共子串

    注: 最长公共子序列采用动态规划解决,由于子问题重叠,故采用数组缓存结果,保存最佳取值方向.输出结果时,则自顶向下建立二叉树,自底向上输出,则这过程中没有分叉路,结果唯一. 最长公共子串采用参考串方式 ...

  8. Objective-C( Foundation框架 一 常见的结构体)

    常见的结构体 (NSPoint,CGPoint).(NSRange,CGRange).(NSSize,CGSize) 苹果官方推荐使用CG开头的结构体 NSRange是Foundation框架中常见的 ...

  9. 关于CSS3线型渐变这些事儿

    CSS3兼容各浏览器的线型渐变方法: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...

  10. APIO2015 酱油记

    Day 0 昨天CTSC才比完,当然是要浪啦! 于是浪了一天...午饭都没吃... 晚饭...貌似也没吃... 晚上的时候觉得这样子浪不太好,还是要认真一下,打开bzoj,弃疗了...还是浪吧... ...