模块编译入门例子hello_module
如何编译第一个模块 hello.ko

如何编译第一个模块hello.ko2011-08-16 21:06 25人阅读评论(0) 收藏举报看了书后,照着书上的方法一步一步去做,却失败了,555真是的,写书的人啊,却不考虑一下细节问题新建一个目录[liu@liu-desktop hellomod]$mddir hellomod[liu@liu-desktop hellomod]$cd hellomod[liu@liu-desktop hellomod]$vi hellomod.c/****************hellomod.c*******************************/#include <linux/module.h> //所有模块都需要的头文件#include <linux/init.h> // init&exit相关宏MODULE_LICENSE("GPL");static int __init hello_init (void){printk("Hello china init/n");return 0;}static void __exit hello_exit (void){printk("Hello china exit/n");}module_init(hello_init);module_exit(hello_exit);/****************hellomod.c*******************************/1、在下载了linux 2.6的内核,解压到/usr/src/linux26目录下[root@liu-desktop linux26]# lsarch CREDITS drivers init kernel Makefile README security block crypto fs ipc lib mm REPORTING-BUGS sound COPYING Documentation include Kbuild MAINTAINERS net scripts usr ----------------------------------------------写一个Makefile文件:内容如下:obj-m := hellomod.o------------------------------------------------[liu@liu-desktop hellomod]$ make -C /usr/src/linux26/ SUBDIRS=$PWD modules make: Entering directory `/usr/src/linux26'ERROR: Kernel configuration is invalid.include/linux/autoconf.h or include/config/auto.conf are missing.Run 'make oldconfig && make prepare' on kernel src to fix it.W ARNING: Symbol version dump /usr/src/linux26/Module.symversis missing; modules will have no dependencies and modversions.CC [M] /home/liu/test/hellomod/hellomod.occ1: 错误:include/linux/autoconf.h:No such file or directory在包含自include/linux/posix_types.h:47 的文件中,从include/linux/types.h:14,从include/linux/prefetch.h:13,从include/linux/list.h:8,从include/linux/module.h:9,从/home/liu/test/hellomod/hellomod.c:1:/usr/lib/gcc/i486-linux-gnu/4.1.3/include/asm/posix_types.h:13:22: 错误:features.h:No such file or directory/usr/lib/gcc/i486-linux-gnu/4.1.3/include/asm/posix_types.h:14:35: 错误:没有包含路径可供搜索asm/posix_types.h ...............................解决方法:[liu@liu-desktop hellomod]#make oldconfig[liu@liu-desktop hellomod]#make prepare好了,在试试:[liu@liu-desktop hellomod]$ make -C /usr/src/linux26/ SUBDIRS=$PWD modules还是有错:make: Entering directory `/usr/src/linux26'W ARNING: Symbol version dump /usr/src/linux26/Module.symversis missing; modules will have no dependencies and modversions.CC [M] /home/liu/test/hellomod/hellomod.oBuilding modules, stage 2.MODPOST 1 modules/bin/sh: scripts/mod/modpost: not foundmake[1]: *** [__modpost] 错误127make: *** [modules] 错误2make: Leaving directory `/usr/src/linux26'看到了吗,提示说没有scripts/mod/modpost,那我们就编译它吧[root@liu-desktop linux26]# make scriptsHOSTCC scripts/genksyms/genksyms.oSHIPPED scripts/genksyms/lex.cSHIPPED scripts/genksyms/parse.hSHIPPED scripts/genksyms/keywords.cHOSTCC scripts/genksyms/lex.oSHIPPED scripts/genksyms/parse.cHOSTCC scripts/genksyms/parse.oHOSTLD scripts/genksyms/genksymsCC scripts/mod/empty.oHOSTCC scripts/mod/mk_elfconfigMKELF scripts/mod/elfconfig.hHOSTCC scripts/mod/file2alias.oHOSTCC scripts/mod/modpost.oHOSTCC scripts/mod/sumversion.oHOSTLD scripts/mod/modpostHOSTCC scripts/kallsymsHOSTCC scripts/conmakehashOK,好了[liu@liu-desktop hellomod]$ make -C /usr/src/linux26/ SUBDIRS=$PWD modulesmake: Entering directory `/usr/src/linux26'W ARNING: Symbol version dump /usr/src/linux26/Module.symversis missing; modules will have no dependencies and modversions.Building modules, stage 2.MODPOST 1 modulesCC /home/liu/test/hellomod/hellomod.mod.oLD [M] /home/liu/test/hellomod/hellomod.komake: Leaving directory `/usr/src/linux26'[liu@liu-desktop hellomod]$ lshellomod.c hellomod.ko hellomod.mod.c hellomod.mod.o hellomod.o Makefile Module.sy mvers[root@liu-desktop linux26]#insmod hellomod.ko[root@liu-desktop linux26]#lsmod |grep hellomodlsmod |grep hellomod[root@liu-desktop linux26]#rmmod hellomod注意:如果出现下面错误,那99%是内核版本号对不上,也就是version magic不对insmod: error inserting 'hellomod.ko': -1 Invalid module format此时,你用sudo tail /var/log/messages你在最后一行应该看到类似下面的提示:Dec 19 13:42:29 localhost kernel: hellomod: version magic '2.6.24.2 SMP mod_unload 686 4KSTACKS ' should be '2.6.27.7-134.fc10.i686 SMP mod_unload 686 4KSTACKS '那该怎么办呢?最简单的办法就是:修改源目录下的Makefie把最Makefile第1-4行的值改为当前内核一样的值VERSION = 2PA TCHLEVEL = 6SUBLEVEL = 24EXTRA VERSION = .2NAME = Err Metey! A Heury Beelge-a Ret!那怎么确定你当前内核的值是多少呢?vi /lib/modules/`uname -r`/build/Makefile现在知道了吧?。
实验二三合

