#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. shockt通信

    目前为止,我们使用的最多网络协议还是tcp/ip网络.通常来说,我们习惯上称为tcp/ip协议栈.至于协议栈分成几层,有两种说法.一种是五层,一种是七层. 5.应用层    4.传输层    3.网络 ...

  2. 程序设计入门——C语言 第2周编程练习 1时间换算(5分)

    1 时间换算(5分) 题目内容: UTC是世界协调时,BJT是北京时间,UTC时间相当于BJT减去8.现在,你的程序要读入一个整数,表示BJT的时和分.整数的个位和十位表示分,百位和千位表示小时.如果 ...

  3. combobox获取值

    easyui-combobox是组合框 ,既可以输入,也可以选择 获取的数据是json格式的  [{"id":"001","text":&q ...

  4. php支付宝在线支付接口开发教程【转】

    php支付宝在线支付接口开发教程 这篇文章主要为大家详细介绍了php支付宝在线支付接口开发教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下   1.什么是第三方支付 所谓第三方支付,就是一些和各 ...

  5. web 标准相关

    摘自:http://www.cnblogs.com/artech/p/restful-web-api-01.html 一.TCP/IP与HTTP TCP/IP是以IP和TCP协议为核心的一整套网络协议 ...

  6. 贪心算法 hdu 1009

    1.因为要排序只派j[i]/f[i],不能知道f[i]和j[i]各自排序后的顺序,因此要用到结构体 2.用sort(ware,ware+n,cmp) cmp 为俩个数组的元素比较大小的布尔值 #inc ...

  7. IE6 一些兼容性问题及处理方法

    1.IE6怪异解析之padding与border算入宽高 原因:未加文档声明造成非盒模型解析 解决方法:加入文档声明<!doctype html> 2.IE6在块元素.左右浮动.设定mar ...

  8. String课后作业

    请查看String.equals()方法的实现代码,注意学习其实现方法. public class StringEquals { @param args the command line argume ...

  9. css布局之三列布局

    网站上使用三列布局的还是比较多的,不过三列和两列有些相似: 1.自适应三列 <!DOCTYPE html> <html lang="en"> <hea ...

  10. 关于GSM基站定位

    一、基站定位两个参数 1、什么是LAC:Location Area Code(LAC)地区区域码,用来划分区域 2、什么是CellID:Cell Tower ID(Cid)CellID代表一个移动基站 ...