一开始 编译模块时,使用了gcc,搞出了笑话哈哈,不了解模块的基本内容了
1.写完一段模块程序后,包括作基本的module_init(globalmem_init)和module_exit(globalmem_exit)等;
2.写一个基本的makefile文件,来进行编译;
3.运行make(makefile中已写入了生成模块的命令),生成globalmem.ko模块;
4.两个方式加载模块:insmod globalmem.ko 和将globalmem.ko复制到/lib/modules/2.6.23.1-42.fc8/下,运行
depmod -a 命令生成模块依赖关系写入module .dep,最后运行modprobe globalmem命令;
ok!
以下参考:http://www.ajaxstu.com/neiheyuanma/270873.html 多谢 在网上找了好久阿
linux下加载模块的两个命令 modprobe 和insmod
1. modprobe能自动处理模块间的依赖关系。在安装一个模块时,能自动安装该模块所需的其它模块;insmod加载时不需要
依赖的模块,直接加载模块。
2. modprobe加载时,先将要加载的模块放入模块搜索路径(我的放在/lib/modules/2.6.23.1-42.fc8/下);
再运行depmod -a(depmod -a,它是生成相关依赖并写如到module.dep中 ) ;再运行modprobe xx即可。
3. insmod加载时,只需要进入模块所在目录,运行命令insmod xx.ko即可
关于在字符设备中建立设备节点的问题:
在使用insmod进行模块加载时,如果程序中未在处理,应手动使用命令mknod /dev/xxx c 250 0 进行设备节点的建立;
在udev中可以使用函数进行自动建立设备节点, (Linux 内核为我们提供了一组函数,可以用来在模块加载的时候自动在
/dev目录下创建相应设备节点,并在卸载模块时删除该节点,当然前提条件是用户空间移植了udev。)
具体在globalmem_init()函数中加入
///-----------------------------------------------------
/* create your own class under /sysfs */
globalmem_class = class_create(THIS_MODULE, "globalmem");
if(IS_ERR(globalmem_class))
{
printk("Err: failed in creating class./n");
return -1;
}
/* register your own device in sysfs, and this will cause udev to create corresponding device node */
device_create(globalmem_class, NULL, MKDEV(globalmem_major, 0), "globalmem",0);
printk (KERN_INFO "Registered character driver/n");
//----------------------------------------------------
在globalmem_exit()函数中加入
//---------------------
device_destroy(globalmem_class,MKDEV(globalmem_major,0));
class_destroy(globalmem_class);
//---------------------
看似终于对globalmem这个虚拟字符设备有了部分的了解了,现在总结一下一些很可笑的错误:
1. 对于echo的了解 使用ehco ‘hello’>/dev/xxx 后会自动在/dev目录下生成一个普通的文件,一开始搞不懂,以为不需要 建立设备节点就可以使用echo测试了,还是需要手动建立设备节点或在程序中添加建立设备节点的代码。
2. 出现如下的一个错误,在网上怎么都搜不到的
bash: echo: write error: 无效的参数
后来下了源代码测试没问题,
这是编译时出现的警告 /root/driver/globalmem/globalmem.c:85: 警告:‘globalmem_write’ 定义后未使用
然后仔细想了原因,原来是在struct file_operations的赋值中没有将globalmem_write赋值给文件的结构体。
真是无语了,估计没人有这样的错误了。。。。。错误天才了哈哈
3. 最后一个问题是源程序的问题,出现如下错误:
hello
cat: /dev/globalmem: 没有那个设备或地址
在网上找了答案,globalmem _ read函数中的if (p >= GLOBALMEM _SIZE)改为if (p > GLOBALMEM _SIZE)
是一个指针的越界问题。
附1:depmod的解释
depmod(depend module) 信息来自"岁月联盟"
功能说明: 分析可载入模块的相依性。
语 法: depmod [-adeisvV][-m <文件>][--help][模块名称]
补充说明: depmod可检测模块的相依性,供modprobe在安装模块时使用。
参 数:
-a或--all 分析所有可用的模块。
-d或debug 执行排错模式。
-e 输出无法参照的符号。
-i 不检查符号表的版本。
-m<文件>或system-map<文件> 使用指定的符号表文件。
-s或--system-log 在系统记录中记录错误。
-v或--verbose 执行时显示详细的信息。
-V或--version 显示版本信息。
--help 显示帮助。
附2:
使用的makfile文件
ifneq ($(KERNELRELEASE),)
obj-m := globalmem.o
# Otherwise we were called directly from the command
# line; invoke the kernel build system.
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KERNELDIR) SUBDIRS=$(PWD) modules
endif
clean:
$(shell rm -f *.bak)
$(shell rm -f globalmem.o)
$(shell rm -f globalmem.ko)
$(shell rm -f globalmem.mod.c)
$(shell rm -f globalmem.mod.o)
$(shell rm -f Module.symvers)
附3:转自:(华清远见 http://www.embedu.org/index.htm)
内核中定义了struct class结构体,顾名思义,一个struct class结构体类型变量对应一个类,内核同时提供了class_create(…)函数,可以用它来创建一个类,这个类存放于sysfs下面,一旦创建 好了这个类,再调用device_create(…)函数来在/dev目录下创建相应的设备节点。这样,加载模块的时候,用户空间中的udev会自动响应 device_create(…)函数,去/sysfs下寻找对应的类从而创建设备节点。
注意,在2.6较早的内核版本中,device_create(…)函数名称不同,是class_device_create(…),所以在新的内核中编译以前的模块程序有时会报错,就是因为函数名称不同,而且里面的参数设置也有一些变化。
struct class和device_create(…) 以及device_create(…)都定义在/include/linux/device.h中,使用的时候一定要包含这个头文件,否则编译器会报错。
在2.6.26.6内核版本中,struct class定义在头文件include/linux/device.h中:
/*
* device classes
*/
struct class {
const char *name;
struct module *owner;
nbsp;struct kset subsys;
struct list_head devices;
struct list_head interfaces;
struct kset class_dirs;
struct semaphore sem; /* locks children, devices, interfaces */
struct class_attribute *class_attrs;
struct device_attribute *dev_attrs;
int (*dev_uevent)(struct device *dev, struct kobj_uevent_env *env);
void (*class_release)(struct class *class);
void (*dev_release)(struct device *dev);
int (*suspend)(struct device *dev, pm_message_t state);
int (*resume)(struct device *dev);
};
class_create(…)在/drivers/base/class.c中实现:
/**
* class_create - create a struct class structure
* @owner: pointer to the module that is to "own" this struct class
* @name: pointer to a string for the name of this class.
*
* This is used to create a struct class pointer that can then be used
* in calls to device_create().
*
* Note, the pointer created here is to be destroyed when finished by
* making a call to class_destroy().
*/
struct class *class_create(struct module *owner, const char *name)
{
struct class *cls;
int retval;
cls = kzalloc(sizeof(*cls), GFP_KERNEL);
if (!cls) {
retval = -ENOMEM;
goto error;
}
cls->name = name;
cls->owner = owner;
cls->class_release = class_create_release;
retval = class_register(cls);
if (retval)
goto error;
return cls;
error:
kfree(cls);
return ERR_PTR(retval);
}
第一个参数指定类的所有者是哪个模块,第二个参数指定类名。
在class.c中,还定义了class_destroy(…)函数,用于在模块卸载时删除类。
device_create(…)函数在/drivers/base/core.c中实现:
/**
* device_create - creates a device and registers it with sysfs
* @class: pointer to the struct class that this device should be registered to
* @parent: pointer to the parent struct device of this new device, if any
* @devt: the dev_t for the char device to be added
* @fmt: string for the device's name
*
* This function can be used by char device classes. A struct device
* will be created in sysfs, registered to the specified class.
*
* A "dev" file will be created, showing the dev_t for the device, if
* the dev_t is not 0,0.
* If a pointer to a parent struct device is passed in, the newly created
* struct device will be a child of that device in sysfs.
* The pointer to the struct device will be returned from the call.
* Any further sysfs files that might be required can be created using this
* pointer.
*
* Note: the struct class passed to this function must have previously
* been created with a call to class_create().
*/
struct device *device_create(struct class *class, struct device *parent,
dev_t devt, const char *fmt, ...)
{
va_list vargs;
struct device *dev;
va_start(vargs, fmt);
dev = device_create_vargs(class, parent, devt, NULL, fmt, vargs);
va_end(vargs);
return dev;
}
第一个参数指定所要创建的设备所从属的类,第二个参数是这个设备的父设备,如果没有就指定为NULL,第三个参数是设备号,第四个参数是设备名称,第五个参数是从设备号。