so库的static 变量深入了解

Linux下NDK编译so库 环境配置 1、NDK下载。地址:https://developer.android.google.cn/ndk/downloads/ 2、随便在哪个目录直接解压 3、配置系统环境变量 #vim /etc/profile 在文件末尾添加如下内容: export ANDROID_NDK=“ndk路径” export PATH=“ANDROIDNDK:ANDROID_NDK:ANDROIDN​DK:PA... 阅读详情

理解 so 的机制

    进程内存空间分成代码段(code),数据段(data),堆(heap),  栈(stack), 考虑加载 .so,进程空间应该不只一份 code 和 data segment)

    static 变量保存可执行文件或 so 的数据段(data segement) 中,并且有初始值

     编译程序在在 link 的时候,为 static 分配地址到数据段,当so被 load 的时候,应该是直接把so 用物理内存映射的放到load进程地址空间,用户可以直接读取 static 变量;但当用户改写此 static 变量的时候,操作系统会重新分配物理内存并映射,原来 static 变量使用的进程地址并不改变, 这就是 copy on write, 看下面的摘要:

Shared libraries are loaded into a process by memory-mapping the file into some portion of the process's address-space. When multiple processes load the same library, the OS simply lets them share the same physical RAM.

Portions of the library that can be modified, such as static globals, are generally loaded in copy-on-write mode, so that when a write is attempted, a page fault occurs, the kernel responds by copying the affected page to another physical page of RAM (for that process only), the mapping redirected to the new page, and then finally the write operation completes.

To answer your specific points:

  1. All processes have their own address space. The sharing of physical memory between processes is invisible to each process (unless they do so deliberately via a shared memory API).
  2. All data and code live in physical RAM, which is a kind of address-space. Most of the addresses you are likely see, however, are virtual memory addresses belonging to the address-space of one process or another, even if that "process" is the kernel.

     当用 gcc 编译时,  可以看见可执行文件中有此 static 变量的 symbol ( 详见本文最后),  当运行load 动态库时 resolve 此 symbol

初始化

如果定义一个结构,就必须有初始化代码


class A {
  public:
   static int m;
   int m2;

};

初始化代码写在 .cpp 中

int A:m=1;


否则就会报错

3.cpp:(.text+0x6): undefined reference to `A::m'
collect2: ld returned 1 exit status

看这个错的意思是如果不初始化,编译器连地址空间都不分配了


两个so都初始化static变量会如何?

构造下面几个文件

--- def.h ----- 
class A {
  public:
   static int m;
   int m2;

};

--- 1.cpp ----- 
#include 
int A::m =1


--- 2.cpp ----- 
#include 
int A::m =2


--- 3.cpp ----- 
#include 
#include 
int main()
printf("%d\n";,A::m);
}

用下面的命令,把 1.cpp 2.cpp 编译为动态库

g++ --shared -fPIC 1.cpp -o lib1.so

g++ --shared -fPIC 2.cpp -o lib2.so


当首先 link lib1.so 时,使用 lib1.so 对变量的初始化
$g++ 3.cpp -L . -l1 -l2
$ ./a.out 
输出 1


当首先 link lib2.so 时,使用 lib2.so 对变量的初始化

$ g++ 3.cpp -L . -l2 -l1
$ ./a.out 
输出  2

可见 static 只认第一次初始化


另: 可以用下面命令查看, static 是全局的 symbol

$readelf -s a.out

...

51: 0000000000601028     4 OBJECT  GLOBAL DEFAULT   26 _ZN1A1mE

...

注: name mangling 的解释

_Z( 开始标志  )  N ( nested) 1( A长度) A (class A) 1 ( m 的长度) m (static int m) E ( 结束标志)

Android源码集成第三方jar和so库 Android源码中MyAPIs放在packages/apps下。MyAPIs下创建目录libs以及libs/armeabi,并把MyJar.jar放在libs/,把libMyLib.so放在libs/armeabi。 LOCAL_PREBUILT_STATIC_JAVA_LIBRARIES:=libMyJar:libs/MyJar.jar LOCAL_PREBUILT_LIBS:=libMyL... 阅读详情

相关推荐

JNI挂接第三方so库

JNI挂接第三方so库(androidstudio) 最近在做一个项目,需要挂接其它部门提供的so库,android纯小白,在网上找了一堆资料,走了很多弯路终于初步挂接成功,整个流程给大家分享一下 基本工具 androidstudio,google官方提供的开发工具,迭代了很多版本了,确实有很多弊端,但是开发用起来的确顺手许多。 基本基础 由于挂接的so库是c++编译的,需要c++基础,JNI的基...

qq_28666281的博客 2033

动态库中的全局变量与静态变量

之前在linux下做过一个测试:写一个so,该so中有一个全局变量。so中的代码在运行时会修改该全局变量的值。然后,有多个程序都需要该so,而且这些应用程序都启动了。此时,很显然so只被加载了一份,那么,当这么多程序在运行调用该so时,该so中的全局变量的值会被覆盖来覆盖去么?答案是不会。这是测试的答案。现在知道原理了,尽管这是windows via C/C++中解释的windows的做法,但是我想linux也是这么类似处理的。windows 使用memory map来加载exe和dll。当一个exe/dl

木牛的博客 3433

Android so库开发——Android Studio调用so库(二)

在中已经创建了自己的so库,这是一个JNI规范的so库,可以直接将so库放到libs中,并按照上面文章中MainActivity中的调用方法使用。1、build.gradle(app)配置2、加载so库中方法在Sudio中方法名虽然显示红色,但不影响使用。3、Activity中调用方法。

小旭的专栏 8027

Linux动态库(.so)链接探究同一个动态库被间接链接多次时类内静态变量使用问题(附带c++源码解释)

  介绍一种场景,有一个抽象基类生成了一个动态库,记为libcompo.so,继承该基类的具体实现有两个组件,也各自生成了动态库libcompo1.so和libcompo2.so,由于使用到了基类,因此这两个库也是会分别链接基类库的,也就是libcompo.so,然后在可执行文件里,我们为了软件各个组件之间的解耦通过反射技术注册的方式动态加载具体组件,因此可执行文件只用到了该抽象基类的指针,只需要在编译时链接libcompo.so即可,在运行时通过dlopen()加载生成的动态库即可完成工作。   最终软件

weixin_45878768的博客 2154

【测试代码】Linux共享库(动态库)与进程之间全局变量是无法共享

测试代码:Linux共享库(动态库)与进程之间全局变量是无法共享

鸿蒙OS开机动画背后的秘密:从代码到视觉的完整解析(附源码分析)

本文深入解析了鸿蒙OS开机动画的系统级实现原理。从bootanimation服务的启动配置、与Render Service的协同,到基于VSync信号的帧率同步与绘制流水线,结合OpenHarmony源码进行了逐行解读。文章揭示了其事件驱动的优雅退出机制,并探讨了视频支持、多屏适配等高级特性与定制化可能,为开发者理解鸿蒙图形子系统提供了硬核技术视角。

sony5的博客 969

C++中的static变量

虽然是老生常谈,但下面这篇文章还是概括地很全面的。 C++中的static有以下三种不同的效果: 当用于成员变量时,表示它将由类分配管理而不是实例。 当在一个函数中时,数据将会被静态分配,在函数第一次被调用时初始化,且一直存在到程序退出。它当然也仅在当前函数中可用。这个特性经常被用于单例的延迟建构。  当在一个编译单元中(如源文件),它可以在本单元中视为全局的,但对

求索 2069

保姆级教程:用AI辅助反编译Python3.9+的EXE文件(兼容新版pycdc工具)

本文详细介绍了如何利用AI技术辅助反编译Python 3.9+的EXE文件,解决传统工具如uncompyle6无法处理新版字节码的问题。通过pycdc工具和AI大模型的结合,开发者可以高效还原代码逻辑,并提供了从EXE解包到字节码解析的完整流程,适用于逆向工程和代码分析场景。

hill8的博客 1223

关于C++静态成员变量

C++静态成员变量是用static修饰的成员变量,不属于对象的一部分,而是类测一部分,因此可以在没有实例化任何对象的时候使用静态成员变量。但是必须初始化它。         由于静态变量只能被初始化一次,所以初始化成员变量不要放在如下地方:1.类的构造函数(构造函数可能多次被调用);2.头文件中(头文件可能被包含入多个地方,也可能被执行多次)。应该放在应用程序中,类以外的任何地方初始化,例如:在

HappyJandun's 学习笔录 766

Android16 自定义HAL层适配一些VINTF和SELINUX问题修改

在RK里面一般权限矩阵在/rockchip/common/manifests/目录,我这版Android16的代码比较特殊,这里重点修改/device/rockchip/rockchip_generic/manifests/frameworks_compatibility_matrix.xml这个文件,不同的版本注册方式不同,在。hal_ruip_default.te,hal_ruip.te,attributes文件。拓展策略的方式添加,但是在Android16里面发现用不了。发现HAL层服务注册成功了。

tzj1058756809的博客 242

OpenClaw对接本地大模型:Llama3/Qwen/ChatGLM全适配,完全私有化部署

OpenClaw对接本地大模型,是企业级AI智能体落地的必经之路——它不仅解决了数据隐私和合规问题,还能大幅降低成本、提升响应速度、实现定制化。这篇文章我给大家完整拆解了两套部署方案:Ollama(新手首选,5分钟搞定)和vLLM(生产环境首选,高性能),覆盖了Llama3/Qwen/ChatGLM三大主流模型,还有真实的落地案例、高级优化、踩坑避坑指南,看完你就能零代码完成完全私有化的部署。从零开发自定义工具,给OpenClaw添加专属业务能力;

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 807

动态库基本原理和使用方法,-fPIC选项的来龙去脉

使用gcc生成so文件时,一般要加一个-fPIC选项,这个选项是啥意思?本文介绍了PIC的来龙去脉,值得一读...

... 1万+

ClawManager实战:OpenClaw批量部署+精细化权限管控,运维效率拉满90%

ClawManager彻底解决了OpenClaw规模化部署的运维痛点,它不是简单的“批量部署工具”,而是一套完整的企业级管理方案——从模板配置、批量部署,到权限管控、监控审计、AI治理,覆盖OpenClaw全生命周期管理,让OpenClaw从“个人工具”升级为“企业级AI基础设施”。对于中小企业,Docker一键部署即可快速落地,无需复杂配置;对于大型企业,K8s部署支持高可用、横向扩展,结合Keycloak对接企业现有认证系统,可完美融入企业IT架构。

2601_94871597的博客 607

Android NDK 集成调用第三方SO库(标准SO库和非标准SO库)

想要进阶高级Android开发工程师,NDK开发是必须要掌握的技能之一,本文以集成第三方SO库为开端,带大家入门NDK开发,主要包含一下内容:1、NDK工程创建;2、编写和打包Android标准SO库;3、集成Android标准SO库;4、集成Android非标准SO库。

sziitjin的博客 2733

YOLOv8架构革命:通过EfficientViT融合实现精度-速度的帕累托突破

目标检测领域长期存在精度与速度的权衡难题。视觉Transformer(ViT)的引入解决了长距离依赖问题,但其巨大的计算复杂度制约了实时应用。最新研究表明,将轻量级ViT与YOLO架构融合,可在几乎不损失推理速度的前提下,将mAP提升3-8个百分点。这种架构改进方案已在工业检测、自动驾驶、安防监控等多个领域得到验证,在保持实时性的同时显著提升了复杂场景下的检测可靠性。通过模块化设计,可以灵活适配不同规模的YOLOv8模型,为实际应用提供精度-速度的帕累托最优解。

FJN110的博客 148

LPDDR5 学习笔记08:电气参数设计要求

本文详细阐述了LPDDR5内存接口的关键电气规范和时序要求。主要内容包括:1)绝对最大额定值限制及长期工作可靠性说明;2)差分时钟信号(CK/WCK)的输入电压、转换速率和交叉点电压规范;3)单端时钟信号的定义和测量方法;4)时钟周期、抖动(周期抖动、相邻周期抖动)和累积误差的精确计算方法;5)片选信号在同步/异步模式下的接收器规范;6)命令地址信号和数据信号的接收器掩模定义及脉冲宽度要求。所有参数均严格定义了测量条件和合规标准,为LPDDR5接口设计提供了完整的电气规范参考。

一只豌豆象的博客 1173

Android HAL层添加三方so库

编译mk文件撰写 1.1 预编译so到手机目录下 每个算法SDK包里面都包含了inc、lib目录,也就是算法要使用到的头文件,库文件。头文件用于对外提供函数名和一些基本的需要的定义值,库文件就是算法公司封装好的代码逻辑了。 大家应该都知道,在mk文件里面每个模块(so,a,lib等)都会定义一个变量名LOCAL_MODULE,编译系统通过该变量名获取A模块的名称,然后就可以在B模块引用A模块...

qq_25672123的博客 3073

【STM32系统及仿真】基于STM32+蓝牙设计的智能窗帘系统__资料编号8

本项目设计并实现了一种基于STM32单片机的智能窗帘系统,集成了光敏传感器、温湿度传感器、蓝牙模块和OLED显示屏,实现了窗帘的自动调节、环境监测和远程控制功能。系统采用STM32F103C8T6作为主控制器,通过光敏传感器检测环境光强,温湿度传感器监测室内环境,蓝牙模块实现与手机APP的通信,用户可以通过APP远程控制窗帘的开合状态。系统在检测到环境光照强度或温度超出设定范围时,可自动调节窗帘的开合,以达到节能和提高舒适度的目的。

嵌入式阿齐Archie 2万+

Android NDK下STD库share static方式加载 (so库混乱调用问题)

结论 -DANDROID_STL=c++_shared 有该选项 share方式加载,打包的so库不含有STD代码 没该选项 static方式加载。 // 打so库的build.gradle android { compileSdkVersion rootProject.android.compileSdkVersion defaultConfig { externalNativeBuild { cmake {

zhjali123的专栏 5663

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Android.mk中配置so库

Android.mk中配置so库 在系统源码开发环境下,往往需要单编某个模块来debug,会涉及到打包so的问题。 第三方so库打包到apk 1、如何判断so库文件是32 bit/64 bit? 2、 如何将so库打包到apk ? 如何判断第三方库文件是32 bit/64 bit? 需要使用Linux 命令: file xxx.so。可以看到的xxx.so的格式 如何将so库打包到apk ? 需...

lijiaren_092008的专栏 5979

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

android 关于mk如何引用其它so库

通常,开发android的软件,常常需要编译so库,然编译的这个so库,需要调用多个其它的so库。这里主要记录一下,编译so库时,调用其它so库的mk,是怎么写的。 这里讲的示例:需要编译出libtest3.so,它需要调用libtest1.so,libtest2.so 1. 在android 源码下编译 LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE_TAGS := eng LOCAL_SRC_F...

jacke121的专栏 6314

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

android.mk 编译so库,android 关于mk如何引用其它so库

Android.mk#jni/Android.mkLOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := android-ffmpegLOCAL_SRC_FILES :=c ffmpeg-build/$(TARGET_ARCH_ABI)/libffmpeg.soLOCAL_EXPORT_C_INCLUDES := ffmpeg...

weixin_29688227的博客 1536

android studio调用c++ so库

要生成的jni so库的名称为libtestwebrtc.so,依赖静态库libpclient.a与libwebrtc.a,主要用来进行接口测试。3.在build.gradle中添加ndk的目录与cmakelists.txt的目录,定义只编译arm64-v8a以及设置apk打包库的目录。1.实现test.cpp,test.cpp中包含对c++ so库要使用方法的jni定义,比如。#include "webrtctest.h" // 包含需要调用的头文件。# 链接静态库到你的本地库。

qq_17411797的博客 985

Android 系统源码项目加载预编好的so库

Android 系统开发中会源代码有加载so库的情况,本文进行简单介绍。Android Studio 项目加载so库,已经有介绍过:Android Studio加载so和使用so还是比较方便的,环境OK的情况,几分钟就可以完成验证测试了。但是如果要在系统源代码Java里面加载和使用so就比较麻烦了,主要通过Android.mk或者Android.bp编译加载so,反正网上的代码写的mk/bp基本都是不行的。本来以为只是介绍一下编译使用的Android.mk或者Android.bp就可以了,

wenzhi的博客 2630

android 如何引用so,android 关于mk如何引用其它so库

Android.mk#jni/Android.mkLOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := android-ffmpegLOCAL_SRC_FILES :=c ffmpeg-build/$(TARGET_ARCH_ABI)/libffmpeg.soLOCAL_EXPORT_C_INCLUDES := ffmpeg...

weixin_39597318的博客 539

HarmonyOS NEXT开发:C代码打包so库,napi调用函数及回调

适用流程:已有一些C代码,不想把源码添加到HarmonyOS工程中,想要把已有的C代码编译成HarmonyOS平台可以使用的so库,在DevEco Studio工程的cpp模块加载so库并调用里面的函数,最终使用ArkTS/TS调用该函数(获取回调)。C源码可以添加到HarmonyOS工程的,可以省略手动编译过程。

weixin_46019555的博客 2955
上一篇: 调查支付宝 余额宝 天弘基金
下一篇: 了解网络视频H.264的播放
span76
博客等级 码龄18年 117粉丝 174原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值