嵌入式系统实验报告嵌入式Linux设备驱动实验学院电子与信息学院专业电子科学与技术学生姓名李泓鑫黄勇实验台号9指导教师提交日期 2015 年 4月 22日1. 了解Linux驱动程序的结构2. 初步掌握Linux驱动程序的编写方法及过程3. 掌握Linux驱动程序的加载方法。
二、实验内容1. 杂项驱动框架的编程实现;2. 具有Led控制功能的驱动编程实现;三、实验原理要写led的设备驱动,首先要了解其硬件电路的设计,才能使之正常工作。
从Tiny210的用户手册中,我们可以找到其led的设计说明。
由此,我们明确LED1~LED4分别由GPJ2_0 ~ GPJ2_3这四个io引脚来控制。
并且由Tiny210的用书手册说明,可知此GPIO输出是低电平有效。
当GPJ作为输出io口的时候,GPJ0 ~ GPJ3的输出,对应于此数据寄存器(0xE0200284)的bit0 ~ bit3. 在这四个bits上,0对应于输出低电平,会使对应的led点亮;1对应于输出高电平,会使对应的led熄灭。
杂项设备是比较简单的字符设备,主设备固定为10,次设备号由linux内核分配。
不需手动创建设备节点,注册和注销设备都比较简单。
框架中,定义了内核模块入口函数TestChar_init和出口函数TestChar_exit分别进行杂项设备的注册misc_register和注销misc_deregister。
file_operations定义了此设备的操作接口,只定义了读和写两个接口函数,分别为TestRead和TestWrite。
这两个函数中,把一个内部整型全局变量myData 和用户进行拷贝传递。
测试程序会打开TestMisc设备,然后读取该设备,再写入该设备,并进行打印显示。
1、杂项设备是比较简单的字符设备。
主设备固定为10,次设备号由linux 内核分配。
不需手动创建设备节点。
注册和注销设备都比较简单。
比较适合用于led驱动。
go module的使用例子

go module的使用例子
Go语言的模块(module)是Go 1.11版本引入的一个重要特性,它可以帮助开发者更好地管理项目的依赖关系和版本控制。
下面我
将为你提供一个简单的使用例子。
首先,假设你有一个名为`hello`的项目,你可以通过以下步骤
来使用Go模块:
1. 首先,创建一个新的目录作为你的项目目录,例如
`hello_project`。
2. 在命令行中进入该目录,并运行`go mod init`命令,例如
`go mod init hello_project/hello`。
这将会初始化一个新的模块,并生成一个`go.mod`文件,用来记录你项目的依赖关系。
3. 接下来,你可以创建一个`main.go`文件,内容可以是一个
简单的Hello World程序。
例如:
go.
package main.
import "fmt"
func main() {。
fmt.Println("Hello, Go Module!")。
}。
4. 保存`main.go`文件后,你可以在命令行中运行`go run .`命令来执行你的程序。
Go模块会自动帮你下载和管理依赖。
5. 如果你想引入其他的第三方包作为你项目的依赖,你可以在代码中直接import这些包,然后运行`go mod tidy`命令来自动更新你的`go.mod`和`go.sum`文件。
总之,使用Go模块可以让你更方便地管理项目的依赖关系,确保你的项目能够稳定、可靠地构建和运行。
希望这个例子能够帮助你更好地理解如何使用Go模块。
Nano之HelloWorld驱动(学习如何单独编译.ko模块)

Makefile
1 把下面3个参数改成你自己的: 2 obj-m (.o文件) 3 KERNELDIR (内核目录全路径) 4 CROSS_ARCH (架构及其编译器)
1 #set KERNELDIR and CROSS_COMPILE path yourself
2#
3 ifneq ($(KERNELRELEASE),)
1、准备下面两个文件:
1 Makefile 2 nano_hello_module.c
nano_hello_module.c
1 #include <linux/kernel.h> 2 #include <linux/module.h> 3 4 static int __init nano_hello_module_init(void) 5{ 6 printk("Hello yfw, Nano module is installed !\n"); 7 return 0; 8} 9 10 static void __exit nano_hello_module_cleanup(void) 11 { 12 printk("Good-bye yfw, Nano module was removed!\n"); 13 } 14 15 module_init(nano_hello_module_init); 16 module_exit(nano_hello_module_cleanup); 17 18 MODULE_LICENSE("GPL");
博客园 用户登录 代码改变世界 密码登录 短信登录 忘记登录用户名 忘记密码 记住我 登录 第三方登录/注册 没有账户, 立即注册
Nano之 HelloWorld驱动(学习如何单独编译 .ko模块)
模块化编程案例

模块化编程案例模块化编程是一种将程序划分为独立、可重用、可测试的模块的编程方法。
它能够提高代码的可维护性、可读性和可复用性,并且使开发过程更加高效。
下面是一些关于模块化编程的案例:1. 案例一:图书管理系统在一个图书馆的图书管理系统中,可以将不同功能的代码模块化,比如图书的借阅模块、归还模块、查询模块等。
每个模块都有自己的功能和接口,可以独立进行开发和测试。
这样,当需要修改或添加某个功能时,只需修改对应的模块,而不影响其他模块的功能。
2. 案例二:购物网站在一个购物网站的后台管理系统中,可以将不同功能的代码模块化,比如商品管理模块、订单管理模块、用户管理模块等。
每个模块都有自己的功能和接口,可以独立进行开发和测试。
这样,当需要修改或添加某个功能时,只需修改对应的模块,而不影响其他模块的功能。
3. 案例三:游戏开发在游戏开发中,可以将不同功能的代码模块化,比如角色控制模块、地图生成模块、碰撞检测模块等。
每个模块都有自己的功能和接口,可以独立进行开发和测试。
这样,当需要修改或添加某个功能时,只需修改对应的模块,而不影响其他模块的功能。
4. 案例四:音乐播放器在一个音乐播放器的软件中,可以将不同功能的代码模块化,比如音乐搜索模块、播放控制模块、歌词显示模块等。
每个模块都有自己的功能和接口,可以独立进行开发和测试。
这样,当需要修改或添加某个功能时,只需修改对应的模块,而不影响其他模块的功能。
5. 案例五:社交媒体平台在一个社交媒体平台的开发中,可以将不同功能的代码模块化,比如用户管理模块、信息发布模块、评论管理模块等。
每个模块都有自己的功能和接口,可以独立进行开发和测试。
这样,当需要修改或添加某个功能时,只需修改对应的模块,而不影响其他模块的功能。
6. 案例六:电子邮件客户端在一个电子邮件客户端的开发中,可以将不同功能的代码模块化,比如邮件接收模块、邮件发送模块、邮件搜索模块等。
每个模块都有自己的功能和接口,可以独立进行开发和测试。
hello内核模块编译的全过程

