Linux驱动直接写函数,init,exit不需要想windows指定函数名,但是需要注册函数。用module_init
#include
#include
MODULE_LICENSE ("GPL");//开源协议GPL 或者MIT BSD
MODULE_AUTHOR ("TOM");//作者
MODULE_DESCRIPTION ("MY_TEST");//描述此驱动
//EXPORT_NO_SYMBOLS;//不导出符号,函数 可以不写
//EXPORT_SYMBOL(hello_data);//导出hello_data
int test_init(void)
{
printk(KERN_INFO "hello world\n");//调试级别
return 0;
}
void test_exit(void)
{
printk(KERN_INFO "goodbye world\n");
}
module_init(test_init); //注册DriverEntry
module_exit(test_exit); //注册DriverUnload
EXTRA_CFLAGS := -g//一些编译选项 ;=的意思是在原来的数上加上其它编译选项
obj-m =hello.o
#hello-objs := file1.o file2.o,如果有多个源文件,加上这么一行
KVERSION = $(shell uname -r)
all:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules(这里前面是tab按键)
clean:
make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean
Makefile无后缀名,且M是大写
make –C之前是一个tab键而不是空格
如果只有一个C文件,那么hello.o要与hello.c同名
make不能使用sudo
写好,代码之后执行,make编译
然后安装运行
sudo insmod hello.ko //加载hello.ko
sudo rmmod hello.ko //卸载hello.ko
sudo lsmod //显示ALL驱动
sudo modinfo hello //查看驱动信息
dmesg | tail //查看最近linux打印信息
sudo cat /proc/kmsg //同上,滚动输出(pro)
Ubuntu模块自启动:
将驱动拷到/lib/modules/2.6.32.65/kernel/lib/
/lib/modules/2.6.32.65/kernel/lib/hello.ko
编辑modules
/etc/modules
增加驱动名,不需要加ko
可以为模块与模块直接传参数,在模块
module_param(who,charp,S_IRUSR)//这个权限是文件所有者可读
加载时候就是insmod kello.ko who="world" time=5
#include
#include
#include
MODULE_LICENSE("Dual BSD/GPL");
static char *who= "world";
static int times = 1;
module_param(times,int,S_IRUSR);
module_param(who,charp,S_IRUSR);
static int hello_init(void)
{
int i;
for(i=0;i
EXPORT_SYMBOL(hello_data);导出
extern int hello_data;使用,要先加载导出在加载导入,卸载反着,但是要先编译导出模块得到Modules.symves,拷贝到导入,才能编译通过,要不然编译这个导入时候不知道导入符号的位置,或者在编译导入的makefile里加入
KBUILD_EXTRA_SYMBOLS = /mnt/hgfs/MallocFree_2018/Linux/10ten-hellokernel/demo/hello-2/Module.symvers
首先加在内核驱动
然后可以通过 cat /proc/devices查看安装上的驱动生成的设备主功能号
通过 sudo mknod /dev/second c xxx yyy 命令创建/dev/second设备节点
编译客户端文件并执行。
Character devices:
1 mem
4 /dev/vc/0
4 tty
4 ttyS
5 /dev/tty
5 /dev/console
5 /dev/ptmx
6 lp
7 vcs
10 misc
13 input
14 sound
Linux的奔溃分为模块OOPS,系统PANIC
oops之后,模块被Killed,有可能不会panic,因为oops可能在进程上下文,并不是中断上下文
若果想oops之后panic,在/etc/syctl.conf中
kernel.panic_on_oops=1
kernel.panic=20
然后sudo sysctl -p
如果oops使用命令:demesg->oops stack or cat /proc/kmsg
然后使用 objdump -S oops.o 查看出错误rip偏移的代码,就定位到代码出错处。
如果panic,系统信息肯定就没了,只能
切换到终端:物理机ALT+CTRL+F1,虚拟机ALT+CTRL+空格+ALT+CTRL+F1
切换到UI:....+F7
生成dump文件,需要安装Kexec-tools
sudo apt-get install linux-crashdump
sudo vim /etc/default/kexec
LOAD_KEXEC=true
reboot
sudo /etc/init.d/kdump start
sudo echo "c">/proc/sysrq-trigger
ls /var/crash/vmcore
去http://ddebs.ubuntu.com/pool/main/linux下载与uname -a命令输出匹配的符号
dpkg -i linux-image-版本编号-XXX ddeb
sudo crash /usr/lib/debug/boot/vmlinux-版本号-generic /var/crash/vmcore
bt/ps/log 查看信息
如果出bug,用printk打日志
printk(KERN_INFO "xxx\n");
kern_info是日志级别。printk可能没输出到终端,去/var/log/messages查看,如果klogd没有运行,消息不会传递到用户控件,只能/proc/kmsg.
也可以gdb观察内核,但是不能修改,设置断点,单步调试,只能查看
还有KDB,KGDB(支持双机调试)
可以显示系统调用信息,包括调用时的参数信息,跟windows平台的API monitor差不多。