linux内核模块怎么调用

linux内核模块怎么调用,第1张

在编写linux内核模块的时候,有时候我们需要调用一只内核模块里面的函数,然而如果是在不同目录下面编译生成的内核模块,此时A模块去调用B模块的函数时候会出现函数未定义,无法调用的情况。那么以前我是在同一个目录下面,先后写两个makefile,然后编译生成两个不同的内核模块,这种方式可以正常实现A模块调用B模块里面的函数,不过非常麻烦。本博文将会针对这种情况提出一种可以同时生成多个内核模块,不要再次编译的方面,下面贴出源码:

内核模块cal.ko:

#include <linux/module.h>

#include <linux/init.h>

MODULE_LICENSE("GPL")

int add(int a, int b) {

return a+b

}

int sub(int a, int b) {

return a-b

}

static int sym_init() {

return 0

}

static int sym_exit() {

return 0

}

module_init(sym_init)

module_exit(sym_exit)

EXPORT_SYMBOL(add)

EXPORT_SYMBOL(sub)

内核模块hello.ko

#include <linux/module.h>

#include <linux/init.h>

MODULE_LICENSE("GPL")

MODULE_AUTHOR("David Xie")

MODULE_DESCRIPTION("Hello World Module")

MODULE_ALIAS("a simplest module")

static int age = 10

module_param(age, int, S_IRUGO)//allow all user to use this param

int add(int a, int b)

int sub(int a, int b)

static int hello_init(void)

{

printk("<0>"" Hello World! age = %d\n", add(10, 20))//调用内核模块cal.ko里面的add函数

return 0

}

static void hello_exit(void)

{

printk("<0>""hello exit %d\n", sub(30,10))//调用内核模块cal.ko里面的sub函数

}

module_init(hello_init)

module_exit(hello_exit)

可以生成多个内核模块的makefile

ifneq ($(KERNELRELEASE),)

obj-m := cal.o hello.o

cal-objs := operator.o

hello-objs := main.o

else

KDIR := /lib/modules/2.6.32-21-generic/build

all:

make -C $(KDIR) M=$(PWD) modules

clean:

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

endif

此时在当前目录执行make就会产生cal.ko和hello.ko两个内核模块

用JNI实现实例:创建HelloWorld.javaclass HelloWorld{private native void print()public staticvoid main(String[] args){new HelloWorld().print()}static{System.loadLibrary("HelloWorld")}}注意print方法的声明,关键字native表明该方法是一个原生代码实现的。另外注意static代码段的System.loadLibrary调用,这段代码表示在程序加载的时候,自动加载libHelloWorld.so库。编译HelloWorld.java在命令行中运行如下命令:javac HelloWorld.java在当前文件夹编译生成HelloWorld.class。生成HelloWorld.h在命令行中运行如下命令:javah -jni HelloWorld在当前文件夹中会生成HelloWorld.h。打开HelloWorld.h将会发现如下代码:/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class HelloWorld */#ifndef _Included_HelloWorld#define _Included_HelloWorld#ifdef __cplusplusextern "C" {#endif/* * Class: HelloWorld * Method:print * Signature: ()V */JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *, jobject)#ifdef __cplusplus}#endif#endif该文件中包含了一个函数Java_HelloWorld_print的声明。这里面包含两个参数,非常重要,后面讲实现的时候会讲到。实现HelloWorld.c创建HelloWorld.c文件输入如下的代码:#include <jni.h>#include <stdio.h>#include "HelloWorld.h"JNIEXPORT void JNICALLJava_HelloWorld_print(JNIEnv *env, jobject obj){printf("Hello World!\n")}注意必须要包含jni.h头文件,该文件中定义了JNI用到的各种类型,宏定义等。另外需要注意Java_HelloWorld_print的两个参数,本例比较简单,不需要用到这两个参数。但是这两个参数在JNI中非常重要。env代表java虚拟机环境,Java传过来的参数和c有很大的不同,需要调用JVM提供的接口来转换成C类型的,就是通过调用env方法来完成转换的。obj代表调用的对象,相当于c++的this。当c函数需要改变调用对象成员变量时,可以通过 *** 作这个对象来完成。编译生成libHelloWorld.so在Linux下执行如下命令来完成编译工作:cc -I/usr/lib/jvm/java-6-sun/include/linux/-I/usr/lib/jvm/java-6-sun/include/-fPIC -shared -o libHelloWorld.so HelloWorld.c在当前目录生成libHelloWorld.so。注意一定需要包含Java的include目录(请根据自己系统环境设定),因为Helloworld.c中包含了jni.h。另外一个值得注意的是在HelloWorld.java中我们LoadLibrary方法加载的是“HelloWorld”,可我们生成的Library却是libHelloWorld。这是Linux的链接规定的,一个库的必须要是:lib+库名+.so。链接的时候只需要提供库名就可以了。运行Java程序HelloWorld大功告成最后一步,验证前面的成果的时刻到了:java HelloWorld如果你这步发生问题,如果这步你收到java.lang.UnsatisfiedLinkError异常,可以通过如下方式指明共享库的路径:java -Djava.library.path='.' HelloWorld当然还有其他的方式可以指明路径请参考《在Linux平台下使用JNI》。我们可以看到久违的“Hello world!”输出了。

C语言源程序文件名的后缀是.c。C源程序经过C编译程序编译之后生成一个后缀为.OBJ的二进制文件,

然后由称为“连接程序”的软件,把此.OBJ文件与C语言提供的各种库函数连接起来生成一个后缀为.EXE的可执行文件。

由高级语言编写的程序称为“源程序”,把由二进制代码表示的程序称为“目标程序”。为了把源程序转换成机器能接受的目标程序,这时我们需要具有翻译功能的软件--“编译程序”。每种高级语言都有与它对应的编译程序。

扩展资料

1、目标文件的扩展名为“.obj”(Windows)或“.o”(Linux)。目标文件已经是机器指令,但还不能运行,因为目标文件还没有解决函数调用问题。

2、可执行文件的扩展名为“.exe“。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/7207602.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-02
下一篇 2023-04-02

发表评论

登录后才能评论

评论列表(0条)

保存