linux编写程序读终端输入,linux编写一个简单的内核模块

编写一个简单的内核模块

(一)实验目的

Linux 操作系统的内核是单一体系结构(monolithic kernel)的,也就是说,整个内核是一个单独的非常大的程序。这样,系统的速度和性能都很好,但是可扩展性和维护性就相对比较差。为了弥补单一体系结构的这种缺陷,Linux操作系统使用了一种全新的机制-模块机制,用户可以根据需要,在不需要对内核重新编译的情况下,模块能动态地载入内核或从内核移出。

本实验通过分析代码,学习Linux 是如何实现模块机制的;通过一个实例,掌握如何编写模块程序并进一步掌握内核模块的机理。

(二)实验内容

实验内容一:

(1)编写一个内核模块helloworld.c当用insmod命令加载模块后,会显示HelloWorld !

#include

#include

MODULE_LICENSE("GPL");

MODULE_AUTHOR("jiang shuliang");

MODULE_DESCRIPTION("Hello World Module");

static int __init hello_init(void)

{

printk(KERN_EMERG"Hello World!\n");

return 0;

}

static void __exit hello_exit(void)

{

printk("<6>hello exit\n");

printk(KERN_EMERG"good bye!\n");

}

module_init(hello_init);

module_exit(hello_exit);

(2)编写Makefile文件

ifneq ($(KERNELRELEASE),)#注意ifneq后空格

obj-m := hello.o

else

KDIR := /lib/modules/$(shell uname -r)/build#改地址

all:

make -C $(KDIR) M=$(PWD) modules#注意tab

clean:

rm -f *.ko *.o *.mod.o *.mod.c *.symvers

endif

(3)执行make生成.ko文件

(4)加载模块 insmod 文件名.ko

(5)lsmod | grep 文件名       查看加载的模块

(6)dmesg

查看日志文件中模块输出的内容

(7)rmmod 文件名.ko     移除模块可以使用(5)查看是否移除成功

注意:

1.在makefile编写要使用tab

2.注意ifneq后有空格

3. 内核中无法使用printf

4.注意makefile中obj-m后面.o文件名和.c一致 5.前面的if和后面的endif配对

6.__init __exit 后面的函数内参数要写上void

7.KDIR指向内核位置/lib/modules/内核名称/build是链接指向了/usr/src/内核名文件下

8.在ubuntu系统中设置了printk的级别也需要在dmesg中查看

实验内容二:

编写一个包含2.c文件的内核模块程序,进行编译,掌握多文件模块编译的方法及Makefile书写规则!

编写两个.c文件

hello1.c

#include

#include

MODULE_LICENSE("GPL");

MODULE_AUTHOR("jiang shuliang");

MODULE_DESCRIPTION("Hello World Module");

static int __init hello_init(void)

{

printk(KERN_EMERG"Hello World1!\n");

return 0;

}

static void __exit hello_exit(void)

{

printk("<6>hello exit1!\n");

printk(KERN_EMERG"good bye!\n");

}

hello2.c

#include

#include

MODULE_LICENSE("GPL");

MODULE_AUTHOR("jiang shuliang");

MODULE_DESCRIPTION("Hello World Module");

static int __init hello_init(void)

{

printk(KERN_EMERG"Hello World2!\n");

return 0;

}

static void __exit hello_exit(void)

{

printk("<6>hello exit2!\n");

printk(KERN_EMERG"good bye!\n");

}

编写Makefile

ifneq ($(KERNELRELEASE),)

obj-m := hello1.o hello2.o

else

KDIR := /lib/modules/$(shell uname -r)/build #改地址

all:

make -C $(KDIR) M=$(PWD) modules #注意tab

clean:

rm -f *.ko *.o *.mod.o *.mod.c *.symvers

endif

3.生成两个.ok文件同上个实验加载模块查看卸载即可

实验内容三:

一. 原理

module_param

1.为什么引入

在用户态下编程可以通过main()来传递命令行参数,而编写一个内核模块则可通过module_param()来传递命令行参数.

2. module_param宏是Linux 2.6内核中新增的,该宏被定义在include/linux/moduleparam.h文件中,具体定义如下:

/* Helper functions: type is byte, short, ushort, int, uint, long,

ulong, charp, bool or invbool, or XXX if you define param_get_XXX,

param_set_XXX and param_check_XXX.

*/ #define module_param_named(name, value, type, perm)

param_check_##type(name, &(value));