示包含$(PWD)下的Makefile文件。3),modules表示模块编译。4),用到了
ifneq...else...endif语句由于开始还没定义KERNELRELEASE,所以只能执行else
分支。而在执行$(MAKE)-C$(KERNELDIR)M=$(PWD)modules后,会在内
核的Makefile中定义KERNELRELEASE,当进入本Makefile时,则只会执行
module_init(),module_exit()kernel.h中的printk(),KERN_ALERTmodule.h中的
MODULE_LICENSE()
2,Makefile文件中的核心是$(MAKE) -C $(KERNELDIR) M=$(PWD) modules1),
-C $(KERNELDIR)表示在$(KERNELDIR)目录下执行make命令。2),M=$(PWD)表
staticint hello_init(void){printk(KERN_ALERT“hellomoduleinit\n”);return0;}
staticvoid hello_exit(void){printk(KERN_ALERT“hellomoduleexit\n”);}
module_init(hello_init);module_exit(hello_exit);
KERN_ALERT“1”修改为#define KERN_ALERT“0”
------------安装模块
#insmod hello.ko
终端显示hello module init
查看已安装的模块#lsmod
卸载模块
openharmony cfg语法

openharmony cfg语法CFG语法是OpenHarmony的配置文件语法,用于配置系统的各种属性和模块的编译选项。
以下是CFG语法的一些常用规则和示例:1. 基本格式:[SECTION]key = value2. 注释:使用"#"符号表示注释,如:# This is a comment3. SECTION的命名规则:使用方括号括起来的大写字母、数字或下划线组成的字符串,如:[DEVICE]4. key的命名规则:小写字母、数字或下划线组成的字符串,如:enable_feature = true5. value的类型:可以是字符串、布尔值或整数,如:module_name = "hello"enable_feature = falseversion = 16. 模块的编译选项:可以通过设置key的值来启用或禁用某个模块的编译选项,如:enable_fs_module = trueenable_network_module = false7. 条件语句:使用if和endif来定义条件语句,根据条件来决定是否执行某段配置,如:if (key == value){# do something}endif可以使用==、!=、<、<=、>、>=等比较操作符,并支持逻辑运算符和括号的使用。
8. 导入其他配置文件:可以使用import语句来导入其他配置文件,如:import "config.txt"以上是CFG语法的一些常用规则和示例,CFG语法还支持更多的高级特性,可以根据具体需要进行更详细的研究和了解。
linux模块编译步骤(详解)

Linux内核模块编程Linux 内核模块编程是一个很重要的知识点。
尤其是编写底层驱动程序时,一定会涉及到它。
内核模块编程也是 Tiger哥学习 Linux 时第一节课所接触的知识。
由此可以看出它的 important, 也可以看出其实它很 easy 。
一前言:1. 什么是内核模块1> 内核模块是具有独立功能的程序。
它可以被单独编译,但是不能单独运行,它的运行必须被链接到内核作为内核的一部分在内核空间中运行。
2> 模块编程和内核版本密切相连,因为不同的内核版本中某些函数的函数名会有变化。
因此模块编程也可以说是内核编程。
3> 特点:模块本身不被编译进内核映像,从而控制了内核的大小;模块一旦被加载,就和内核中的其他部分完全一样。
2 . 用户层编程和内核模块编程的区别应用程序内核模块程序使用函数libc库内核函数运行空间用户空间内核空间运行权限普通用户超级用户入口函数main()module_init出口函数exit()module_exit编译gcc makefile链接gcc insmod运行直接运行insmod调试gdb kdbug、kdb、kgdb二 . 说了这么多,那么怎么编写一个内核模块的程序呢?1. 我们先来看两个最简单的函数实例,也是几乎所有程序员在学习一门新语言时都会编写的程序:输出 hello world!现在我们分别用模块编程输出 hello world! ,和在用户层编程输出 hello wrold !。
通过这两个程序我们来分析下如何来编写一个内核模块程序。
用户层编程: hello.c#include<stdio.h>int main(void){printf("hello world/n");}内核编程 : module.c#include <linux/init.h>#include <linux/module.h>#include <linux/kernel.h>MODULE_LICENSE("Dual BSD/GPL");static int hello_init(void){printk(KERN_ALERT "hello,I am edsionte/n");return 0;}static void hello_exit(void){printk(KERN_ALERT "goodbye,kernel/n");}module_init(hello_init);module_exit(hello_exit);// 可选MODULE_AUTHOR("Tiger-John");MODULE_DESCRIPTION("This is a simple example!/n"); MODULE_ALIAS("A simplest example");Tiger-John说明:1.> 相信只要是学过 C 语言的同学对第一个程序都是没有问题的。
linux Kconfig说明

endmenu
再看led目录下的Makefile和Kconfig:
Makefile为文件:
obj-$(CONFIG_LED)+=led.o
Kconfig文件:
config LED
tristate “led support”
key目录下的Makefile和Kconfig类似。
1 #
2 # Automatically generated make config: don’t edit
3 #
4 CONFIG_X86=y
5 CONFIG_MMU=y
6 CONFIG_UID16=y
7 CONFIG_GENERIC_ISA_DMA=y
8
9 #
10 # Code maturity level options
obj-$(CONFIG_TEST) += test.o #因为在myDriver目录中要编译test.c文件
#所以会根据CONFIG_TEST来决定编译选项
obj-y += led/#编译myDriver目录中的子目录led
obj-y += key/#编译myDriver目录中的子目录key
然后Kconfig文件是:
menu “TEST MyDriver” #在make menuconfig时要显示的菜单入口
comment “Test myDriver” #menu title
config TEST
tristate “MyDriver test”
source “drivers/myDriver/led/Kconfig”#将led目录下的Kconfig添加进来
verilog编译指令

Verilog是一种硬件描述语言,用于设计和建模电子系统,特别是数字系统。
Verilog语言具有编译指令,这些指令告诉编译器如何处理代码。
以下是一些常见的Verilog编译指令:1. `module`: 这是Verilog中最基本的编译指令,用于定义一个模块。
模块是Verilog设计的基本单元,它描述了电路的功能。
```verilogmodule module_name (input, output, ...);...endmodule```2. `parameter`: 该指令用于定义参数,可以在模块实例化时进行赋值。
```verilogparameter PARAMETER_NAME = DEFAULT_VALUE;```3. `input`: 该指令用于定义模块的输入端口。
```veriloginput port_name;```4. `output`: 该指令用于定义模块的输出端口。
```verilogoutput port_name;```5. `reg`: 该指令用于定义寄存器类型。
在Verilog中,所有的信号都必须是寄存器类型或者线类型。
```verilogreg reg_name;```6. `wire`: 该指令用于定义线类型。
线类型通常用于表示信号,并且可以驱动其他寄存器类型的变量。
```verilogwire wire_name;```7. `assign`: 该指令用于为线类型变量赋值。
在Verilog中,线类型变量不能在连续赋值语句中使用,必须使用`assign`语句进行赋值。
```verilogassign wire_name = expression;```8. `initial`: 该指令用于定义模块的初始化代码块。
在Verilog 中,所有的模块都必须有一个`initial`块。
```veriloginitial begin// initialization code hereend```。
简单实例讲解linux的module模块编译步骤

