【基本知识】printk,模块机制

知识点1:使用命令cat /proc/sys/kernel/printk可查看当前系统的的printk的级别值(4 4 1 7),其中数值越小,级别越高;第一个值,表示控制台日志级别;第二个值是用该优先级打印没有注明级别的消息;第三个值是指控制台日志可被设置的小值;第四个值是缺省的控制台日志级别;可在/var/log/syslog或/var/log/messages中查看,或使用dmesg来查看,现在ubuntu一般控制台都不输出这些信息,由init进程转接给日志文件;


知识点2:在我们insmod kk.ko时内核会初始化,申请资源,而rmmod kk时,一定要在模块的退出函数中,一定要撤销初始化函数所做的一切,否则在系统重新引导之前某些东西就会在系统中;


知识点3:无论在内核程序和应用程序中,栈是用来保存函数调用历史以及当前活动函数的自动变量的,但是在内核中栈非常小,比如4kb这样的页面大小,我们的函数是和整个内核空间共享这个链的,因此申明大的自动变量是不好的;


知识点4:在模块有前后依赖关系的时候,如果rmmod被依赖的模块会报错;


知识点5:内核中的可靠性是至关重要的,初始化过程成的出错处理,内核源代码中大量使用了goto语句,主要是因为它的高效;应用程序中,我们是可以避免goto语句的;


知识点6:使用static,可以是的函数的作用域在本文件;


知识点7:仅仅是申明使用外来文件定义的x,而去掉extern,那就是本文件的x;如果没有文件导出x,那么在insmod会出现unkonwn symbol的错误;


程序实现

module1.c

#include 
#include 
#include 

int x = 10;
/*
	知识点1:使用命令cat /proc/sys/kernel/printk可查看当前系统的的printk的级别值(4 4 1 7),其中数值越小,级别越高;
	第一个值,表示控制台日志级别;第二个值是用该优先级打印没有注明级别的消息;第三个值是指控制台日志可被设置的小值;第四个值是缺省的控制台日志级别;可在/var/log/syslog或/var/log/messages中查看,或使用dmesg来查看,现在ubuntu一般控制台都不输出这些信息,由init进程转接给日志文件;
	知识点2:在我们insmod kk.ko时内核会初始化,申请资源,而rmmod kk时,一定要在模块的退出函数中,一定要撤销初始化函数所做的一切,否则在系统重新引导之前某些东西就会在系统中;
	知识点3:无论在内核程序和应用程序中,栈是用来保存函数调用历史以及当前活动函数的自动变量的,但是在内核中栈非常小,比如4kb这样的页面大小,我们的函数是和整个内核空间共享这个链的,因此申明大的自动变量是不好的;
	知识点4:在模块有前后依赖关系的时候,如果rmmod被依赖的模块会报错;
	知识点5:内核中的可靠性是至关重要的,初始化过程成的出错处理,内核源代码中大量使用了goto语句,主要是因为它的高效;应用程序中,我们是可以避免goto语句的;

*/
static void add(int a, int b)
{
	printk("Default Hello Linux %d + %d + %d = %d\n", a, b, x, a + b + x);
}

static int hello_init(void)
{
	printk(KERN_EMERG "KERN_EMERG Here I am IN%s  %s %i\n",__FILE__,__FUNCTION__,__LINE__);
  	printk(KERN_ALERT "KERN_ALERT Hello Linux %s  %s %i\n",__FILE__,__FUNCTION__,__LINE__);
	printk(KERN_CRIT "KERN_CRIT Hello Linux\n");
	printk(KERN_ERR "KERN_ERR Hello Linux\n");
	printk(KERN_WARNING "KERN_WARNING Hello Linux\n");
	printk(KERN_NOTICE "KERN_NOTICE Hello Linux\n");
	printk(KERN_INFO "KERN_INFO Hello Linux\n");
	printk(KERN_DEBUG "KERN_DEBUG Hello Linux\n");
	printk("Default Hello Linux\n");
	printk(KERN_ALERT "KERN_ALERT The process is %s  %i\n", current->comm, current->pid);	//打印出当前进程所执行程序文件的基本名称以及进程号;
	
	add(2, 10);
  	return 0;
}

static void hello_exit(void)	//使用static,可以是的函数的作用域在本文件
{

}

EXPORT_SYMBOL_GPL(x);		//导出符号x
EXPORT_SYMBOL_GPL(add);		//导出函数add

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("module");
MODULE_AUTHOR("[email protected]");
MODULE_VERSION("version 1.0");

module2.c

#include 
#include 
#include 

extern int x;		//仅仅是申明使用外来文件定义的x,而去掉extern,那就是本文件的x;如果没有文件导出x,那么在insmod会出现unkonwn symbol的错误;

int y;

extern int add(int, int);

static char *whom = "world";
static char *whom2 = "hello";

static int hello_init(void)
{
	add(6, 20);
	printk("Default Hello Linux %d ,%d ,%s, %s\n", x, y, whom, whom2);
  	return 0;
}

static void hello_exit(void)	//使用static,可以是的函数的作用域在本文件
{
	
}

module_param(whom, charp, S_IRUGO);	//允许任何用户,模块参数

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("module");
MODULE_AUTHOR("[email protected]");
MODULE_VERSION("version 1.0");

Makefile

obj-m += module1.o module2.o

KERN_DIR := /lib/modules/2.6.32-62-generic/build

all:
	make -C $(KERN_DIR) M=`pwd` modules

clean:
	make -C $(KERN_DIR) M=`pwd` modules clean
	rm -rf modules.order

程序输出

【基本知识】printk,模块机制_第1张图片

你可能感兴趣的:(Linux内核)