scull在Ubuntu11.10上的编译

本文详细介绍了如何在Ubuntu 11.10上编译Linux设备驱动程序scull,包括解决编译过程中的常见错误和更新代码以适应不同内核版本的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面的话

在学习Linux设备驱动程序过程中,ldd3是必不可少的一本书,那么在书中,我们会看到书中的一个设备驱动程序----scull。

今天,我们就要看看如何将这个设备驱动程序在Ubuntu11.10上进行编译;而后,我们就能利用scull更加深层次的去学习驱动程序的知识。


首先,我们去下载一份ldd3的配套源码,下面是我分享的一份代码,大家可以下载使用:http://yunpan.cn/lk/sV2ZrN6JFEKKW?sid=301

对源码进行解压,里面会有好几个目录,我们现在要关心的就是scull这个目录,下面的操作都会在这里进行。

root@yafeng-VirtualBox:/examples# ls
include  LICENSE   misc-modules  pci    scull   sculld  scullv  shortprint  skull  tty
lddbus   Makefile  misc-progs    sbull  scullc  scullp  short   simple      snull  usb
root@yafeng-VirtualBox:/examples# 

再者,我们来看看我们要编译的平台的是怎么样的一个平台:

root@yafeng-VirtualBox:/# uname -a
Linux yafeng-VirtualBox 3.0.0-12-generic #20-Ubuntu SMP Fri Oct 7 14:50:42 UTC 2011 i686 i686 i386 GNU/Linux
root@yafeng-VirtualBox:/# 

通过上面的打印,我们可以知道是3.0.0.12的内核。

好了,万事俱备,只欠东风。下面就开始编译吧。我们总的思路就是一步步的make,然后根据提示一步步的解决啊!

一.习惯性地由make开始,我们会看到下面的错误:

root@yafeng-VirtualBox:/examples/scull# make
make -C /lib/modules/3.0.0-12-generic/build M=/examples/scull LDDINC=/examples/scull/../include modules
make[1]: Entering directory `/usr/src/linux-headers-3.0.0-12-generic'
scripts/Makefile.build:49: *** CFLAGS was changed in "/examples/scull/Makefile". Fix it to use EXTRA_CFLAGS.  Stop.
make[1]: *** [_module_/examples/scull] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.0.0-12-generic'
make: *** [modules] Error 2

解决方法:循着错误提示,我们将Makefile文件中的CFLAGS都改为了EXTRA_CFLAGS,共三处。

二.继续make:

root@yafeng-VirtualBox:/examples/scull# make
make -C /lib/modules/3.0.0-12-generic/build M=/examples/scull LDDINC=/examples/scull/../include modules
make[1]: Entering directory `/usr/src/linux-headers-3.0.0-12-generic'
  CC [M]  /examples/scull/main.o
/examples/scull/main.c:17:26: fatal error: linux/config.h: No such file or directory
compilation terminated.
make[2]: *** [/examples/scull/main.o] Error 1
make[1]: *** [_module_/examples/scull] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.0.0-12-generic'
make: *** [modules] Error 2
root@yafeng-VirtualBox:/examples/scull# 

解决方法:根据提示,我们来到main.c文件。将#include <linux/config.h>直接删掉即可,因为config.h这个头文件貌似在2.6.19的内核版本后就没有了。

三.走着:

