Linux设备驱动程序(第三版)读书笔记1,hello world

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zmnqazqaz/article/details/38058713
1.构建一个内核树

说是要2.6内核的源码书,所以就去kernel.org下载一个2.6的内核linux-2.6.32.63.tar.xz

xz -d linux-2.6.32.63.tar.xz
tar -xvf  linux-2.6.32.63.tar
cd linux-2.6.32.63
make oldconfig #配置原版
make -j4  @编译内核(此过程耗时长,编译完后在linux-2.6.32.63多出一个vmlinux,jN代表用几个线程来编译)

//make
  -j4  modules #编译模块,2.6内核并不需要再单独编译了,make已经做过了
make modules_install  安装模块(操作结束后多出目录/lib/modules/2.6.32.63)
,, 

make install #安装2.6内核的系统中,会自动安装内核并更新grub


2.重启

进入grub启动项,没有倒计时的话开机一直按shift键或者是esc键,启动2.6内核。

这里我编译的内核启动后貌似卡死在紫色屏幕,所以我暂时先放弃了启动2.6内核,尝试ubuntu12.4自带的3.5内核吧。(ps,后续重新编译了一次,能进入2.6内核了)


3. uname -r 可以看到启动后内核

 3.5.0-23-generic


4.测试hello,world

①、hellomod.c

#include<linux/init.h>  //初始换函数
#include<linux/kernel.h>  //内核头文件
#include<linux/module.h>  //模块的头文件
MODULE_LICENSE("Dual BSD/GPL");
 
static int hello_init(void)
{
 printk(KERN_ALERT "Hello,world\n");
 return 0;
}

static void hello_exit(void)
{
 printk(KERN_ALERT "Goodbye,Cruel world \n");
}

module_init(hello_init);
module_exit(hello_exit);
</pre><pre name="code" class="cpp"><pre name="code" class="html">②、Makefile
obj-m := hello.o
KVERSION = $(shell uname -r) #这里编译<span style="white-space: pre;">内核版本可以ls /lib/modules看一下</span>
all:
	make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules
clean:
	make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean

会在目录下生成hello.ko文件
无错误的输出:
make -C /lib/modules/3.5.0-23-generic/build M=/home/u/桌面 modules
make[1]: 正在进入目录 `/usr/src/linux-headers-3.5.0-23-generic'
  Building modules, stage 2.
  MODPOST 1 modules
make[1]:正在离开目录 `/usr/src/linux-headers-3.5.0-23-generic'


$ modinfo hello.ko

filename:       hello.ko
license:        Dual BSD/GPL
srcversion:     800BA9CD509F78BD1257A18
depends:        
vermagic:       3.5.0-23-generic SMP mod_unload modversions -

$ uname -r

3.5.0-23-generic



④、插入内核并查看insmod hello.ko

#发现没有hello world  

#原因书上介绍了由于是虚拟终端,信息不会显示出来,而是存到系统日志中查看日志:

tail -f /var/log/kern.log  

Jul 22 17:08:25 u-VirtualBox kernel: [ 5634.200312] Hello,world!

#切换到黑窗口很清楚的看到这个现象

或者cat  /var/log/messages   #发现没有这个文件,文档说不同的 linux可能路径不同,ubuntu解决办法是在最下面。

直接用下面这个命令看已经加载的模块

$ lsmod

ModuleSize  Used by   hello                  12497  0 [permanent] #这个永久的意思包含的信息量太大了

                                       vesafb                 13846  1 

⑤移除模块sudo rmmod hellomod

ERROR: Module hellomod does not exist in /proc/modules

#错误应该是来自于[permanent] 这里 应该是无法被卸载!#经测试重启后会消失掉!

原因:系统默认的内核使用gcc版本与当前编译模块的gcc不同导致。   

忽然想起来了编译安卓的时候把默认的GCC改成4.4了。。然后我们还是继续看一下。

$ cd  /lib/modules/`uname -r`/build/include/generated/

$ cat compile.h 

/* This file is auto generated, version 35~precise1-Ubuntu */

/*SMP */#define UTS_MACHINE "x86_64"#define UTS_VERSION "#35~precise1-Ubuntu SMP Fri Jan 25 17:13:26 UTC 2013"

#define LINUX_COMPILE_BY "buildd"

#define LINUX_COMPILE_HOST "komainu"

#define LINUX_COMPILER "gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5) "

可以看到官方编译的gcc版本为 4.6.3$gcc -vgcc version 4.4.7 (Ubuntu/Linaro 4.4.7-1ubuntu2) //发现了吧,然后解决办法。

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------

解决办法(测试成功)

ls -al /usr/bin/gcc*

   lrwxrwxrwx 1 root root     7  7月 16 10:57 

  /usr/bin/gcc -> gcc-4.4-rwxr-xr-x 1 root root 259232  4月 16  2012

  /usr/bin/gcc-4.4-rwxr-xr-x 1 root root 353216  4月 16  2012 

  /usr/bin/gcc-4.6lrwxrwxrwx 1 root root      7  7月 15 16:10

 /usr/bin/gcc.bak -> gcc-4.6  

那么很简单了把gcc这个软连接指向gcc-4.6就ok了,

之前我有备份直接改一下名字就可以了

创建软连接的方法:ln -s /usr/bin/gcc-4.6 /usr/bin/gcc

重新编译lsmod一下:

Module                  Size  Used byhello                   12497  0

 rmmod hello

没有出现提示错误查看一下日志吧,

tail-f /var/log/kernel.0

Jul 22 18:04:47 u-VirtualBox kernel: [   69.715499] Hello,worldJul 22 18:06:00 u-VirtualBox kernel: [  142.161470] Goodbye 

————————————————————————————————————————————————————————————

版本2:

//关于加载模块时指定模块参数的值

#include <linux/init.h>
#include <linux/module.h>
#include <linux/moduleparam.h>

MODULE_LICENSE("Dual BSD/GPL");
static char *whom = "world";
static int howmany = 1;
//module_param宏在moduleparam.h定义,charp字符指针,
//最后一个参数是权限掩码作为辅助的sysfs入口
//insmod hello howmany=10 whom="hello" 这样改变模块参数
module_param(howmany, int, S_IRUGO);
module_param(whom, charp, S_IRUGO); 
//bool invbool charp int long short uint ulong ushort
//数组 module_param_array(name,type,num,perm)
//1.数组名 2.数组元素类型 3.长度  4.权限值

static int hello_init(void)
{
	int i;
	for (i = 0; i < howmany; i++)
		printk(KERN_ALERT "(%d) Hello, %s\n", i, whom);
	return 0;
}

static void hello_exit(void)
{
	printk(KERN_ALERT "Goodbye, cruel world\n");
}

module_init(hello_init);
module_exit(hello_exit);

-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ps::
ubuntu12.04没有/var/log/messages解决
 
因为出错了找不到这个文件,很奇怪,因为网上介绍说查看这个文件的
 
然后百度,发现有些版本是没有,不过ubuntu的可以有
 
编辑/etc/rsyslog.d/50-default.conf
 
其中有这么一段
 
*.=info;*.=notice;*.=warn;\
    auth,authpriv.none;\
    cron,daemon.none;\
    mail,news.none        -/var/log/messages
 
这是本来就有,却被注释了。现在解注释就行
 
保存后重启服务:sudo restart rsyslog    
 



展开阅读全文

没有更多推荐了,返回首页