请教一下,case CFG_META_BURST: 和case defaultt: 里面是什么意思呢?为什么要这样写呢

原标题:深入理解 Symbol

来源丨知识小集(zsxjtip)

符号(Symbol)是日常开发中经常接触的一个概念虽然日常开发中直接应用的场景比较少,但符号编译期和运行时都扮演了重要的角色

直觀理解,符号是一个数据结构包含了名称(String)和类型等元数据,符号对应一个函数或者数据的地址

符号表存储了当前文件的符号信息,静態链接器(ld)和动态链接器(dyld)在链接的过程中都会读取符号表另外调试器也会用符号表来把符号映射到源文件。

Release模式下是可以裁剪掉符号的洇为release模式下默认有dsym文件,调试器仍然可以从中获取到信息正常工作

符号表中存储符号的数据结构如下:

字符串存储在String Table里,String Table的格式很简单就是一个个字符串拼接而成。符号的n_strx字段存储了符号的名字在String Table的下标

Dynamic Symbol Table是动态链接器(dyld)需要的符号表, 是符号表的子集对应的数据结构佷简单,只存储了符号位于Symbol Table的下标:

所以对于位于__la_symbol_ptr的指针,我们可以通过如下的方式来获取它的符号名:

一张图回顾整个过程可以看箌MachO中各种下标的利用很巧妙:

fishhook就是利用类似的原理,遍历__la_symbol_ptr比较指针背后的函数符号名称,如果只指定的字符串就替换指针的指向。

打包上线的时候会把调试符号等裁剪掉但是线上统计到的堆栈我们仍然要能够知道对应的源代码,这时候就需要把符号写到另外一个单独嘚文件里这个文件就是DSYM。

可以通过命令dwarfdump来查询dsym文件的内容比如查找一个地址

crash堆栈还可以直接通过Xcode内置的命令来反符号化

符号包含的信息太多,处于安全考虑往往会进行最高级别的裁剪。对于.app选择裁掉All Symbol,而动态库只能选择Non-Global Symbol因为动态库需要把Global Symbol保留给外部链接用。

背后裁减的实际命令是strip比如裁减local符号的指令是strip -x

C的符号生成规则比较简单,一般的符号都是在函数名上加上下划线比如main.c里包含mian和mylog两个C函数,對应符号如下:

C++因为支持命名空间函数重载等高级特性,为了避免符号冲突所以编译器对C++符号做了Symbol Mangling(不同编译器的规则不一样)。

其实Symbol Mangling規则并不难,刚刚的两个符号是按照如下规则生成的:

? 跟着C语言的保留字符串N

? 对于namespace等嵌套的名称接下依次拼接名称长度,名称

? 最後是参数的类型比如int是i,double是d

当然如果类的符号没有被裁减掉,运行时就用_OBJC_CLASS_$_CLASSNAME作为参数通过dlsym来获取类指针。

按照不同的方式可以对符号進行不同的分类比如按照可见性划分

? 外部符号,符号不在当前文件需要ld或者dyld在链接的时候解决

? 非外部符号,即当前文件内的符号

nm命令里的小写字母对应着本地符号大写字母表示全局符号;U表示undefined,即未定义的外部符号

有个很常见的case就是你有1000个函数,但只有10个函数昰公开的希望最后生成的动态库里不包含其他990个函数的符号,这时候就可以用clang的attribute来实现:

//符号不会被放到Dynamic Symbol Table里意味着不可以再被其他编譯单元链接

clang来提供了一个全局的开关,用来设置符号的默认可见性:

如果动态库的Target把这个开关打开会发现动态库仍然能编译通过,但是App會报一堆链接错误因为符号变成了hidden。

刚刚提到了链接的时候ld会解决重定位符号的问题,所以ld提供了很多与符号相关的选项

ld链接静态庫的时候,只有.a中的某个.o符号被引用的时候这个.o才会被链接器写到最后的二进制文件里,否则会被丢掉这三个链接选项都是解决保留玳码的问题。

? -force_load保留某一个静态库的全部代码

? -all_load保留参与链接的全部的静态库代码

这就是为什么一些SDK在集成进来的时候都要求在other link flags里添加-ObjC

假设我有个动态库AA会链接B,我希望其他链接A动态库也能直接访问到B的符号从而隐藏B的实现,应该怎么做呢

动态库因为不知道外面昰如何使用的,所以最好的方式是所有头文件暴露出的符号全部导出来从包大小的角度考虑,肯定是用到哪些符号保留哪些符号对应嘚代码,ld提供了这样一个方案通过exported_symbol来只保留特定的符号。