root@yafeng-VirtualBox:/examples/scull# make
make -C /lib/modules/3.0.0-12-generic/build M=/examples/scull LDDINC=/examples/scull/../include modules
make[1]: Entering directory `/usr/src/linux-headers-3.0.0-12-generic'
  CC [M]  /examples/scull/main.o
/examples/scull/main.c:555:2: error: unknown field ‘ioctl’ specified in initializer
/examples/scull/main.c:555:2: warning: initialization from incompatible pointer type [enabled by default]
/examples/scull/main.c:555:2: warning: (near initialization for ‘scull_fops.aio_read’) [enabled by default]
/examples/scull/main.c: In function ‘scull_init_module’:
/examples/scull/main.c:651:3: error: implicit declaration of function ‘init_MUTEX’ [-Werror=implicit-function-declaration]
cc1: some warnings being treated as errors

make[2]: *** [/examples/scull/main.o] Error 1
make[1]: *** [_module_/examples/scull] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.0.0-12-generic'
make: *** [modules] Error 2

这里有两个错误:

1.ioctl。

因为在内核2.6.36中已经完全删除了struct file_operations中的ioctl函数指针,取而代之的是unlocked_ioctl。

这种改动在应用程序中是兼容的,但是在驱动程序中,我们可以发现,两者是不能兼容的,参数中少了inode,所以在驱动程序中必须加以改变,不然就会影响cmd参数的变化。

int scull_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg);

long scull_ioctl (struct file *filp, unsigned int cmd, unsigned long arg);

 解决办法:1.就是将源代码中的scull_ioctl的函数头改为上面的第二种形式。

               2.所有file_operations结构体中的ioctl函数指针。改为unlocked_ioctl。

改动比较多,各个.c和.h文件中几乎都会涉及到。

2.init_MUTEX. 

在2.6.24的内核中,我们可以发现如下定义:

static inline void init_MUTEX (struct semaphore *sem) 
{ 
        sema_init(sem, 1); 
}

但是在2.6.25以后就已经不再使用这个宏了。

解决方法:我们就直接用sema_init(struct semaphore *sem, int val);来代替它。

同样这里的改动比较多,因而还是要仔细一点。

四.坚持着:

root@yafeng-VirtualBox:/examples/scull# make
make -C /lib/modules/3.0.0-12-generic/build M=/examples/scull LDDINC=/examples/scull/../include modules
make[1]: Entering directory `/usr/src/linux-headers-3.0.0-12-generic'
  CC [M]  /examples/scull/main.o
  CC [M]  /examples/scull/pipe.o
/examples/scull/pipe.c: In function ‘scull_p_read’:
/examples/scull/pipe.c:131:7: error: ‘TASK_INTERRUPTIBLE’ undeclared (first use in this function)
/examples/scull/pipe.c:131:7: note: each undeclared identifier is reported only once for each function it appears in
/examples/scull/pipe.c:131:3: error: implicit declaration of function ‘signal_pending’ [-Werror=implicit-function-declaration]
/examples/scull/pipe.c:131:3: error: implicit declaration of function ‘schedule’ [-Werror=implicit-function-declaration]
/examples/scull/pipe.c: In function ‘scull_getwritespace’:
/examples/scull/pipe.c:168:38: error: ‘TASK_INTERRUPTIBLE’ undeclared (first use in this function)
/examples/scull/pipe.c: In function ‘scull_p_write’:
/examples/scull/pipe.c:219:2: error: ‘TASK_INTERRUPTIBLE’ undeclared (first use in this function)
/examples/scull/pipe.c:223:34: error: ‘SIGIO’ undeclared (first use in this function)
/examples/scull/pipe.c:223:41: error: ‘POLL_IN’ undeclared (first use in this function)
cc1: some warnings being treated as errors

make[2]: *** [/examples/scull/pipe.o] Error 1
make[1]: *** [_module_/examples/scull] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.0.0-12-generic'
make: *** [modules] Error 2

看错误提示,这里主要就是TASK_INTERRUPTIBLE宏没有定义。这是最好办的。

解决方法:到源码中rgrep一下呗,看它在哪个头文件中,就将它加上。

一般来说,系统的源代码都会放在:/usr/src/XXX-generic目录下。

最后,发现TASK_INTERRUPTIBLE定义在linux/sched.h中;因而,只需要在需要的.c文件中添加#include <linunx/sched.h>即可。

五.胜利就在眼前:

make -C /lib/modules/3.0.0-12-generic/build M=/examples/scull LDDINC=/examples/scull/../include modules
make[1]: Entering directory `/usr/src/linux-headers-3.0.0-12-generic'
  CC [M]  /examples/scull/access.o
/examples/scull/access.c:99:34: error: ‘SPIN_LOCK_UNLOCKED’ undeclared here (not in a function)
/examples/scull/access.c: In function ‘scull_u_open’:
/examples/scull/access.c:107:29: error: ‘struct task_struct’ has no member named ‘uid’
/examples/scull/access.c:108:29: error: ‘struct task_struct’ has no member named ‘euid’
/examples/scull/access.c:115:26: error: ‘struct task_struct’ has no member named ‘uid’
/examples/scull/access.c: In function ‘scull_w_available’:
/examples/scull/access.c:166:27: error: ‘struct task_struct’ has no member named ‘uid’
/examples/scull/access.c:167:27: error: ‘struct task_struct’ has no member named ‘euid’
/examples/scull/access.c: In function ‘scull_w_open’:
/examples/scull/access.c:185:26: error: ‘struct task_struct’ has no member named ‘uid’
/examples/scull/access.c: In function ‘scull_w_available’:
/examples/scull/access.c:169:1: warning: control reaches end of non-void function [-Wreturn-type]
make[2]: *** [/examples/scull/access.o] Error 1
make[1]: *** [_module_/examples/scull] Error 2
make[1]: Leaving directory `/usr/src/linux-headers-3.0.0-12-generic'
make: *** [modules] Error 2

