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

飞雪天龙 飞雪天龙     2023-03-25     507

关键词:

今天对程序进行编译,结果出现 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设备模型:内核添加删除设备驱动程序(代码片段)

文章目录1.前言2.准备工作2.1.概念2.2.具体总线、设备、驱动结构体说明2.3.注册总线3.添加设备3.1.STEP1——发现设备并创建设备结构structXXX_dev3.2.STEP2——初始化设备结构3.3.STEP3——注册设备4.删除设备5.添加驱动程序6.删除驱动程... 查看详情

字符设备驱动体验,字符设备驱动学习

                字符设备驱动学习  在Linux系统中,驱动程序通常采用内核模块的程序结构来进行编码。因此,编译/安装一个驱动程序,其实质就是编译/安装一个内核模块。一、编译安装字符设备驱动程... 查看详情

linux驱动开发笔记:helloworld驱动源码编写makefile编写以及驱动编译基本流程(代码片段)

前言  基于linux的驱动开发学习笔记,本篇是描述了一个字符驱动的基础开发流程,以便做嵌入式开发多年的应用或者系统学习驱动开发。 笔者自身情况  笔者拥有硬件基础,单片机软硬基础,linux系统基础等各种,就... 查看详情

linux驱动开发-混杂字符设备驱动模型笔记4(代码片段)

混杂字符设备驱动模型概念linux系统中,称以主设备号为“10”,但次设备号不同的字符设备为混杂设备所有的混杂设备形成一个链表对设备访问时,内核根据次设备号查找到相应的设备结构描述structmiscdeviceintminor;/*... 查看详情

linux驱动开发-混杂字符设备驱动模型笔记4(代码片段)

混杂字符设备驱动模型概念linux系统中,称以主设备号为“10”,但次设备号不同的字符设备为混杂设备所有的混杂设备形成一个链表对设备访问时,内核根据次设备号查找到相应的设备结构描述structmiscdeviceintminor;/*... 查看详情

linux设备驱动的并发控制学习笔记(代码片段)

文章目录并发和竞态编译乱序和执行乱序并发控制机制中断屏蔽原子操作整型原子操作位原子操作自旋锁自旋锁的使用读写自旋锁顺序锁读-复制-更新信号量互斥体完成量并发和竞态并发:多个执行单元同时、并行被执行。... 查看详情

linux驱动开发-字符设备控制技术笔记3(代码片段)

字符设备控制技术  笔记要做的自己看起来舒服和有头绪,这不又折腾切换编辑器来从新排版,有强迫症啊!对于字符控制,很多时候编写上层应用程序时,使用ioctl系统调用来控制设备,原型如下:/*fd:... 查看详情

linux驱动学习记录-新字符设备(代码片段)

...knod命令创建节点。这些都是老版本,现在学习新字符设备驱动开发。第一节提了一点点,申请设备号是用自动分配的方式就是新设备开发。 1.新字符设备注册        Linux中cdev结 查看详情

字符设备驱动程序

...使用面包板搭简单的外部电路;4.    学习Linux设备驱动程序的开发过程;5.    学习在内核中访问外设寄存器,操作外设的方法 二、     实验器材1.    Linu 查看详情

linux字符设备驱动实例笔记

...en、close、read、write、ioctrl这几个函数。在Linux下一个字符设备驱动与用户调用该设备的程序之间的关系如下图所示,Linux内核使用cdev结构体来描述字符设备,通过其成员dev_t来定义设备号(分为主、次设备号)以... 查看详情

linux驱动开发学习二:创建一个阻塞型的字符设备(代码片段)

在Linux驱动程序中,可以使用等待队列来实现阻塞进程的唤醒。等待队列的头部定义如下,是一个双向列表。structlist_head       structlist_head*next,*prev;; struct__wait_queue_head     &n 查看详情

binder学习笔记——穿越到驱动层(代码片段)

Binder驱动层的代码在kernel/goldfish/drivers/staging/android下的binder.c和binder.h。Android源码是不带Linux内核的,驱动正是在这个内核里,需要单独下载,出门左转参见《Anrdoid源码、内核编译》。驱动的相关知识先不在这里展开... 查看详情

linux学习笔记基本的bashshell命令

...协调管理各个存储设备。LinuxPC上安装的第一块硬盘为根驱动器,在根驱动器上创建一些特别的目录,我们称之为挂载点。挂载点是虚拟目录中用于分配额外存储设备的目录。虚拟目录会让文件和目录出现在这些挂载点目录中,... 查看详情

linux学习资料整理

...ux系统信号(Linux系统上驱动移植)(Linux字符设备驱动框架)Linux(驱动)Linux设备驱动模型-KobjectLinux驱动之input输入子系统linux设备驱动之I2C驱动框架linux内核之leds子系统linux驱动底层深入理解Linux设备驱... 查看详情

linux-usb驱动笔记

...4、USB总线4.1、USB2.04.2、USB3.05、USB控制器类型1、前言USB的驱动非常的复杂,一下子去看源码也是一头雾水,下面记录下学习USB驱动的过程,后续也会有几篇笔记连续起来。2、USB简介USB,是英文UniversalSerialBus(... 查看详情

linux设备驱动第三篇:写一个简单的字符设备驱动

   在linux设备驱动第一篇:设备驱动程序简介中简单介绍了字符驱动,本篇简单介绍如何写一个简单的字符设备驱动。本篇借鉴LDD中的源码,实现一个与硬件设备无关的字符设备驱动,仅仅操作从内核中分配的一些内... 查看详情

linux驱动学习笔记(一linux架构)

...函数库;可以分为应用层(关注业务逻辑)和驱动层(提供函数接口),Linux系统大部分使用C语言编写只在系统的启动部分含有汇编代码。Linux提供了大量的资源比如网络协议栈,多任务处理,内存... 查看详情

我的内核学习笔记12:linuxi2c-gpio驱动应用实例(代码片段)

linux内核的i2c-gpio是使用GPIO模拟I2C协议的驱动,只需要配置2根GPIO即可使用。Linux的I2C子系统比较复杂,笔者暂时还没有研究。本着“实用”的目的,介绍一下如何使用这个驱动及一些注意事项。一、概述Linux内核很多... 查看详情