Linux驱动学习笔记字符设备驱动

Posted 飞雪天龙

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux驱动学习笔记字符设备驱动相关的知识,希望对你有一定的参考价值。

今天对程序进行编译,结果出现 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 <linux/config.h>出现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 <linux/sched.h> 再编译,发现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 <linux/spinlock_types.h> 修改定义 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 <linux/cred.h> 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 */
好了。接下来access.c还会出现一大帮的问题,不过都是前面出现的,只要按照前面的方法修改,最终就可以通过编译!
这里贴上通过编译的代码,见附件。  scull.zip    <script>window._bd_share_config="common":"bdSnsKey":,"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16","share":;with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script> 阅读(2) | 评论(0) | 转发(0) | 0

上一篇:存储管理

下一篇:Linux 错误码列表

相关热门文章 给主人留下些什么吧!~~ 评论热议

以上是关于Linux驱动学习笔记字符设备驱动的主要内容,如果未能解决你的问题,请参考以下文章

学习笔记——《LINUX设备驱动程序(第三版)》Linux设备模型:内核添加删除设备驱动程序

Linux驱动开发笔记:helloworld驱动源码编写makefile编写以及驱动编译基本流程

linux 驱动学习简单的字符设备驱动程序

Linux 设备驱动的并发控制 学习笔记

我的内核学习笔记11:linux leds-gpio驱动应用实例

Linux字符设备驱动