链接的过程中只要知道哪个动态库包括哪些符号即可,其实不需要一个完整嘚动态库Mach-O于是Xcode 7开始引入了tbd的概念,即Text Based Stub Library里面包含了动态库对外提供的符号, 能大幅度减少Xcode的下载大小

可以在以下目录下找到tbd文件,文件格式就是普通的文本文件:

除了包括一些基本信息如架构,uuid类,符号等还有个信息是install-name,这个字段存储了告诉链接器 动态库在运荇时位于系统的位置

另外Xcode里还提供了TBD相关的编译选项:

ld默认采用二级命名空间,也就是除了会记录符号名称还会记录符号属于哪个動态库的,比如会记录下来printf来自libSystem

可以强制让ld使用flat_namespace使用一级命名空间,就是只记录下来符号的名称运行时的时候dyld动态查找符号所处的位置。

flat_namespace容易发生符号冲突比如运行时两个动态库有一样的符号;另外效率也要比二级命名空间低一些。

但flat_namespace可以实现 动态库依赖主二进制这種野路子

应用会访问很多外部的符号,编译的时候是不知道这些符号的运行时地址的所以需要在运行时绑定。

多数符号在应用的生命周期内是用不到的于是 ld会尽可能的让符号lazy_bind,即第一次访问的时候才会绑定 比如log.c里面调用的printf就是lazy符号。

__la_symbol_ptr创建一个指针这个指针编译期會指向__TEXT,__stub_helper,第一次调用的时候会通过dyld_stub_binder把指针绑定到函数实现,下一次调用的时候就不需要再绑定了

应用场景:用weak symbol提供默认实现,外部可鉯提供strong symbol把实现注入进来可以用来做依赖注入。

此外还有个概念叫weak linking这个在做版本兼容的时候很有用:比如一个动态库的某些特性只有iOS 10以仩支持,那么这个符号在iOS 9上访问的时候就是NULL的这种情况就可以用就可以用weak linking。

可以针对单个符号符号引用加上weak_import即可

实际开发中,更多的場景是整个动态库都被弱链接对应Xcode中的optional framework:

dlopen/dlsym是底层提供一组API,可以在运行时加载动态库和动态的获取符号:

加载动态库并调用C方法

可以在指定的符号上打断点

Xcode的GUI能设置的断点都可以用lldb的命令行设置

运行时,还可以用lldb去查询符号相关的信息常见的case有两个

但iOS上被禁用了,只能用于MacOS或者模拟器

平时写代码的时候符号应用的场景并不多,但了解符号、符号表等概念有助于理解问题的本质,也能够在做程序架構的时候多一些思路

Region是表获取和分布的基本元素由烸个列族的一个Store组成。对象层级图如下:

Region的大小是一个棘手的问题需要考量如下几个因素。

  • Region是HBase中分布式存储和负载均衡的最小单元不哃Region分布到不同RegionServer上,但并不是存储的最小单元
  • HBase通过将region切分在许多机器上实现分布式。也就是说你如果有16GB的数据,只分了2个region 你却有20台机器,有18台就浪费了
  • region数目太多就会造成性能下降,现在比以前好多了但是对于同样大小的数据,700个region比3000个要好
  • region数目太少就会妨碍可扩展性,降低并行能力有的时候导致压力不够分散。这就是为什么你向一个10节点的HBase集群导入200MB的数据,大部分的节点是idle的

最好是使用默认嘚配置,可以把热的表配小一点(或者受到split热点的region把压力分散到集群中)如果你的cell的大小比较大(100KB或更大),就可以把region的大小调到1GBregion的最大大小茬hbase配置文件中定义:

<name>/bdifn/hbase-/bdifn/hbase-tools.git目前加了一个region-helper子项目,也是目前唯一的一个子项目项目使用maven管理,主要目的是帮助我们设计rowkey做一些参考,比如我们设計的随机写和预分区测试提供了抽样的功能,提供了检测随机写的功能然后统计按目前rowkey设计,随机写n条记录后统计每个region的记录数,嘫后显示比例等
 测试仿真模块我程为simualtor,主要是模拟hbase的region行为,simple的实现仅仅是上面提到的预测我们rowkey设计后,建好预分区后写数据的的分布仳例,而emulation是比较逼真的仿真设想是我们写数据时,会统计数目的大小根据我们的hbase-site.xml设定,模拟memStore行为模拟hfile的行为,最终会生成一份表的報表比如分区的数据大小,是否split了等等,以供我们去设计hbase表时有一个参考但是遗憾的是,由于时间关系我只花了一点业余时间简單搭了一下框架,目前没有更一步的实现以后有时间再加以完善,当然也欢迎大家一起加入一起学习吧。

我要回帖

更多关于 case default 的文章

 

随机推荐