这里也是有两个问题哦。

1.struct task_struct。

错误提示没有uid和euid。查看源代码发现还真没有,不过觉得有点不可思议。继续搜索……发现在2.6.35内核中,就将这两个成员放到const struct cred *cred成员中了 。也就是被降级了。

解决方法:很好办,只要像下面一样,在uid和euid引用的地方再加一层cred,不就OK了。

current->uid-----》current->cred->uid
current->euid-----》current->cred->euid

2.SPIN_LOCK_UNLOCKED

很明显,这又是一个未定宏的错误。但是我们又发现了这个宏在2.6.19的内核中就已经被弃用.

解决方法:在我们3.0.0.12的内核中要换一个宏来代替它----DEFINE_SPINLOCK(X);替代方法如下:

static spinlock_t scull_u_lock = SPIN_LOCK_UNLOCKED;----> static DEFINE_SPINLOCK(scull_u_lock);

注意要在每个.c文件中都将SPIN_LOCK_UNLOCKED进行如上替换。

六.阳光总在风雨后:

root@yafeng-VirtualBox:/examples/scull# make
make -C /lib/modules/3.0.0-12-generic/build M=/examples/scull LDDINC=/examples/scull/../include modules
make[1]: Entering directory `/usr/src/linux-headers-3.0.0-12-generic'
  CC [M]  /examples/scull/main.o
  CC [M]  /examples/scull/pipe.o
  CC [M]  /examples/scull/access.o
  LD [M]  /examples/scull/scull.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /examples/scull/scull.mod.o
  LD [M]  /examples/scull/scull.ko
make[1]: Leaving directory `/usr/src/linux-headers-3.0.0-12-generic'

经过这么多的修改,终于将scull编译好了。

接下来,你就可以用实验来好好巩固你在书本上看到的知识了哦!以后我也可以用这个来讲解驱动知识了,不会那么的枯燥。

最后,我们来看看如何加载scull。

看到有scull_load和scull_unload了吧。对的,加载就用scull_load,反之卸载就用scull_unload。

要是两个文件没有执行权限的,就先给他们chmod一个执行权限哦!加载后如下所示:

root@yafeng-VirtualBox:/examples/scull# chmod +x scull_*
root@yafeng-VirtualBox:/examples/scull# ls
access.c  main.c  Makefile       Module.symvers  pipe.o   scull.init  scull_load   scull.mod.o  scull_unload
access.o  main.o  modules.order  pipe.c          scull.h  scull.ko    scull.mod.c  scull.o
root@yafeng-VirtualBox:/examples/scull# ./scull_load
root@yafeng-VirtualBox:/examples/scull# 

 用cat /proc/devices应该就能scull*的几项打印,这就说明设备已经挂载好了。

当不使用scull时,就指向scull_unload文件。即可卸载。

好了,今天就先讲到这了,以后有机会,就讲讲用scull实验的情况。

转载于:https://www.cnblogs.com/xiaoya901109/archive/2012/11/21/2780789.html

基于Spring Boot搭建的一个多功能在线学习系统的实现细节。系统分为管理员和用户两个主要模块。管理员负责视频、文件和文章资料的管理以及系统运营维护;用户则可以进行视频播放、资料下载、参与学习论坛并享受个性化学习服务。文中重点探讨了文件下载的安全性和性能优化(如使用Resource对象避免内存溢出),积分排行榜的高效实现(采用Redis Sorted Set结构),敏感词过滤机制(利用DFA算法构建内存过滤树)以及视频播放的浏览器兼容性解决方案(通过FFmpeg调整MOOV原子位置)。此外,还提到了权限管理方面自定义动态加载器的应用,提高了系统的灵活性和易用性。 适合人群:对Spring Boot有一定了解,希望深入理解其实际应用的技术人员,尤其是从事在线教育平台开发的相关从业者。 使用场景及目标:适用于需要快速搭建稳定高效的在线学习平台的企业或团队。目标在于提供一套完整的解决方案,涵盖从资源管理到用户体验优化等多个方面,帮助开发者更好地理解和掌握Spring Boot框架的实际运用技巧。 其他说明:文中不仅提供了具体的代码示例和技术思路,还分享了许多实践经验教训,对于提高项目质量有着重要的指导意义。同时强调了安全性、性能优化等方面的重要性,确保系统能够应对大规模用户的并发访问需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值