首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Linux内核驱动开发的EXPORT_SYMBOL

Linux内核驱动开发的EXPORT_SYMBOL

作者头像
Rice加饭
发布2022-05-10 18:20:34
发布2022-05-10 18:20:34
3.8K0
举报
文章被收录于专栏:Rice嵌入式Rice嵌入式

前言

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

简介

  • 本文主要来讲讲Linux内核驱动中,EXPORT_SYMBOL()宏定义的用法。
  • 在阅读的Linux内核驱动源码的时候,我们会发现很多的函数带有EXPORT_SYMBOL()宏定义。
  • 从这个宏定义的理解为输出符号。那么他究竟有什么作用。

EXPORT_SYMBOL()宏定义作用

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

使用方法

  1. 在模块函数定义之后使用"EXPORT_SYMBOL(函数名)"来导出。
代码语言:javascript
复制
static int rice_func(void)
{
    return 0;
}
EXPORT_SYMBOL(rice_func);
  1. 在调用该函数的另外一个模块中使用extern对之声明。
代码语言:javascript
复制
extern int rice_func(void);
  1. 先加载定义该函数的模块,然后再加载调用该函数的模块,先后顺序必须注意。

实验

编写代码

  • 编写两个模块:rice_export.ko 和 rice_import.ko,其中:
    • rice_export.ko:导出定义的函数
    • rice_import.ko:调用导出的函数
导出函数模块的代码(rice_export.c)
  • 导出函数为:rice_drv_export,函数含义:外部输入一个字符串,然后打印出来
代码语言:javascript
复制
#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);,含义:声明外部函数
代码语言:javascript
复制
#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
  • 运行结果:
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-20,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 前言
  • 简介
  • EXPORT_SYMBOL()宏定义作用
  • 使用方法
  • 实验
    • 编写代码
    • 编译运行
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档