您的位置:首页 > 运维架构 > Linux

LDD3 范例程序在新版本内核下的问题及解决办法(linux—2.6.38.8)

2011-12-14 11:43 741 查看
Linux内核从2.6.18到2 .6.19发生了较大变化,而《limux设备驱动程序3》中的程序是针对2.6.10内核的,在使用包含较新版本内核的linux发行版编译这些程序时,总不是向书上说的那么顺利,在此总结一下遇到的问题和解决办法,本篇日志会随着我的进度进行更新,有些问题可能发现了我也暂时解决不了,欢迎交流。

scull:

1)编译main.c时提示错误:main.c:17:26: error: linux/config.h: No such file or directory

解决办法:把#include<linux/config.h>注释掉或者在内核源码中创建空的config.h文件,从2.6.19后的新版本的内核已经不再包含config.h文件了,参见。

2)编译access.c时提示错误:

/home/lits/test/access.c: In function ‘scull_u_open’:

/home/lits/test/access.c:108: error: dereferencing pointer to incomplete type

/home/lits/test/access.c:109: error: dereferencing pointer to incomplete type

/home/lits/test/access.c:116: error: dereferencing pointer to incomplete type

/home/lits/test/access.c: In function ‘scull_w_available’:

/home/lits/test/access.c:167: error: dereferencing pointer to incomplete type

/home/lits/test/access.c:168: error: dereferencing pointer to incomplete type

/home/lits/test/access.c: In function ‘scull_w_open’:

/home/lits/test/access.c:181: error: ‘TASK_INTERRUPTIBLE’ undeclared (first use in this function)

/home/lits/test/access.c:181: error: (Each undeclared identifier is reported only once

/home/lits/test/access.c:181: error: for each function it appears in.)

/home/lits/test/access.c:181: error: implicit declaration of function ‘signal_pending’

/home/lits/test/access.c:181: error: implicit declaration of function ‘schedule’

/home/lits/test/access.c:186: error: dereferencing pointer to incomplete type

/home/lits/test/access.c: In function ‘scull_w_release’:

/home/lits/test/access.c:207: error: ‘TASK_INTERRUPTIBLE’ undeclared (first use in this function)

/home/lits/test/access.c: In function ‘scull_c_open’:

/home/lits/test/access.c:279: error: dereferencing pointer to incomplete type

/home/lits/test/access.c:283: error: dereferencing pointer to incomplete type

/home/lits/test/access.c: In function ‘scull_access_setup’:

/home/lits/test/access.c:356: warning: format not a string literal and no format arguments


解决办法:在access.c中添加 #include <linux/sched.h>即可正常编译产生模块文件。

今天试着编译LDD3例子源代码中的scull模块,出现了问题

参照下面的文章解决了问题:http://blog.163.com/chenfang7977@yeah/blog/static/1282741962010219327201/

内核版本:2.6.27

1、提示scripts/Makefile.build:46:*** CFLAGS was changed in "/home/chenfang/scull/Makefile",Fix it use EXTRA_CFLAGS.Stop.:

由于LDD3使用的是2.6.10内核,很多东西已经发生了变化,这里提示我们修改Makefile中的CFLAGS,用EXTRA_CFLAGS代替,照它说的做就可以。

2、提示找不到文件linux/config.h:

在2.6.19开始的内核中删除了config.h文件,因此只要在mian.c中注释掉#include<linux/config.h>即可。

3、提示access.c中存在:dereferencing pointer to incomplete type 错误:

在 源码中发现只能是current存在错误,current应该是一个task_struct类型的全局变量,查找task_struct存在于 linux/sched.h中,因此在access.c中加入#include<linux/sched.h>,重新make即可。

顺便看下current这个全局变量是在哪里定义的:

在source ininsight中查找得到的current类似于以下的定义:

static inline struct task_struct *get_current(void) __attribute_const__;

static inline struct task_struct *get_current(void)

{

return current_thread_info()->task;

}

#define current (get_current())

可 见,current其实是一个“伪全局变量”,是函数get_current()的宏定义。当access.c中使用current->uid时, 就调用了get_current()函数,从而返回task_struct结构的task,因此current->uid就相当于 task->uid。

make成功后,在scull目录下生成了scull.ko文件,命令:chomd +x scull_load scull_unload 使这两个脚本变为可执行。

./scull_load 挂载scull.ko模块

./scull_unload 卸载

scull_load脚本是对insmod的调用,该脚本在调用insmod之后读取/proc/devices以获得新分配的主设备号,然后创建对应的设备文件。
$DEVICE.ko

以下是我的实践收获:

另外,scull例子源码目录中还提供了一个脚本scull.init可以完成,scull_load 和scull_unload 的工作。

直接运行这个脚本sudo ./scull.init start会提示失败:

Loading scull (loading file ./scull.o)insmod: error inserting './scull.o': -1 Invalid module format