简单实例讲解linux的module模块编译步骤本⽂将直接了当的带你进⼊linux的模块编译。
当然在介绍的过程当中,我也会添加⼀些必要的注释,以便初学者能够看懂。
之所以要写这篇⽂章,主要是因为从书本上学的话,可能要花更长的时间才能学会整个过程,因为看书的话是⼀个学习过程,⽽我这篇⽂章更像是⼀个培训。
所以实践性和总结性更强。
通过本⽂你将会学到编译⼀个模块和模块makefile的基本知识。
以及加载(卸载)模块,查看系统消息的⼀些知识;第⼀步:准备源代码⾸先我们还是要来编写⼀个符合linux格式的模块⽂件,这样我们才能开始我们的模块编译。
假设我们有⼀个源⽂件mymod.c。
它的源码如下:mymod.c#include#include#includeMODULE_AUTHOR("Yu Qiang");MODULE_LICENSE("GPL");static int nbr = 10;module_param(nbr, int, S_IRUGO);static int __init yuer_init(void){int i;for(i=0; i{printk(KERN_ALERT "Hello, How are you. %d\n", i);}return0;}static void __exit yuer_exit(void){printk(KERN_ALERT"I come from yuer's module, I have been unlad.\n");}module_init(yuer_init);module_exit(yuer_exit);我们的源⽂件就准备的差不多了,这就是⼀个linux下的模块的基本结构。
第9⾏是导出我们的符号变量nbr。
这样在你加载这个模块的时候可以动态修改这个变量的值。
稍后将演⽰。
c++ import语法

