我的环境是ubuntu12.04

内核版本:3.13.0-32-generic

这个内核版本算是比较新的,scull源码编译会出现很多问题以下对这些问题进行归纳总结:


今天对程序进行编译,结果出现

make -C /lib/modules/3.3.2-6.fc16.x86_64/build M=/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull LDDINC=/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/../include modules
make[1]: Entering directory `/usr/src/kernels/3.3.2-6.fc16.x86_64'
scripts/Makefile.build:49: *** CFLAGS was changed in "/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/Makefile". Fix it to use ccflags-y.  Stop.
make[1]: *** [_module_/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull] Error 2
make[1]: Leaving directory `/usr/src/kernels/3.3.2-6.fc16.x86_64'
make: *** [modules] Error 2

vim /usr/src/kernels/3.3.2-6.fc16.x86_64/scripts/Makefile.build
第49行内容
 # If the save-* variables changed error out
 47 ifeq ($(KBUILD_NOPEDANTIC),)
 48         ifneq ("$(save-cflags)","$(CFLAGS)")
 49                 $(error CFLAGS was changed in "$(kbuild-file)". Fix it to use ccflags-y)
 50         endif
 51 endif
没有定义KBUILD_NOPEDANTIC,且修改了CFLAGS,导致编译不能继续。我想这里是开发者为了防止修改CFLAG进行的保护措施,解决办法可以在编译前定义KBUILD_NOPEDANTIC,export KBUILD_NOPEDANTIC=1或者修改Makefile中的CFLAGS为ccflags-y

继续编译,#include 出现include的linux下没有config.h这个文件

/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/main.c:17:26: fatal error: linux/config.h: No such file or directory

把这个文件加上去就好了。现在较新的内核已经弃用了config.h。
sudo vim /usr/src/kernels/3.3.2-6.fc16.x86_64/include/linux/config.h
 #ifndef _LINUX_CONFIG_H
 #define _LINUX_CONFIG_H
 #endif
OK!这个问题解决了。

接下来有出问题了

/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/main.c:556:2: error: unknown field 'ioctl' specified in initializer

ioctl是未知域,查看file_operations结构体,在build/inlcude/linux/fs.h中的1603行定义,前面有两句话
 /* These macros are for out of kernel modules to test that
  * the kernel supports the unlocked_ioctl and compat_ioctl
  * fields in struct file_operations. */
根据开发者的意见,ioctl使用了大内核锁,这个是不安全的,新的kerne将l不再支持ioctl方法,而应该使用 unlocked_ioctl或者compat_ioctl。修改main.c中556行的.ioctl为unlocked_ioctl,这个错误不会出现了。同时,这个函数指针的原型也改变了!
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); 
与原来的ioctl函数原型相比少传递了struct inode *inode 这个变量,因此我们的实现scull_ioctl需要变为
main.c
394  int scull_ioctl(struct file *filp,
395                        unsigned int cmd, unsigned long arg)
scull.h
131 int     scull_ioctl(struct file *filp,
132                     unsigned int cmd, unsigned long arg);

接着,出现另外一个问题:
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/main.c:652:3: error: implicit declaration of function 'init_MUTEX

与前一个错误来源一样,init_MUTEX(&sem)在新内核里也被弃用了。用sema_init(&sem,1)进行替换可解决此问题。
好了,main.c的问题解决了,pipe.c编译的时候出现了一大堆问题了。

/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:130:3: error: dereferencing pointer to incomplete type
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:131:7: error: 'TASK_INTERRUPTIBLE' undeclared (first use in this function)
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:131:7: note: each undeclared identifier is reported only once for each function it appears in
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:131:3: error: implicit declaration of function 'signal_pending' [-Werror=implicit-function-declaration]
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:131:3: error: implicit declaration of function 'schedule' [-Werror=implicit-function-declaration]
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:153:2: error: dereferencing pointer to incomplete type
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c: In function 'scull_getwritespace':
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:167:3: error: dereferencing pointer to incomplete type
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:168:38: error: 'TASK_INTERRUPTIBLE' undeclared (first use in this function)
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c: In function 'scull_p_write':
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:219:2: error: 'TASK_INTERRUPTIBLE' undeclared (first use in this function)
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:223:34: error: 'SIGIO' undeclared (first use in this function)
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:223:41: error: 'POLL_IN' undeclared (first use in this function)
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:224:2: error: dereferencing pointer to incomplete type
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c: At top level:
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:319:2: warning: initialization from incompatible pointer type [enabled by default]
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/pipe.c:319:2: warning: (near initialization for 'scull_pipe_fops.unlocked_ioctl') [enabled by default]
cc1: some warnings being treated as errors

太吓人了,不过仔细看这些错误,大部分都是类型未定义,怎么办?我们可以用命令在 /lib/modules/$(uname -r)/build/include/linux 文件夹下搜搜

find ./ -type f -exec grep "TASK_INTERRUPTIBLE" {} \; -print

结果显示

#define TASK_INTERRUPTIBLE 1
#define TASK_NORMAL (TASK_INTERRUPTIBLE | TASK_UNINTERRUPTIBLE)
#define TASK_REPORT (TASK_RUNNING | TASK_INTERRUPTIBLE | \
if (!(state & (TASK_INTERRUPTIBLE | TASK_WAKEKILL)))
return (state & TASK_INTERRUPTIBLE) || __fatal_signal_pending(p);
./sched.h
原来改到了在sched.h中定义了。把这个头文件加到pipe.c中
#include
再编译,发现access.c也出现跟pipe.c一样的问题,再把sched.h添加进去。
还是出现问题:
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/access.c:99:34: error: 'SPIN_LOCK_UNLOCKED' undeclared here (not in a function)
原因,SPIN_LOCK_UNLOCKED在新内核中被弃用,用新内核编译的人伤不起阿!解决办法,添加头文件
#include
修改定义
static spinlock_t scull_u_lock = SPIN_LOCK_UNLOCKED;
static DEFINE_SPINLOCK(scull_u_lock);

问题:
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/access.c:107:29: error: 'struct task_struct' has no member named 'uid'
/home/jqzeng/workSpace/ldd3/ldd3-samples-1.0.0/scull/access.c:108:29: error: 'struct task_struct' has no member named 'euid'
原因:新的struct task_struct 定义有变化,uid和euid在cred结构体中。
解决办法:加头文件cred.h,将 current->uid改为current->cred->uid,current->euid改为current->cred->euid
#include
108         if (scull_u_count &&
109                         (scull_u_owner != current->cred->uid) &&  /* allow user */
110                         (scull_u_owner != current->cred->euid) && /* allow whoever did su */
...
117                 scull_u_owner = current->cred->uid; /* grab it */
到这里后改过还是问题
/home/kevin/Documents/examples/scull/access.c: In function ‘scull_u_open’:
/home/kevin/Documents/examples/scull/access.c:109:19: error: invalid operands to binary != (have ‘uid_t’ and ‘kuid_t’)
/home/kevin/Documents/examples/scull/access.c:110:19: error: invalid operands to binary != (have ‘uid_t’ and ‘kuid_t’)
解决办法,参考如下连接
http://bbs.csdn.net/topics/390734456
http://lists.infradead.org/pipermail/linux-pmfs/2013-April/000010.html
 current->cred->uid为kuid_t类型,需要继续获取val才可以进行比较
typedef struct {
	uid_t val;
} kuid_t;
代码改过后
scull_w_owner == current->cred->uid.val ||
scull_w_owner == current->cred->euid.val ||

这里贴上通过编译的代码,见附件。

Logo

更多推荐