FAILED!

.

回到scull.init中把 $DEVICE.o改成$DEVICE.ko即可。

ps;前面定义了DEVECE=scull
error :implicit declaration of function 'init_MUTEX'

后来一查,在新版本的linux内核中,init_mutex已经被废除了。

查了一下早期版本的定义。

平台:X86 32位

内核:2.6.24

定义

static inline void init_MUTEX (struct semaphore *sem)

{

sema_init(sem, 1);

}


说明:Init_MUTEX()函数初始化信号量为互斥量。 互斥量为信号量的特例,它可以防止数据被两个不同系统调用读写。

static inline void sema_init (struct semaphore *sem, int val)

{

/*

* *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);

*

* i'd rather use the more flexible initialization above, but sadly

* GCC 2.7.2.3 emits a bogus warning. EGCS doesn't. Oh well.

*/

atomic_set(&sem->count, val);

sem->sleepers = 0;

init_waitqueue_head(&sem->wait);

}

sleepers : 指定了允许进入等待进入临界区的进程数,这里初始化为 0 。

init_waitqueue_head() : 初始化一个等待队列头。

根据代码判断,只要在init_mutex的地方直接使用sema_init来替换,试了一些,果然可以成功make。

代码大概是这样的init_MUTEX(&wl->sem); 手动修改为 sema_init(&wl->sem,1); 然后再进行编译就可以。

1、提示scripts/Makefile.build:46:*** CFLAGS was changed in "/home/chenfang/scull/Makefile",Fix it use EXTRA_CFLAGS.Stop.:

由于LDD3使用的是2.6.10内核,很多东西已经发生了变化,这里提示我们修改Makefile中的CFLAGS,用EXTRA_CFLAGS代替,照它说的做就可以。

2、提示找不到文件linux/config.h:

在2.6.19开始的内核中删除了config.h文件,因此只要在mian.c中注释掉#include<linux/config.h>即可。

3、提示access.c中存在:dereferencing pointer to incomplete type 错误:

在 源码中发现只能是current存在错误,current应该是一个task_struct类型的全局变量,查找task_struct存在于 linux/sched.h中,因此在access.c中加入#include<linux/sched.h>,重新make即可。

顺便看下current这个全局变量是在哪里定义的:

在source ininsight中查找得到的current类似于以下的定义:

static inline struct task_struct *get_current(void) __attribute_const__;

static inline struct task_struct *get_current(void)

{

return current_thread_info()->task;

}

#define current (get_current())

可 见,current其实是一个“伪全局变量”,是函数get_current()的宏定义。当access.c中使用current->uid时, 就调用了get_current()函数,从而返回task_struct结构的task,因此current->uid就相当于 task->uid。

之前在Ubuntu里编译scull时有错误,还好有网友提供了解决办法,即删除config.h文件和增加#include 两个头文件:capability.h和sched.h

最近将Ubuntu升级到9.10版本后,重新生成了2.6.31版本的内核树,没想到编译scull模块时出现新的

/home/dengwei/eclipse_workspace/scull/access.c:108: error: ‘struct task_struct’ has no member named ‘uid’

/home/dengwei/eclipse_workspace/scull/access.c:109: error: ‘struct task_struct’ has no member named ‘euid’

/home/dengwei/eclipse_workspace/scull/access.c:116: error: ‘struct task_struct’ has no member named ‘uid’

/home/dengwei/eclipse_workspace/scull/access.c: In function ‘scull_w_available’:

/home/dengwei/eclipse_workspace/scull/access.c:167: error: ‘struct task_struct’ has no member named ‘uid’

/home/dengwei/eclipse_workspace/scull/access.c:168: error: ‘struct task_struct’ has no member named ‘euid’

/home/dengwei/eclipse_workspace/scull/access.c: In function ‘scull_w_open’:

/home/dengwei/eclipse_workspace/scull/access.c:186: error: ‘struct task_struct’ has no member named ‘uid’

原因:

struct task_struct定义在include/linux/sched.h中,原来task_struct结构体定义有所改动,将uid和euid等挪到 cred中,见include/linux/sched.h和include/linux/cred.h。

解决方法:

只需要将报error的代码做如下修改

current->uid 修改为 current->cred->uid

current->euid 修改为 current->cred->euid

make success

结果:

root@dw:/home/dengwei/eclipse_workspace/scull# ls

access.c main.o Module.symvers scull.init scull.mod.o

access.o Makefile pipe.c scull.ko scull.o

_desktop.ini Module.markers pipe.o scull_load scull_unload

main.c modules.order scull.h scull.mod.c

root@dw:/home/dengwei/eclipse_workspace/scull# insmod scull.ko

按照上面提示,就可以顺利编译成ko文件,其中include/linux在我的Linux中绝对路径名是

/usr/src/linux-headers-2.6.32-21/include/linux
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