c++ import语法随着C++的不断发展,对模块化和代码组织的需求也在不断增加。
C++20标准引入了模块系统,其中import 语法是一个关键的组成部分。
本文将深入探讨C++中的import 语法,介绍其基本用法、特性以及在代码组织和可维护性方面的优势。
1. import 语法基础1.1 引入头文件的问题在传统的C++编程中,为了使用外部代码,我们通常需要使用#include 来引入头文件。
这种方式存在一些问题,如头文件的重复包含、宏定义的处理等。
1.2 import 的引入C++20引入了import 语法,它更为现代化和模块化。
使用import 可以直接导入模块,而无需使用传统的头文件引入方式。
import module_name;2. 模块的创建和使用2.1 模块的创建要使用import,首先需要创建一个模块。
模块是一个包含了代码和声明的独立单元。
以下是一个简单的模块示例:export module module_example;export void hello(){// 模块的实现// ...}2.2 模块的使用通过import 语句,可以在其他文件中使用已创建的模块:// main.cppimport module_example;int main(){hello();// 调用模块中的函数return0;}3. import 的特性3.1 命名空间的处理import 语法引入了一种新的命名空间处理方式。
模块中的符号默认处于模块的命名空间中,不会污染全局命名空间。
export module module_example;namespace module_example {void hello(){// 模块的实现// ...}}在使用时,可以明确指定命名空间:// main.cppimport module_example;int main(){module_example::hello();return0;}3.2 编译时性能优化使用import 语法还带来了一些编译时的性能优化。
Ubuntu编译的第一个内核模块hello

所有模块都要使用头文件module.h,此文件必须包含进来。
头文件kernel.h包含了常用的内核函数。
头文件init.h包含了宏_init和_exit,它们允许释放内核占用的内存。
lkp_init是模块的初始化函数,它必需包含诸如要编译的代码、初始化数据结构等内容。
使用了printk()函数,该函数是由内核定义的,功能与C库中的printf()类似,它把要打印的信息输出到终端或系统日志。
lkp_cleanup是模块的退出和清理函数。
此处可以做所有终止该驱动程序时相关的清理工作。
module_init()和cleanup_exit()是模块编程中最基本也是必须的两个函数。
module_init()是驱动程序初始化的入口点。
而cleanup_exit()注销由模块提供的所有功能。
2 编写Makefile 文件,与hello.c 放在同一个目录里obj-m := hello.oKERNELBUILD :=/lib/modules/$(shell uname-r)/builddefault: make -C $(KERNELBUILD) M=$(shell pwd) modulesclean: rm -rf *.o *.ko *.mod.c .*.cmd *.markers *.order *.symvers .tmp_versions(注意makefile里面要求的tab)KERNELBUILD :=/lib/modules/$(shell uname -r)/build是编译内核模块需要的Makefile的路径,Ubuntu下是/lib/modules/2.6.31-14-generic/buildmake -C $(KERNELBUILD) M=$(shell pwd) modules 编译内核模块。
-C 将工作目录转到KERNELBUILD,调用该目录下的Makefile,并向这个Makefile传递参数M的值是$(shell pwd) modules。
visual studio中的fortran中的模块编译 -回复

visual studio中的fortran中的模块编译-回复在Visual Studio 中使用Fortran 编程时,模块是一种组织代码、管理变量和函数的重要方式。
模块可以提供更好的代码可读性和复用性,并且能够帮助减少编程错误。
本文将一步一步地介绍如何在Visual Studio 中编译和使用Fortran 中的模块。
第一步:创建Visual Studio 项目首先,在Visual Studio 中创建一个新的Fortran 项目。
点击菜单栏中的"文件",然后选择"新建"-> "项目"。
在弹出的对话框中,选择"Visual Fortran"-> "Windows"-> "空项目"。
填写项目名称和存储位置,点击"确定"。
第二步:添加Fortran 源代码在解决方案资源管理器中,右键点击项目名称,然后选择"添加"-> "新建项"。
在弹出的对话框中,选择"Visual Fortran"-> "源文件",填写文件名称(例如,module.f90)和存储位置,点击"添加"。
在新建的文件中,输入以下代码:fortranmodule mymoduleimplicit noneinteger :: myvarcontainssubroutine mysub()print *, "Hello from mysub!"end subroutine mysubend module mymodule这段代码定义了一个名为"mymodule" 的模块,其中包含一个整数变量"myvar" 和一个名为"mysub" 的子程序。
编译hello Word内核模块

编译hello Word内核模块:1. 写hello.c/** hello.c _The Hello, World! 我们的第一个内核模块*/#include <linux/init.h> /* needed for the macros */宏#include <linux/module.h> /* needed by all modules */#include <linux/kernel.h> /* needed for KERN_ALERT */static int __init hello_init(void){printk(KERN_ALERT "Hello world!\n");return 0;}static void __exit hello_exit(void){printk(KERN_ALERT "Hello world exit.\n");}module_init(hello_init);module_exit(hello_exit);MODULE_LICENSE("GPL");2.写Makefile文件(新建空文件,命名Makefile)obj-m +=hello.o3.进入test_module文件夹(存放hello.c Makefile)输入命令:make -C /usr/src/linux-`uname -r` SUBDIRS=$PWD modules注:uname –r 命令是显示内核版本号的,也可以直接把所有内核版本号写上使用insmod ./hello.ko 命令加载该模块进入/proc目录cd /proc用查看命令cat 查看modules文件:cat modules使用rmmod hello. 卸载模块进入/var/log目录用命令cat 查看messages文件内容是否有相关的日志内容:cat messages。
操作系统课程设计 内核模块编程和设备驱动程序

课程设计题目内核模块编程和设备驱动程序学生姓名朱小波学号**********专业计算机科学与技术班级20091121指导教师张莉莉完成日期2012年1月5日Linux内核模块编程与设备驱动程序摘要:本文给出了一个linux字符设备驱动程序的例子,其包括了内核模块编程.其主要功能是:在内存虚拟一个字符设备,并由编写的驱动程序加载到系统,完成字符的输入与输出功能.此设备驱动程序可以用作linux实践教学的实例.关键词:字符设备驱动;内核模块编程;虚拟;模拟1 前言驱动程序是应用程序和硬件设备的一个接口,linux设备驱动程序属于内核的一部分,熟练驱动程序和内核模块开发需要硬件知识,了解操作系统的实现,需要了解内核基础知识,了解内核中的并发控制和同步以及复杂的软件结构框架.本文论述了如何在linux下实现一个简单的字符设备驱动程序,主要完成了内核树的建立、内核的编译、字符设备的模拟、字符设备的驱动、字符设备驱动程序的测试等.本文首先阐述了设备驱动程序和内核模块编程的基础知识,然后给出了实现一个设备驱动程序的总体框架,最后根据框架一步步详细完成了一个字符设备驱动程序,包括终端命令和源程序的编写.做好设备驱动程序可以更好的了解硬件和操作系统,本设备驱动程序可以作为操作系统实验课程的实例.2 设备驱动程序和内核模块编程相关基础知识linux内核是一个整体是结构.因此向内核添加任何东西.或者删除某些功能,都十分困难.为了解决这个问题. 引入了内核机制.从而可以可以动态的想内核中添加或者删除模块.模块不被编译在内核中,因而控制了内核的大小.然而模块一旦被插入内核,它就和内核其他部分一样.这样一来就会增加一部分系统开销.同时,假如模块出现问题.,也许会带来系统的崩溃.2.1模块的实现机制:启动时,由函数 void inti_modules 来初始化模块,.因为启动事很多时候没有模块.这个函数往往把内核自身当作一个虚模块.如由系统需要,则调用一系列以sys 开头的函数,对模块进行操作. 如:sys_creat_modules,sys_inti_modules , sys_deldte_modules等等.这里会用到一些模块的数据就结构,在/usr/scr/linux/include/linux/module.h 中.块的加入有两种方法:一是手动加入:如:insmod modulename.另一种是根据需要,动态的加载模块.如你执行命令:$mount -t msdos /dev/hdd /mnt/d 时.系统便自动加载 FAT模块,以支持MSDOS 的文件系统.2.2 模块编程写一个模块,必须有一定的多进程编程基础.因为编的程序不是以一个独立的程序的来运行的.另外,因为,模块需要在内核模式下运行,会碰到内核空间和用户空间数据交换的问题.一般的数据复制函数无法完成这一个过程.因此系统已入了一些非凡的函数以用来完成内核空间和用户空间数据的交换. 这些函数有:void put _user、memcpy_tofs 等等,需要说明的是.模块编程和内核的版本有很大的关系. 假如版本不通可能造成,内核模块不能编译,或者.在运行这个模块时,出现不可测结果.如:系统崩溃等.对于每一个内核模块来说.必定包含两个函数:int init_module :这个函数在插入内核时启动,在内核中注册一定的功能函数,或者用它的代码代替内核中某些函数的内容.因此,内核可以安全的卸载.int cleanup_module:当内核模块卸载时调用.将模块从内核中清除.2.3内核模块与应用程序对比应用程序是一个进程,编程从主函数main()开始,主函数main返回即是进程结束,使用glibc的库.驱动程序是一系列内核函数,函数入口和出口不一样,使用Linux内核的函数,这些函数由内核在适当的时候来调用,这些函数可以用来完成硬件访问等操作.2.4设备的分类设备一般分为字符设备(char device)、块设备(block device)、网络设备(network device).图1:设备的分类i字符设备特点:像字节流一样来存取的设备( 如同文件 )通过/dev下的文件系统结点来访问通常至少需要实现 open, close, read, 和 write 等系统调用只能顺序访问的数据通道,不能前后移动访问指针.特例:比如framebuffer设备就是这样的设备,应用程序可以使用mmap或lseek访问图像的各个区域ii块设备特点:块设备通过位于 /dev 目录的文件系统结点来存取块设备和字符设备的区别仅仅在于内核内部管理数据的方式块设备有专门的接口,块设备的接口必须支持挂装(mount)文件系统.应用程序一般通过文件系统来访问块设备上的内容图2:块设备驱动图3:网络设备驱动linux中的大部分驱动程序,是以模块的形式编写的.这些驱动程序源码可以修改到内核中,也可以把他们编译成模块形式,在需要的时候动态加载.一个典型的驱动程序,大体上可以分为这么几个部分:1,注册设备在系统初启,或者模块加载时候,必须将设备登记到相应的设备数组,并返回设备的主驱动号,例如:对快设备来说调用 refister_blkdec将设备添加到数组blkdev中.并且获得该设备号.并利用这些设备号对此数组进行索引.对于字符驱动设备来说,要使用 module_register_chrdev来获得祝设备的驱动号.然后对这个设备的所有调用都用这个设备号来实现.图4:内核模块调用过程2,定义功能函数对于每一个驱动函数来说.都有一些和此设备密切相关的功能函数.那最常用的块设备或者字符设备来说.都存在着诸如 open read write ioctrol这一类的操作.当系统社用这些调用时.将自动的使用驱动函数中特定的模块.来实现具体的操作.而对于特定的设备.上面的系统调用对应的函数是一定的. 如:在块驱动设备中.当系统试图读取这个设备时),就会运行驱动程序中的block_read 这个函数. 打开新设备时会调用这个设备驱动程序的device_open 这个函数.3,卸载模块在不用这个设备时,可以将它卸载.主要是从/proc 中取消这个设备的文件.可用特定的函数实现.3 设备驱动程序实现框架4 数据结构设计与主要功能函数(1)字符设备描述结构体:struct cdev {struct kobject kobj; /*内嵌的kobject对象*/struct module *owner; /*所属模块*/const struct file_operations *ops; /*文件操作结构体*/struct list_head list; /*双向循环链表*/dev_t dev; /*设备号32位高12位为主设备号,低20位为次设备号*/unsigned int count; /*设备数量*/};(2) 设备描述结构体struct mem_dev{char *data; /*数据*/unsigned long size; /*长度*/};表1 主要功能函数列表主要函数列表功能说明int mem_open(struct inode *inode, struct file *filp) 文件打开int mem_release(struct inode *inode, struct file *filp) 文件释放读文件static ssize_t mem_read(struct file *filp, char __user *buf, size_tsize, loff_t *ppos)写文件static ssize_t mem_write(struct file *filp, const char __user *buf,size_t size, loff_t *ppos)static loff_t mem_llseek(struct file *filp, loff_t offset, int whence) 文件定位static int memdev_init(void) 设备驱动模块加载static void memdev_exit(void) 卸载设备5 字符设备驱动程序的实现下载安装LINUX内核,需要下载和本机一样版本的内核源码.本设备驱动程序是在linux-3.0.12内核下进行的.5.1 安装编译内核所需要的软件并编译内核.使用以下命令安装需要的软件:sudo apt-get install build-essential autoconf automake cvs subversion kernel-package libncurses5-dev图5:安装所需软件在/pub/linux/kernel/v3.0/ 下载内核linux-3.0.12.tar.bz2将内核放置/usr/src目录下使用命令tar解压sudo tar jxvf linux-3.0.12.tar.bz2图6:解压内核使用以下命令配置系统cd linux-3.0.12cp /boot/config-`uname -r` ./.config #拷贝目前系统的配置文件make menuconfig终端会弹出一个配置界面最后有两项:load a kernel configuration... (.config)、save a kernel configuration... (.config) 选择load a kernel configuration保存,然后在选择save akernel configuration再保存退出,并退出配置环境.图7:配置系统参数make #这步需要比较长时间make bzImage #执行结束后,可以看到在当前目录下生成了一个新的文件: vmlinux, 其属性为-rwxr-xr-x.make modules #/* 编译模块*/make modules_install #这条命令能在/lib/modules目录下产生一个目录图8:make内核图9:make bzImage图10:make modules图11:make modules_installcd /usr/includerm -rf asm linux scsiln -s /usr/src/linux-3.0.12/include/asm-generic asmln -s /usr/src/linux-3.0.12/include/linux linuxln -s /usr/src/linux-3.0.12/include/scsi scsi5.2 编写字符设备驱动程序并调试编译.cd /rootmkdir firstdrivertouch memdev.c #建立驱动程序文件touch memdev.h #头文件touch Makefile #编写Makefile编译驱动程序模块make -C /lib/modules/3.0.0-12-generic/build M=/root/firstdriver modules图12:make 驱动程序ls查看当前目录的内容root@cloudswave-VirtualBox:~/firstdriver# lsMakefile memdev.h memdev.mod.c memdev.o Module.symversmemdev.c memdev.ko memdev.mod.o modules.order这里的memdev.ko就是生成的驱动程序模块.通过insmod命令把该模块插入到内核root@cloudswave-VirtualBox:~/firstdriver# insmod memdev.ko查看插入的memdev.ko驱动图13:查看插入的memdev.ko驱动可以看到memdev驱动程序被正确的插入到内核当中,主设备号为88,该设备号为如果这里定义的主设备号与系统正在使用的主设备号冲突,比如主设备号定义如下:#define MEMDEV_MAJOR 254,那么在执行insmod命令时,就会出现如下的错误:root@cloudswave-VirtualBox:~/firstdriver# insmod memdev.koinsmod: error inserting 'memdev.ko': -1 Device or resource busy5.3.测试驱动程序1,首先应该在/dev/目录下创建与该驱动程序相对应的文件节点,使用如下命令创建:root@cloudswave-VirtualBox:/dev# mknod memdev0 c 88 0使用ls查看创建好的驱动程序节点文件root@cloudswave-VirtualBox:/dev# ls -al memdev0图14:驱动程序节点文件2,编写如下应用程序memtest.c,来对驱动程序进行测试.编译并执行该程序root@cloudswave-VirtualBox:~/firstdriver# gcc -o memtest memtest.croot@cloudswave-VirtualBox:~/firstdriver# ./memtest图15:程序测试驱动手动测试驱动的方法:root@cloudswave-VirtualBox:~/firstdriver# echo 'haha shi wo' > /dev/memdev0root@cloudswave-VirtualBox:~/firstdriver# cat /dev/memdev06.小结:LINUX使用make编译驱动程序模块的过程.Linux内核是一种单体内核,但是通过动态加载模块的方式,使它的开发非常灵活、方便.那么,它是如何编译内核的呢?我们可以通过分析它的Makefile入手.以下是一个当我们写完一个hello模块,编写类似以上的Makefile.然后用命令make编译.假设我们把hello模块的源代码放在/home/examples/hello/下.当我们在这个目录运行make时,make是怎么执行的呢?首先,由于make后面没有目标,所以make会在Makefile中的第一个不是以.开头的目标作为默认的目标执行.于是default成为make的目标.make会执行make-C/lib/modules/3.0.0-12-generic/build M=/home/examples/hello/modules是一个指向内核源代码/usr/src/linux的符号链接.可见,make执行了两次.第一次执行时是读hello模块的源代码所在目录/home/examples/hello/下的Makefile.第二次执行时是执/usr/src/linux/下的Makefile.7 结束语本文给出了一个字符设备驱动与内核模块编程的完整实例,可以从中掌握内核编译、内核编程基础、设备驱动程序开发基础,优点是比较详细的给出了驱动开发的流程,并且把每一步的操作进行了详细的说明包括要执行的终端命令.最后还分析了驱动编译的过程.这样有利于初学者了解学习设备驱动的开发.有待进一步改进之处在于:此设备驱动程序针对的是字符设备,实现的功能比较简单,以后有时间可根据这次的开发流程,参考api编写块设备和网络设备的驱动程序.参考文献[1]Abraham Silberschatz 操作系统概念(第七版)影印版高等教育出版社,2007 [2]费翔林Linux操作系统实验教程高等教育出版社,2009[3](美)博韦等(DanielP. Bovet) 编著深入理解LINUX内核北京:中国电力出版社,2008 [4]Jonahan Corbet编著Linux设备驱动程序北京:中国电力出版社,2005附录。
Ubuntu16.04下的modules模块编译加载

Ubuntu16.04下的modules模块编译加载⼀、⾸先编写对应的驱动程序的相关内容:(最简单的hello.c程序)1 #include<linux/init.h>2 #include<linux/module.h>3 MODULE_LICENSE("Dual BSD/GPL");4 MODULE_AUTHOR("MDAXIA");56static int __init hello_init(void)7 {8 printk(KERN_ALERT "Hello world!\n");9return0;10 }11static void __exit hello_exit(void)12 {13 printk(KERN_ALERT "Goodbye,cruel world!");14 }15 module_init(hello_init);16 module_exit(hello_exit);⼆、编写对应Makefile⽂件:(注意事项Makefile,⾸字母⼤写M)1 ifeq ($(KERNELRELEASE),)2 KDIR:=/lib/modules/$(shell uname -r)/build3 PWD:=$(shell pwd)4 modules:5 $(MAKE) -C $(KDIR) M=$(PWD) modules6 modules_install:7 $(MAKE) -C $(KDIR) M=$(PWD) modules_install8 clean:9 rm -rf *.o *.ko .depend *.mod.o *.mod.c Module.* modules.*10 .PHONY:modules modules_install clean11else12 obj-m :=hello.o13 endif三、使⽤make指令对程序进⾏编译⽣成⽬标⽂件hello.kosudo make使⽤的是sudo make的指令来保证运⾏和⽂件的执⾏权限等等,编译的结果如下所⽰:这⾥成功⽣成了我们需要的.ko⽂件使⽤sudo make clean命令来清除相关的中间⽂件以及⽬标⽂件:sudo make clean这样就清除了所有的⽂件了~四、安装加载模块,需要的是root权限:sudo insmod ./hello.ko这⾥的路径变了⼀下,是因为我的Ubuntu16.04的实体主机加载模块的时候,需要数字签名,但是数字签名之后还是不能正确的加载,之后就在我的虚拟机Ubuntu16.04上实验了⼀下,这样居然成功了,因此路径有所改变,但是驱动成功加载了。
rust 多文件编译方法

rust 多文件编译方法Rust是一种现代的、安全的系统级编程语言,它鼓励开发者使用模块化的编程风格。
在Rust中,一个项目可以由多个文件组成,每个文件包含一个或多个模块。
这种模块化的结构有助于将代码分成更小、更易于管理的部分,并使其在多个文件之间共享。
要在Rust中进行多文件编译,你需要:1.创建模块:在Rust中,一个模块通常被定义为一个文件。
你可以在一个文件中定义一个模块,然后在其他文件中引用它。
模块定义需要使用关键字`mod`,后跟模块名称和模块的内容。
例如,我们可以在`module.rs`文件中定义一个名为`module`的模块:```rust// module.rspub mod module {pub fn print_message() {println!("Hello from module!");}}```2.导入模块:要在另一个文件中使用一个模块,你需要先导入它。
可以使用`use`关键字来导入一个模块。
例如,我们可以在`main.rs`文件中导入`module`模块,然后调用`print_message`函数:```rust// main.rsmod module;use module::module::print_message;fn main() {print_message();}```在导入模块时,需要使用双冒号`::`来指示模块的路径。
在这个例子中,我们需要指定`module::module`的路径,其中`module`是文件名。
3.构建项目:一旦你将代码分成多个文件和模块,在构建项目时,你需要告诉Rust编译器如何找到这些文件。
可以使用Cargo来管理和构建Rust项目。
创建一个名为`Cargo.toml`的文件,并添加以下内容:```toml[package]name = "my_project"version = "0.1.0"edition = "2018"[lib]name = "my_lib"path = "src/lib.rs"[[bin]]name = "my_binary"path = "src/main.rs"```在这个示例中,我们定义了一个库`my_lib`和一个可执行文件`my_binary`。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Linux 2.6内核的编译步骤及模块动态加载-操作系统中国网络
然后查看该目录下有哪些文件生成:
debian:/home/david # ls -l 总计 28 drwxr-xr-x 2 david david 4096 2007-02-07 17:49 Desktop -rw-r--r-- 1 david david 462 2007-07-20 13:42 hello.c -rw-r--r-- 1 root root 2432 2007-07-20 13:55 hello.ko -rw-r--r-- 1 root root 607 2007-07-20 13:55 hello.mod.c -rw-r--r-- 1 root root 1968 2007-07-20 13:55 hello.mod.o -rw-r--r-- 1 root root 1140 2007-07-20 13:55 hello.o -rw-r--r-- 1 david david 267 2007-07-20 13:48 Makefile -rw-r--r-- 1 root root 0 2007-07-05 14:11 Module.symvers
/linux/1601.html(第 3/8 页)200及模块动态加载-操作系统中国网络
//hello.c #include <linux/init.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);
●
.
专题 虚拟技术 Linux 防火墙 VPN 备份恢复 Vista
资源 新闻中心 认证培训 在线实验 软件下载 好书推荐
●
.
产品 服务器 网络设备 报价
●
.
ITPro俱乐部 论坛 《ITPro Magazine》杂志 博客
●
.
电子书
IBM Ctrix HP EMC TestInside |Firefox最安全的浏览器 | 订阅技术杂志 | ITPro俱乐部技术活动 |虚拟化技术专区 | 大量电子书技术手册 | 加入ITPro俱乐部
本文是基于2.6的内核,也建议各位可以先看一下《Linux内核设计与实现(第二版)》作为一个基础知识的 铺垫。当然,从实践角度来看,只要按着以下的步骤去做也应该可以实现成功编译内核及加载模块。 个人用的Linux版本为:Debian GNU/Linux,内核版本为:2.6.20-1-686. 第一步,下载Linux内核的源代码,即构建LDD3(Linux Device Drivers 3rd)上面所说的内核树。 如过安装的Linux系统中已经自带了源代码的话,应该在/usr/src目录下。如果该目录为空的话,则需要 自己手动下载源代码。下载代码的方法和链接很多,也可以在CU上通过/search/? key=&q=kernel&frmid=53去下载。不过,下载的内核版本最好和所运行的Linux系统的内核版本一致。当然,也 可以比Linux系统内核的版本低,但高的话应该不行(个人尚未实践)。
Linux 2.6内核的编译步骤及模块动态加载-操作系统中国网络
Ctrix,HP,EMC,CIW,Oracle,Comptia,IBM,
衡
●
热点: Certification Exams Questions;Bootcamp
Braindumps-TestInside
·RedHat Linux下防火墙配置入门必
最新专题:
HACMP for AIX 4.3.3 技术专题 命令大全
FreeBSD使用大全
Apache应用专题
Linux
专题 | 分类 | 投稿 | 搜索
操作系统首页 | 新闻动态 | Linux | freebsd | unix | Solaris | IBM AIX 操作系统首页 >> Linux >> Linux安全 >>
学
●
·Linux系统常用的三款网络安全工具 ·Linux操作系统中RPM命令参数的使
●
用详解
●
·介绍Linux操作系统下关于声卡配置的
方法
●
·Linux十大高级安全管理技巧
●
»导航列表
Debian下可以很方便的通过Debian源下载: 首先查找一下可下载的内核源代码: # apt-cache search linux-source 其中显示的有:linux-source-2.6.20,没有和我的内核版本完全匹配,不过也没关系,直接下载就可以 了: # apt-get install linux-source-2.6.20 下载完成后,安装在/usr/src下,文件名为:linux-source-2.6.20.tar.bz2,是一个压缩包,解压缩既可 以得到整个内核的源代码: # tar jxvf linux-source-2.6.20.tar.bz2 解压后生成一个新的目录/usr/src/linux——source-2.6.20,所有的源代码都在该目录下。 注:该目录会因内核版本的不同而不同,各位动手实践的朋友只需知道自己的源代码所在的具体位置即 可。 第二步:配置及编译内核。 进入/usr/src/linux——source-2.6.20目录下,可以看到Makefile文件,它包含了整个内核树编译信 息。该文件最上面四行是关于内核版本的信息。对于整个Makefile可以不用做修改,采用默认的就可以了。
Makefile文件的内容为:
obj-m := hello.o KERNELDIR := /lib/modules/2.6.20/build PWD := $(shell pwd) modules: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules modules_install: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install clean: rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
/linux/1601.html(第 2/8 页)2008-4-2 12:21:55
●
网管技术:网络知识 | 网络管理 | 网络 协议 | 传输介质 | 备份恢复 | 协议分析 | 安全:安全公告 | 病毒木马 | 安全知识 | 安全技术 | 防火墙 | VPN
精彩文章
●
活动资讯
今日头条
Linux 2.6内核的编译步骤及模块动态加载
●
·Ubuntu Server版系统的用户安全优
2007-07-24 20:24:02 作者: 来源:收集 浏览次数:183 文字大小:【大】【中】【小】 简介:本文是基于2.6的内核,也建议各位可以先看一下《Linux内核设计与实现(第二版)》作为一个基础 知识的铺垫。当然,从实践角度来看,只要按着以下的步骤去做也应该可以实现成功编译内核及加载模块。 个人用的 ... 关键字: Linux 内核 Linux 2.6内核 内核编译
化方法
●
·Apache Web服务的安全配置 ·linux下用iptable实现防火墙 ·Linux后门系列--由浅入深sk13完全
●
●
分析
●
·Linux下双网卡绑定技术实现负载均
/linux/1601.html(第 1/8 页)2008-4-2 12:21:55
其中,hello.c和Makefile文件应该位于同一个目录下,可以放在/home下,我的两个文件都位于/home/ david/. 第四步:编译和装载模块 在文件所处的目录下,执行: debian:/home/david # make
/linux/1601.html(第 4/8 页)2008-4-2 12:21:55
/linux/1601.html(第 5/8 页)2008-4-2 12:21:55
Linux 2.6内核的编译步骤及模块动态加载-操作系统中国网络
这里有两个问题,其一就是printk()输出的问题.LDD3上也说,在加载和卸载模块的时候都会有信息输出在 屏幕上,如果在Windows下通过终端仿真器(我们常用的虚拟机算是一种),则在屏幕上看不到任何输出.我同时 在虚拟机和和物理机都运行了该模块,均未看到有"Hello, world"(加载模块时printk的输出)或"Goodby, cruel world"(卸载模块时printk的输出). 这个不知道是我操作系统发行版的原因还是系统配置的问题,请了解 这个问题的朋友指点一下. 其二,书上讲到如果屏幕上看不到信息,可能输出在某个日志文件里面了,并说可能在/var/log/messages 文件中.并且看到网上很多网友也说是输出到这个文件里面.我不知道有没有发现输出在其他日志文件里的,不过 我的这个信息输出在/var/log/syslog里面.在加载和卸载完该模块后, 执行命令: debian:/home/david # cat /var/log/syslog | grep world 可以看到有两行内容.当然,也可以不用grep world, 应该会出现在最后两行. Jul 20 14:15:29 localhost kernel: Hello, world Jul 20 14:15:34 localhost kernel: Goodbye, cruel world 这就是printk应该输出的信息. 这里有另外一个方法,可以实现printk的信息输出在屏幕上,即更改printk输出的优先级.例子中的优先级 为:KERN_ALERT,优先级为<1>,如果将优先级改为KERN_EMERG即<0>,则可以看到屏幕的输出信息. 修改的方法只是修改一下hello.c中两句printk()的内容,修改后的hello.c如下: