RK3568平台 EXPORT_SYMBOL的作用

一、EXPORT_SYMBOL 的作用

1.在一个模块中使用 EXPORT_SYMBOL(name)。name 表示函数或者变量等符号,它是对全部内核代码公开的,因此在您的内核模块中可以直接调用 name,即使用 EXPORT_SYMBOL 可以将一个函数以符号的方式导出给其他模块使用。

2.EXPORT_SYMBOL 的符号,是把这些符号和对应的地址保存起来,在内核运行的过程中,可以找到这些符号对应的地址。而模块在加载过程中,其本质就是能动态连接到内核。

3.如果在模块中引用了内核或其它模块的符号,就要 EXPORT_SYMBOL 这些符号,这样才能找到对应的地址连接。

二.EXPORT_SYMBOL 和 EXPORT_SYMBOL_GPL 的区别

EXPORT_SYMBOL(name);
EXPORT_SYMBOL_GPL(name);
这两个宏均用于将给定的符号导出到模块外, _GPL版本的宏定义只能使符号对GPL许可的模块可用。

三、EXPORT_SYMBOL 和 EXPORT_SYMBOL_GPL 使用方法

EXPORT_SYMBOL 使用方法:

在模块函数定义之后使用 EXPORT_SYMBOL(函数名);

在调用该函数的模块中使用 extern 对它声明,才可以开始调用函数;

首先加载(insmod mod1.ko)定义该函数的模块,再加载(insmod mod2.ko)调用该函数的模块;
举例简要说明:

在模块(mod1)中使用 EXPORT_SYMBOL(func1);
在模块(mod2)中声明 extern int func1();
如此就可以在(mod2)中调用 func1 了。

例如,在一个驱动中 drivers/net/ethernet/stmmac/tnkhw.c 定义了函数 tnkhw_bonding_setcurr_active_slave,然后在另外的.c文件中可以直接extern来使用:

void tnkhw_bonding_setcurr_active_slave(int curr_slave)
{uint32_t data;unsigned long flags;spin_lock_irqsave(&tnkhw_reg_lock, flags);data = readl(tnkhw_ioaddr + TNK_REG_TOE_BONDING_CTRL);if (curr_slave) {TNKBD_DBG("%s curr_slave = eth1\n", __func__);writel((0x00000004 | data),tnkhw_ioaddr + TNK_REG_TOE_BONDING_CTRL);} else {TNKBD_DBG("%s curr_slave = eth0\n", __func__);writel((0xfffffffb & data),tnkhw_ioaddr + TNK_REG_TOE_BONDING_CTRL);}spin_unlock_irqrestore(&tnkhw_reg_lock, flags);
}
EXPORT_SYMBOL(tnkhw_bonding_setcurr_active_slave);

使用 extern 来声明:

extern void tnkhw_bonding_setcurr_active_slave(int curr_slave);void bond_select_active_slave(struct bonding *bond)
{struct slave *best_slave;int rv;best_slave = bond_find_best_slave(bond);if (best_slave != bond->curr_active_slave) {bond_change_active_slave(bond, best_slave);
#ifdef TNK_BONDINGif (hitoe && bond->curr_active_slave) {int slave_dev_id = 0;/* set bond current active slave */slave_dev_id =select_slave_dev(bond->curr_active_slave->dev);TNKB_DBG(" %s bond->curr_active_dev->name = %s\n",__func__, bond->curr_active_slave->dev->name);TNKB_DBG("slave_dev_id = %d\n", slave_dev_id);tnkhw_bonding_setcurr_active_slave(slave_dev_id);}
#endifrv = bond_set_carrier(bond);if (!rv)return;if (netif_carrier_ok(bond->dev)) {pr_info("%s: first active interface up!\n",bond->dev->name);} else {pr_info("%s: now running without any active interface !\n",bond->dev->name);}}
}

EXPORT_SYMBOL_GPL 使用方法:
EXPORT_SYMBOL_GPL 使用方法基本与 EXPORT_SYMBOL 相同,但是也有差异。
在模块函数定义之后使用 EXPORT_SYMBOL_GPL(函数名);

在调用该函数的模块中使用 extern 对它声明,然后必须使用 MODULE_LICENSE(“GPL”) 或者 MODULE_LICENSE(“Dual BSD/GPL”),才可以开始调用函数(这是因为 EXPORT_SYMBOL_GPL 主要是给有GPL认证的模块使用的);

首先加载(insmod mod1.ko)定义该函数的模块,再加载(insmod mod2.ko)调用该函数的模块;
举例简要说明:

在模块(mod1)中使用 EXPORT_SYMBOL_GPL (func1);
在模块(mod2)中先声明 extern int func1(),然后使用宏 MODULE_LICENSE(“GPL”) ;
如此就可以在(mod2)中调用 func1 了。

例如,在一个驱动中 drivers/usb/core/urb.c 定义了函数 usb_scuttle_anchored_urbs,然后在另外的.c文件中可以直接extern来使用:

void usb_scuttle_anchored_urbs(struct usb_anchor *anchor)
{struct urb *victim;unsigned long flags;spin_lock_irqsave(&anchor->lock, flags);while (!list_empty(&anchor->urb_list)) {victim = list_entry(anchor->urb_list.prev, struct urb,anchor_list);__usb_unanchor_urb(victim, anchor);}spin_unlock_irqrestore(&anchor->lock, flags);
}EXPORT_SYMBOL_GPL(usb_scuttle_anchored_urbs);

使用 extern 来声明:

extern void usb_scuttle_anchored_urbs(struct usb_anchor *anchor);MODULE_LICENSE("GPL");static void carl9170_usb_cancel_urbs(struct ar9170 *ar)
{int err;carl9170_set_state(ar, CARL9170_UNKNOWN_STATE);err = carl9170_usb_flush(ar);if (err)dev_err(&ar->udev->dev, "stuck tx urbs!\n");usb_poison_anchored_urbs(&ar->tx_anch);carl9170_usb_handle_tx_err(ar);usb_poison_anchored_urbs(&ar->rx_anch);tasklet_kill(&ar->usb_tasklet);usb_scuttle_anchored_urbs(&ar->rx_work);usb_scuttle_anchored_urbs(&ar->rx_pool);usb_scuttle_anchored_urbs(&ar->tx_cmd);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/710501.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MongoDB聚合运算符:$cond

文章目录 语法用法举例 $cond聚合运算符根据布尔表达式的结果返回两个表达式中的一个。 语法 { $cond: { if: <boolean-expression>, then: <true-case>, else: <false-case> } }或&#xff1a; { $cond: [ <boolean-expression>, <true-case>…

(案例贴2) html+css 倒计时器

欢迎大家使用这个计时器噢 老哥直接附代码咯. timer.html <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0">&l…

GitLab--Merge Request 权限管理

场景 团队在日常开发工作中需要进行分支管理&#xff0c;通常使用feature分支进行开发&#xff0c;然后依次合并到dev分支、release分支&#xff0c;整个代码合并过程不仅仅是代码合并还需要对代码进行审核&#xff0c;如果在线下进行审核合并&#xff0c;这样操作无法保留痕迹…

【力扣hot100】刷题笔记Day18

前言 晚上巩固一下今天的回溯题&#xff0c;基础不牢地动山摇&#xff0c;po一张代码随想录总结的 组合补充 77. 组合 - 力扣&#xff08;LeetCode&#xff09; class Solution:def combine(self, n: int, k: int) -> List[List[int]]:path []res []def backtrack(star…

go垃圾回收

1 go 垃圾回收变更 Go 语言的垃圾回收器&#xff08;GC&#xff09;自其诞生以来一直在不断演进和优化&#xff0c;以提高性能、减少暂停时间和对程序执行的影响。以下是一些关键的改进和变更点&#xff1a; 并发标记周期&#xff1a; Go 语言从一开始就采用了并发标记&#xf…

日立F-4700FL数据分析实验报告

实验设定 日立F-4700FL为荧光分光光度计,可输出三维光谱扫描结果到计算机。D和L为两种化合物。对4种不同的溶液进行三维光谱扫描,得到的光谱文件如下。 溶质光谱文件无K.txtDD.txtLL.txtD+LH.txt光谱文件(txt)的内容格式如下。 Sample: ... File name: ... Run date: ... …

[C#] 重难点区分[In]、[Out]、in、out、in T、out T

[In] 属性&#xff1a; - [In] 属性用于标识参数是一个输入参数。这意味着参数的值将被传递到方法或函数&#xff0c;但在其执行期间不会被修改。 - 当通过 P/Invoke 或 COM 互操作调用函数时&#xff0c;使用 [In] 属性指示参数的传递方式为输入。 - 示例&#xff1a…

深入探析:云计算与边缘计算在软件开发中的应用与挑战

随着互联网技术的飞速发展&#xff0c;云计算和边缘计算作为两种重要的计算模型&#xff0c;已经成为当今IT领域的热点话题。云计算通过将计算、存储、网络等资源集中在云端&#xff0c;为企业提供弹性、可靠、安全的计算服务。而边缘计算则是将部分计算任务从云端迁移到网络边…

BeautifulSoup解析 HTML标签Tag及属性attrs的常用方法

# 使用 BeautifulSoup 解析 HTML 内容 # BeautifulSoup 对象表示整个解析树或文档&#xff0c;可以用来遍历、搜索和操作文档。# 常用方法&#xff1a; # find(name, attrs, recursive, text, **kwargs)&#xff1a;在文档中查找第一个符合条件的元素&#xff0c;并返回该元素…

Java面试值之集合

集合 1.HashMap底层&#xff1f;扩容机制&#xff1f;1.7-1.8的升级&#xff1f;2.HashMap的长度为什么是2的幂次方&#xff1f;3.HashMap 插入1.7和1.8的区别&#xff1f;4.什么是红黑树&#xff1f;O(logn)5.HashMap为什么会使用红黑树&#xff1f;6.ArrayList底层&#xff1…

鸿蒙(HarmonyOS)项目方舟框架(ArkUI)之FlowItem容器组件

鸿蒙&#xff08;HarmonyOS&#xff09;项目方舟框架&#xff08;ArkUI&#xff09;之FlowItem容器组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、FlowItem组件 子组件 可以包含子组件。 接口 FlowItem() 使用该接口来…

免费音频剪辑

在数字时代&#xff0c;音频剪辑已成为许多职业和爱好者不可或缺的技能。无论是制作播客、教育视频、还是进行广告宣传&#xff0c;高质量的音频剪辑都能为作品增色不少。今天&#xff0c;我要为大家强烈安利一款免费且功能强大的音频剪辑工具&#xff0c;它绝对是你办公桌上不…

Kotti-基于Python的开源内容管理系统介绍与使用

前言 Kotti是一个基于Python的开源内容管理系统&#xff08;CMS&#xff09;&#xff0c;旨在为开发人员提供快速、简单和灵活的方式来构建Web应用。它基于Pyramid框架&#xff0c;使用SQLAlchemy进行数据库管理&#xff0c;支持自定义内容类型和可扩展的插件系统。本文将深入…

命令行启动mongodb服务器的问题及解决方案 -- Unrecognized option: storage.journal

目录 mongodb命令行启动问题 -- Unrecognized option: storage.journal问题日志&#xff1a;问题截图&#xff1a;问题来源&#xff1a;错误原因&#xff1a;解决方式&#xff1a; mongodb命令行启动问题 – Unrecognized option: storage.journal 同样是格式出问题的问题分析和…

《Spring Security 简易速速上手小册》第5章 高级认证技术(2024 最新版)

文章目录 5.1 OAuth2 和 OpenID Connect5.1.1 基础知识详解OAuth2OpenID Connect结合 OAuth2 和 OIDC 5.1.2 重点案例&#xff1a;使用 OAuth2 和 OpenID Connect 实现社交登录案例 Demo 5.1.3 拓展案例 1&#xff1a;访问受保护资源案例 Demo测试访问受保护资源 5.1.4 拓展案例…

MySQL锁机制【重点】

参考链接 【1】https://xiaolincoding.com/mysql/lock/mysql_lock.html 【2】https://learnku.com/articles/39212?order_byvote_count& 重要的锁&#xff1a; 表级锁&#xff08;Table-level locks&#xff09;&#xff1a; 表级锁是对整个表进行加锁&#xff0c;当一个事…

Blazor 向 ECharts 传递 option

目标 将ECharts封装为Blazor组件&#xff0c;然后通过jsRuntime向ECharts传递参数&#xff0c;即设置option。 封装ECharts 步骤&#xff1a; 1. 在index.html中引入echarts.min.js&#xff1b; 2. 创建blazor组件&#xff0c;将ref传递给js用于初始化echarts&#xff1b; …

#stm学习总结 (二十八)硬件随机数实验

28.1 随机数发生器简介 STM32F407 自带了硬件随机数发生器&#xff08;RNG&#xff09;&#xff0c;RNG 处理器是一个以连续模拟噪声为基础的随机数发生器&#xff0c;在主机读数时提供一个 32 位的随机数。 28.1.1 RNG 框图 STM32F407 的随机数发生器&#xff08;RNG&#x…

ffmpeg单张图片生成固定时长的视频

ffmpeg -r 25 -f image2 -loop 1 -i fps_1.jpg -vcodec libx264 -pix_fmt yuv420p -s 1080*1920 -r 25 -t 30 -y fps.mp4这个命令将 fps_1.jpg 图片转换为一个 30 秒长的视频&#xff0c;分辨率为 1920x1080&#xff0c;帧率为 25 帧/秒&#xff0c;并使用 libx264 编码器进行压…

LeetCode -- 79.单词搜索

1. 问题描述 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 单词必须按照字母顺序&#xff0c;通过相邻的单元格内的字母构成&#xff0c;其中“相邻”单元格是那些水…