module_param_call(name, param_set_##type, param_get_##type, &value, perm);

__MODULE_PARM_TYPE(name, #type)

#define module_param(name, type, perm)

module_param_named(name, name, type, perm)

由此可知 module_param的实现是通过module_param_named(name, name, type, perm)的。

3.module_param使用了3个参数:变量名,它的类型,以及一个权限掩码用来做一个辅助的sysfs入口。

这个宏定义应当放在任何函数之外,典型地是出现在源文件的前面。

eg: static char *whom=“world”

static int tige=1;

module_param(tiger,int,S_IRUGO);

module_param(whom,charp,S_IRUGO);

4.模块参数支持许多类型:

bool

invbool

一个布尔型( true 或者 false)值(相关的变量应当是 int 类型). invbool 类型颠倒了值, 所以真值变成 false, 反之亦然.

charp :一个字符指针值. 内存为用户提供的字串分配, 指针因此设置.

int

long

short

uint

ulong

ushort

基本的变长整型值. 以 u 开头的是无符号值.

5.数组参数, 用逗号间隔的列表提供的值, 模块加载者也支持。

声明一个数组参数, 使用:

module_param_array(name,type,num,perm);

这里 name 是你的数组的名子(也是参数名),

type 是数组元素的类型,

num 是一个整型变量,

perm 是通常的权限值.

如果数组参数在加载时设置, num 被设置成提供的数的个数. 模块加载者拒绝比数组能放下的多的值.

Tiger-John说明:

perm参数的作用是什么?

最后的 module_param 字段是一个权限值,表示此参数在sysfs文件系统中所对应的文件节点的属性。你应当使用 中定义的值. 这个值控制谁可以存取这些模块参数在 sysfs 中的表示.当perm为0时,表示此参数不存在 sysfs文件系统下对应的文件节点。 否则, 模块被加载后,在/sys/module/ 目录下将出现以此模块名命名的目录, 带有给定的权限.。

权限在include/linux/stat.h中有定义

比如:

#define S_IRWXU 00700

#define S_IRUSR 00400

#define S_IWUSR 00200

#define S_IXUSR 00100

#define S_IRWXG 00070

#define S_IRGRP 00040

#define S_IWGRP 00020

#define S_IXGRP 00010

#define S_IRWXO 00007

#define S_IROTH 00004

#define S_IWOTH 00002

#define S_IXOTH 00001

使用 S_IRUGO 参数可以被所有人读取, 但是不能改变; S_IRUGO|S_IWUSR 允许 root 来改变参数. 注意, 如果一个参数被 sysfs 修改, 你的模块看到的参数值也改变了, 但是你的模块没有任何其他的通知. 你应当不要使模块参数可写, 除非你准备好检测这个改变并且因而作出反应.

二.实例:

说了这么多,看一个程序体验以下:

file name : module_param.c

#include

#include

#include

MODULE_LICENSE("GPL");

static char *who;

static int times;

module_param(who,charp,0644);

module_param(times,int,0644);

static int __init hello_init(void)

{

int i;

for(i = 1;i <= times;i++)

printk("%d %s!\n",i,who);

return 0;

}

static void __exit hello_exit(void)

{

printk("Goodbye,%s!\n",who);

}

module_init(hello_init);

module_exit(hello_exit);

2.编写Makefile文件

obj-m:=module_param.o

CURRENT_PATH:=$(shell pwd)

VERSION_NUM :=$(shell uname -r)

LINUX_PATH :=/usr/src/linux-headers-$(VERSION_NUM)

all :

make -C $(LINUX_PATH) M=$(CURRENT_PATH) modules

clean :

make -C $(LINUX_PATH) M=$(CURRENT_PATH) clean

3.在终端输入:make

4 .加载模块: sudo insmod module_param.ko who=tiger times=4

5.dmesg :查看结果。

在写完了.c文件和Makfile之后过程实例步骤:

a. 在终端输入:make

think@Ubuntu:~/module_param$ make

make -C /usr/src/linux-headers-2.6.32-25-generic M=/home/think/module_param modules

make[1]: 正在进入目录 `/usr/src/linux-headers-2.6.32-25-generic'

Building modules, stage 2.

MODPOST 1 modules

make[1]:正在离开目录 `/usr/src/linux-headers-2.6.32-25-generic'

think@ubuntu:~/module_param$

b.在终端输入:

sudo insmod module_param.ko who=tiger times=4

think@ubuntu:~/module_param$ sudo insmod module_param.ko who=tiger times=4

c 在终端输入:dmesg

[ 4297.711137] 1 tiger!

[ 4297.711139] 2 tiger!

[ 4297.711140] 3 tiger!

[ 4297.711141] 4 tiger!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
好的,以下是一个简单Linux内核中断程序和Makefile文件的示例: 中断程序代码(文件名为int_handler.c): ```c #include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/interrupt.h> MODULE_LICENSE("GPL"); // 定义中断号 #define IRQ_NUM 1 // 中断处理函数 static irqreturn_t int_handler(int irq, void *dev_id) { printk(KERN_INFO "Interrupt %d occurred\n", irq); return IRQ_HANDLED; } // 模块加载函数 static int __init int_handler_init(void) { int ret; // 注册中断处理函数 ret = request_irq(IRQ_NUM, int_handler, IRQF_SHARED, "int_handler", (void *)int_handler); if (ret) { printk(KERN_ERR "Failed to register interrupt handler\n"); return ret; } printk(KERN_INFO "Interrupt handler registered\n"); return 0; } // 模块卸载函数 static void __exit int_handler_exit(void) { // 释放中断处理函数 free_irq(IRQ_NUM, (void *)int_handler); printk(KERN_INFO "Interrupt handler unregistered\n"); } module_init(int_handler_init); module_exit(int_handler_exit); ``` Makefile文件代码: ```makefile # 指定目标文件名 obj-m := int_handler.o # 指定内核源码目录 KERNELDIR ?= /lib/modules/$(shell uname -r)/build # 当前目录 PWD := $(shell pwd) # 编译规则 default: $(MAKE) -C $(KERNELDIR) M=$(PWD) modules # 清除规则 clean: $(MAKE) -C $(KERNELDIR) M=$(PWD) clean ``` 使用方法: 1. 将以上代码保存为两个文件(int_handler.c和Makefile)并放在同一目录下。 2. 打开终端,进入该目录。 3. 执行`make`命令编译模块。 4. 执行`sudo insmod int_handler.ko`命令加载模块。 5. 执行`cat /proc/interrupts`命令查看中断计数器是否增加。 6. 执行`sudo rmmod int_handler`命令卸载模块

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值