Linux设备驱动程序学习随笔1--从头文件 linux/moudle.h开始

所有的程序员入门的第一个程序都是从 Holle World 开始,linux嵌入式驱动开发也不例外,《Linux设备驱动程序》这本书的第一个程序就是hello world。然而,人生写驱动程序的第一次编译就异常的艰难。

以下是hello world 的程序,很简单,基本上学过C就能看懂,该程序包括两个头文件,引用了4个外部函数,内建2个函数。

 1 #include <linux/init.h>
 2 #include <linux/module.h>
 3
 4 MODULE_LICENSE("Dual BSD/GPL");
 5
 6 static int hello_init(void)
 7 {
 8         printk(KERN_ALERT "Hello world\n");
 9         return 0;
10 }
11
12 static void hello_exit(void)
13 {
14         printk(KERN_ALERT "goodbye,cruel world\n");
15 }
16
17 module_init(hello_init);
18 module_exit(hello_exit);

这个程序相当的清晰的指出了,驱动程序的程序结构,整个驱动程序由init函数引导加载,exit函数引导卸载。值得注意的是,驱动程序不需要main函数,这是驱动程序和普通程序一个比较明显的区别。

注:如果你使用的是老版本的书或者PDF,hello world的代码会和上述代码有所区别,建议使用上述代码,比较老版本是2.0时代的代码了(第一版是2000年左右出版的),不过书的内容并没有变化太大。



下面我们进入今天的正题。

写完这个简单的函数就可以进行编译了,然而这个时候如果你直接使用GCC编译的话你就会得到如下结果。

这里mo.c就是我的源程序文件。

可以看到这个时候编译器报错,No such file or directory,书上并没有到如何解决,只能求助于万能的度娘了。百度一圈之后,我发现,原来默认编译器就没引用这个头文件,头文件的地址就在/usr/src/linux-headers-3.16.0-30下面,于是我用-I来引用头文件,然而并不能通过。

经过一番研究我发现,网上各路大神都是使用makefile进行编译

 1 obj-m := mo.o
 2
 3  CURRENT_DIR :=$(shell pwd)
 4
 5  KERNEL_DIR := /usr/src/linux-headers-$(shell uname -r)
 6 all:
 7     $(MAKE) -C $(KERNEL_DIR) M=$(CURRENT_DIR) modules
 8
 9 clean:
10     rm -rf %.o

这些总可以开开心心编译了吧,呵呵,make之后

这错误信息到底是啥意思?常识了10个小时,我终于发现

mdzz



总之makefile报错记得用权限跑一下 。。。。

时间: 2024-11-16 02:25:14

Linux设备驱动程序学习随笔1--从头文件 linux/moudle.h开始的相关文章

linux设备驱动程序该添加哪些头文件以及驱动常用头文件介绍(转)

原文链接:http://blog.chinaunix.net/uid-22609852-id-3506475.html 驱动常用头文件介绍 #include <linux/***.h> 是在linux-2.6.29/include/linux下面寻找源文件.#include <asm/***.h> 是在linux-2.6.29/arch/arm/include/asm下面寻找源文件.#include <mach/***.h> 是在linux-2.6.29/arch/ar

Linux设备驱动程序学习笔记(一)

1.设备驱动程序扮演的角色:       设备程序是一个独立的“黑盒子”,使其某个特定硬件响应一个定义良好的内部编程接口,这些接口完全隐藏了设备的工作细节.用户的操作通过一组标准化的调用执行,而这些调用独立于特定的驱动程序.将这些调用映射到作用于实际硬件的设备特有操作上,则是设备驱动程序的任务.2.驱动程序的作用:        驱动程序应该处理如何使用硬件可用的问题,而将怎样使用硬件的问题留给上层应用.(提供机制,而不是策略)3.内核功能划分:        进程管理    内存管理    文

Linux设备驱动程序学习 高级字符驱动程序操作[阻塞型I/O和非阻塞I/O]【转】

转自:http://blog.csdn.net/jacobywu/article/details/7475432 阻塞型I/O和非阻塞I/O 阻塞:休眠 非阻塞:异步通知 一 休眠 安全地进入休眠的两条规则: (1) 永远不要在原子上下文中进入休眠,即当驱动在持有一个自旋锁.seqlock或者 RCU锁时不能睡眠:关闭中断也不能睡眠.持有一个信号量时休眠是合法的,但你应当仔细查看代码:如果代码在持有一个信号量时睡眠,任何其他的等待这个信号量的线程也会休眠.因此发生在持有信号量时的休眠必须短暂,而

linux设备驱动程序学习笔记一:在ubuntu 14.04.3 LTS下调试ldd的scull代码

操作系统版本 [email protected]:~/vm_disk_dpdk/study/drive/examples/scull# sudo lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description:    Ubuntu 14.04.3 LTSRelease:        14.04Codename:       trusty[email protected]:~/vm_disk_dpdk

转:《Linux设备驱动程序3》源码目录结构和源码分析经典链接

转自:http://blog.csdn.net/geng823/article/details/37567557 [原创][专栏]<Linux设备驱动程序>--- LDD3源码目录结构和源码分析经典链接 [专栏]Linux设备驱动程序学习(总目录) [专栏]LDD3源码分析链接(总目录) 1. LDD3源码分析之hello.c与Makefile模板 2. LDD3源码分析之字符设备驱动程序 其他错误: 我的Linux内核为 3.2.0-65-generic-pae,在scull目录下make时

LINUX设备驱动程序笔记(一)设备驱动程序简介

<一>:设备驱动程序的作用 从一个角度看,设备驱动程序的作用在于提供机制,而不是策略.在编写驱动程序时,程序员应该特别注意下面这个基本概念:编写访问硬件的内核代码时,不要给用户强加任何特定策略.因为不同的用户有不同的需求,驱动程序应该处理如何使硬件可用的问题,而将怎样使用硬件的问题留给上层应用程序. 从另一个角度来看驱动程序,它还可以看作是应用程序和实际设备之间的一个软件层. 总的来说,驱动程序设计主要还是综合考虑下面三个方面的因素:提供给用户尽量多的选项.编写驱动程序要占用的时间以及尽量保持

LINUX设备驱动程序笔记(二)构造和运行模块

         <一>:设置测试系统 首先准备好一个内核源码树,构造一个新内核,然后安装到自己的系统中.           <二>:HelloWorld模块 #include <linux/init.h> //定义了驱动的初始化和退出相关的函数 #include <linux/module.h> //定义了内核模块相关的函数.变量及宏 MODULE_LICENSE("Dual BSD/GPL"); //该宏告诉内核,该模块采用自由许可

LINUX设备驱动程序笔记(三)字符设备驱动程序

      <一>.主设备号和次设备号        对字符设备的访问时通过文件系统内的设备名称进行的.那些设备名称简单称之为文件系统树的节点,它们通常位于/dev目录.字符设备驱动程序的设备文件可通过ls -l命令输出的第一列中的'c'来识别.块设备同样位于/dev下,由字符'b'标识 crw-rw----  1 root root    253,   0 2013-09-11 20:33 usbmon0 crw-rw----  1 root root    253,   1 2013-09

Linux 设备驱动程序 字符设备

已经无法再精简,适合入门. 1 #include<linux/module.h> 2 #include<linux/init.h> 3 4 #include<asm/uaccess.h> 5 #include <linux/types.h> 6 #include<linux/fs.h> 7 #include<linux/cdev.h> 8 struct mengc_dev{ 9 char data[64]; 10 struct cde