Linux内核驱动开发的EXPORT_SYMBOL

前言

  • 很抱歉各位粉丝啊,博主好久没有更新原创文章,从今天起开始恢复写文章的时光。前段时间各种不顺利,到时心情低落。现在恢复状态了。

简介

  • 本文主要来讲讲Linux内核驱动中,EXPORT_SYMBOL()宏定义的用法。

  • 在阅读的Linux内核驱动源码的时候,我们会发现很多的函数带有EXPORT_SYMBOL()宏定义。

834fee0b7a9822f65259da2556d580fc.png
  • 从这个宏定义的理解为输出符号。那么他究竟有什么作用。

EXPORT_SYMBOL()宏定义作用

  • EXPORT_SYMBOL宏定义定义的函数或者符号将对内核代码公开,不用修改内核代码就在其他的内核模块中直接调用,即使用EXPORT_SYMBOL可以将一个函数以符号的方式导出给其他模块使用。

使用方法

  1. 在模块函数定义之后使用"EXPORT_SYMBOL(函数名)"来导出。

static int rice_func(void)
{
    return 0;
}
EXPORT_SYMBOL(rice_func);
  1. 在调用该函数的另外一个模块中使用extern对之声明。

extern int rice_func(void);
  1. 先加载定义该函数的模块,然后再加载调用该函数的模块,先后顺序必须注意。

实验

编写代码

  • 编写两个模块:rice_export.ko 和 rice_import.ko,其中:

    • rice_export.ko:导出定义的函数

    • rice_import.ko:调用导出的函数

导出函数模块的代码(rice_export.c)

  • 导出函数为:rice_drv_export,函数含义:外部输入一个字符串,然后打印出来

#include "rice_export.h"

#define CLASS_NAME  "rice_export"
#define DEVICE_NAME "rice_export"

typedef struct {
    int major_number;
    struct device *device;
    struct class *class;
} Rice_Driver;

Rice_Driver rice_drv;

static int rice_drv_export(char *name) {
    
    printk(KERN_ALERT "Rice Export: %s\n", name);
    return 0;
}
EXPORT_SYMBOL(rice_drv_export);

static int __init rice_export_init(void) {
    rice_drv.major_number = register_chrdev(0, DEVICE_NAME, NULL);

    if (rice_drv.major_number < 0) {
        printk(KERN_ALERT "Register fail!!\n");
        return rice_drv.major_number;
    }

    printk(KERN_ALERT "Registe success, major number is %d\n", rice_drv.major_number);

    rice_drv.class = class_create(THIS_MODULE, CLASS_NAME);

    if (IS_ERR(rice_drv.class)) {
        unregister_chrdev(rice_drv.major_number, DEVICE_NAME);
        return PTR_ERR(rice_drv.class);
    }

    rice_drv.device = device_create(rice_drv.class, NULL, MKDEV(rice_drv.major_number, 0), NULL, DEVICE_NAME);

    if (IS_ERR(rice_drv.device)) {
        class_destroy(rice_drv.class);
        unregister_chrdev(rice_drv.major_number, DEVICE_NAME);
        return PTR_ERR(rice_drv.device);
    }

    printk(KERN_ALERT "rice export ko init!!\n");

    return 0;
}

static void __exit rice_export_exit(void) {
    device_destroy(rice_drv.class, MKDEV(rice_drv.major_number, 0));
    class_unregister(rice_drv.class);
    class_destroy(rice_drv.class);
    unregister_chrdev(rice_drv.major_number, DEVICE_NAME);

    printk(KERN_ALERT "rice export ko exit!!\n");
}

module_init(rice_export_init);
module_exit(rice_export_exit);
MODULE_AUTHOR("RieChen");
MODULE_LICENSE("GPL");

电泳函数模块的代码(rice_import.c)

  • 调用函数声明:extern int rice_drv_export(char *name);,含义:声明外部函数

#include "rice_import.h"

#define CLASS_NAME  "rice_import"
#define DEVICE_NAME "rice_import"

typedef struct {
    int major_number;
    struct device *device;
    struct class *class;
} Rice_Driver;

Rice_Driver rice_drv;


extern int rice_drv_export(char *name);


static int __init rice_import_init(void) {
    rice_drv.major_number = register_chrdev(0, DEVICE_NAME, NULL);

    if (rice_drv.major_number < 0) {
        printk(KERN_ALERT "Register fail!!\n");
        return rice_drv.major_number;
    }

    printk(KERN_ALERT "Registe success, major number is %d\n", rice_drv.major_number);

    rice_drv.class = class_create(THIS_MODULE, CLASS_NAME);

    if (IS_ERR(rice_drv.class)) {
        unregister_chrdev(rice_drv.major_number, DEVICE_NAME);
        return PTR_ERR(rice_drv.class);
    }

    rice_drv.device = device_create(rice_drv.class, NULL, MKDEV(rice_drv.major_number, 0), NULL, DEVICE_NAME);

    if (IS_ERR(rice_drv.device)) {
        class_destroy(rice_drv.class);
        unregister_chrdev(rice_drv.major_number, DEVICE_NAME);
        return PTR_ERR(rice_drv.device);
    }

    printk(KERN_ALERT "rice import ko init!!\n");

    rice_drv_export("RiceChen");

    return 0;
}

static void __exit rice_import_exit(void) {
    device_destroy(rice_drv.class, MKDEV(rice_drv.major_number, 0));
    class_unregister(rice_drv.class);
    class_destroy(rice_drv.class);
    unregister_chrdev(rice_drv.major_number, DEVICE_NAME);

    printk(KERN_ALERT "rice import ko exit!!\n");
}

module_init(rice_import_init);
module_exit(rice_import_exit);
MODULE_AUTHOR("RieChen");
MODULE_LICENSE("GPL");

编译运行

  • 将两个模块编译完,push到板子,先加载导出模块--rice_export.ko,然后再加载调用模块--rice_import.ko

  • 运行结果:

ba8e22e042012cf9854fda9223c0db10.png


关注微信公众号『Rice嵌入式开发技术分享』,后台回复“微信”添加作者微信,备注”入群“,便可邀请进入技术交流群。

9a56c0a1f152a07db81a86a8ca5f3978.png
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rice嵌入式开发

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值