insmod: error inserting 'main.ko': -1 Unknown symbol in module
ldd3第三章的字符设备驱动是在2.6.10内核上写的,如果要在更高的版本上使用,则编译和使用都需要进行修改。
关于编译方面进行的修改,网上相关的很多,自己也可以根据自己的进行修改。
1、在书上配套的代码中,动态加载主设备的设备驱动程序,使用了一个脚本,该脚本在自己的系统中不能正常使用,提示mknod 命令错误,
该问题留待进行解决。
2、自己用命令的方式如下:
读取 /proc/devices 获得新分配的设备号。
mknod /dev/scull0 c 250 0 创建相应的设备文件。
注意修改设备 文件的访问权限 chmod 0+w /dev/scull 否则,只有超级用户才可以进行访问该设备文件。
然后就可以对该设备文件,进行相应的测试了。
3、关于SCULL内存使用
图表可以见书65页。 注意每个设备都是一个指针链表,scull_qset 结构中(每一个这样的结构可以引用4 000 000 bytes),4 000 000 = 1 000(量子集) * 4 000(量子)
对这种设备布局的理解是读懂程序的关键。而读懂程序,scull_read 中的一段更具代表性。
ssize_t scull_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
struct scull_dev *dev = filp->private_data;
struct scull_qset *dptr; / * the first listitem (listitem prefers to scull_qset)* /
int quantum = dev->quantum, qset = dev->qset;
int itemsize = quantum * qset; / * how many bytes in the listitem * /
int item, s_pos, q_pos, rest;
ssize_t retval = 0;
if (down_interruptible(&dev->sem))
{
return -ERESTARTSYS;
}
if (*f_pos >= dev->size)
{
goto out;
}
if (*f_pos + count > dev->size)
{
count = dev->size - *f_pos;
}
/ * find listitem, qset index, and offset in the quantum * /
item = (long)*f_pos / itemsize; //定位要读取的数据在那个scull_qset
rest = (long)*f_pos % itemsize; //定位要读取的数据scull_qset中的偏移量,是中间变量。
s_pos = rest / quantum; //定位要读取的数据在哪个quantum
q_pos = rest % quantum; //定位要读取的数据在quantum中的偏移量
/ * follow the list up to the right position (defined elsewhere) * /
dptr = scull_follow(dev, item);
if ((dptr == NULL) || !dptr->data || !dptr->data[s_pos])
{
goto out;
} / * don't fill holes * /
/ * read only up to the end of this quantum * /
/ * 该函数一次只读取一个的quantum,跨quantum的数据不能全部读取* /
if (count > quantum - q_pos)
{
count = quantum - q_pos;
}
/ *
Function copy_to_user and copy_from_user copy a whole segment of data to or from
the user address space.
* /
if (copy_to_user(buf, dptr->data[s_pos] + q_pos, count))
{
retval = -EFAULT;
goto out;
}
*f_pos += count;
retval = count;
out:
up(&dev->sem);
return retval;
}
4、为了对程序有更好的理解,要自己重新 对程序进行修改,加上打印信息。
然后,我把main.c和 那个头文件拷贝到其他的目录下,自己写的Makefiel,编译可以通过,但是在 插入模块时,发生下面的错误:
insmod: error inserting 'main.ko': -1 Unknown symbol in module
在网上说,内核中使用了以前内核是用的宏之类的东西。
可以使用 日志文件来查看错误信息 : /var/log/message
Apr 8 15:46:20 ubuntu kernel: [21786.371081] main: Unknown symbol scull_access_cleanup (err 0)
所以,问题是 scull_access_cleanup()在另一文件中国定义。
所以,把scull文件夹里的代码全部拷贝了过来,
注意要重新修改Makefile了。
KVER = $(shell uname -r)
scull-objs := main.o pipe.o access.o
obj-m := scull.o
kernel_modules:
make -C /lib/modules/$(KVER)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(KVER)/build M=$(PWD) clean
在插入模块后,查看 日志文件的打印信息入下:
Apr 8 16:01:53 ubuntu kernel: [22716.931129] scullsingle registered at fa00008
Apr 8 16:01:53 ubuntu kernel: [22716.931149] sculluid registered at fa00009
Apr 8 16:01:53 ubuntu kernel: [22716.931152] scullwuid registered at fa0000a
Apr 8 16:01:53 ubuntu kernel: [22716.931154] sullpriv registered at fa0000b
小知识:如何删除在 /dev目录下的一个设备节点。
sudo rm /dev/scu_dev
root@ubuntu:/home/wangkai/Documents/test# sudo chmod o+w /dev/scull0
上面这个一定要注意啊。。
为了调试,可以在代码中,加上自己的一下诶调试信息,
在函数 scull_write()的入口加上下面的调试信息:
printk("Debug by wang_kai:scull_write\n");
然后,想设备写内容。 打开 /vzr/log/message 后,就可以看到调试信息了
Apr 8 16:17:38 ubuntu kernel: [23659.823762] Debug by wang_kai:scull_write
但是,一直不能在日志文件中,看到打印信息。原因在于,我是这样添加的:
printk(KERN_ALERT "Debug by wang_kai :scull_init_nodule\n");
加上了,KERN_ALERT.,不能显示。 原因不知道,留有以后分析。