Linux代码结构学习

Linux代码结构 准备学习Linux,看源码是少不了的,先对Linux源码有个大体认识(基于linux4.13) 代码主要文件解析 Makefile 这是整个源码的Makefile,里面定义了一系列的变量和规则,比如默认的gcc编译flag。 Documentation/ 项目文档,里面包含了很多关于配置内核、与ramdisk运行等有用的信息。这里面没有不同配置项的帮助信息,这些信息可以在相关子目录的 Kconfig 文件中查看。 arch/ 体系结构相关代码都在这里,还有一部分在include/arch-generic中。每个体系结构在这个目录下都有一个子目录。比如基于x86体系的代码都在 arch/x86 下。另外,这个目录下还包含低级别的内存管理,中断处理,早期初始化,汇编例程等信息。 crypto/ 内核使用的加密API代码。 drivers/ 所有设备相关的信息都在这个目录下。包括视频设备,网卡设备,低级别的SCSI设备。比如网络设备一般是在 drivers/net 目录下。 fs/ 通用的文件系统与其它类型的文件系统代码都在这里。现在的操作系统的根文件系统一般为ext4格式,它的代码在 fs/ext4 下 include/ 所有.c文件中包含的头文件都定义在这个目录下。 init/ 这个目录包含了内核启动的入口文件 main.c ,版本信息文件 version.c 和早期用户空间相关的代码,早期空间代码提供内核出现时的功能,它不需要在内核中进行运行。 ipc/ 进程间通信相关代码,包含共享内存,信号量等信息。 kernel/ 内核级别代码,上层的系统调用代码在这里,还有关于 printk() 代码,调度,信号量处理的代码。 lib/ 内核所有使用的库都在这里。常见的字符串运算,调试库,命令行解析代码等。 mm/ 高级别的内存管理代码。虚拟内存是通过这些库与低级别的体系结构代码(在 arch//mm )一同实现的。这里完成了早期引导内存管理,涉及文件的内存映射,页缓存的管理,内存分配和RAM中页面的交换。 net/ 高级别的网络代码。与低级别的网络进行发包与收包交互。*net/core* 中包含其它网络协议使用的核心代码。net子目录就是特定的网络协议实现。 scripts/ 这里面包含构建内核的脚本文件。 security/ 不同Linux的安全模型代码。 sound/ 声卡及相关代码在这里。 usr/ 该目录包含构建根文件系统映射的cpio格式的文档代码,该文档用于早期的用户空间。

2022-04-06 ·  (🌟Updated: 2022-04-06) · 1 min · 54 words · tomyli

记一次SpringWebflux框架下堆外OOM排查经历

症状 生产环境业务页面打不开,看错误日志是 OutOfDirectMemoryError (OOM)了,详情报错信息如下: 2022-03-21 06:00:00.541 [,] [tafprx-asyrecv_9] ERROR r.c.p.Operators - [error,314] - Operator called default onErrorDropped java.lang.OutOfMemoryError: Direct buffer memory at java.base/java.nio.Bits.reserveMemory(Bits.java:175) at java.base/java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:118) at java.base/java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:317) at io.netty.buffer.PoolArena$DirectArena.allocateDirect(PoolArena.java:632) at io.netty.buffer.PoolArena$DirectArena.newChunk(PoolArena.java:607) at io.netty.buffer.PoolArena.allocateNormal(PoolArena.java:202) at io.netty.buffer.PoolArena.tcacheAllocateSmall(PoolArena.java:172) at io.netty.buffer.PoolArena.allocate(PoolArena.java:134) at io.netty.buffer.PoolArena.allocate(PoolArena.java:126) at io.netty.buffer.PooledByteBufAllocator.newDirectBuffer(PooledByteBufAllocator.java:395) at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:187) at io.netty.buffer.AbstractByteBufAllocator.directBuffer(AbstractByteBufAllocator.java:178) at io.netty.buffer.AbstractByteBufAllocator.buffer(AbstractByteBufAllocator.java:115) at org.springframework.core.io.buffer.NettyDataBufferFactory.allocateBuffer(NettyDataBufferFactory.java:71) at org.springframework.core.io.buffer.NettyDataBufferFactory.allocateBuffer(NettyDataBufferFactory.java:39) at org.springframework.http.codec.json.AbstractJackson2Encoder.encodeValue(AbstractJackson2Encoder.java:236) at org.springframework.http.codec.json.AbstractJackson2Encoder.lambda$encode$0(AbstractJackson2Encoder.java:150) at reactor.core.publisher.FluxMapFuseable$MapFuseableSubscriber.onNext(FluxMapFuseable.java:113) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815) at reactor.core.publisher.MonoCompletionStage.lambda$subscribe$0(MonoCompletionStage.java:82) at java.base/java.util.concurrent.CompletableFuture.uniWhenComplete(CompletableFuture.java:859) at java.base/java.util.concurrent.CompletableFuture.uniWhenCompleteStage(CompletableFuture.java:883) at java.base/java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:2251) at java.base/java.util.concurrent.CompletableFuture.whenComplete(CompletableFuture.java:143) at reactor.core.publisher.MonoCompletionStage.subscribe(MonoCompletionStage.java:57) at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815) at reactor.core.publisher.MonoFlatMap$FlatMapInner.onNext(MonoFlatMap.java:249) at reactor.core.publisher.FluxOnErrorResume$ResumeSubscriber.onNext(FluxOnErrorResume.java:79) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199) at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.complete(MonoIgnoreThen.java:284) at reactor.core.publisher.MonoIgnoreThen$ThenIgnoreMain.onNext(MonoIgnoreThen.java:187) at reactor.core.publisher.Operators$MonoSubscriber.complete(Operators.java:1815) at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:151) 根据报错的堆栈,找到 AbstractJackson2Encoder:236 行,调试发现框架使用的buffer在最后都进行了释放,看着没问题。 ...

2022-03-31 ·  (🌟Updated: 2022-04-13) · 3 min · 615 words · tomyli

那些提高效率MAC软件(全程免费)

NTFS 支持MAC电脑读取NTFS格式文件 eul 监控MAC运行状态的工具 uPic 文件与图片云端上传工具 Sequel-Ace MAC上数据库管理工具,支持Mysql与MariaDB CopyQ MAC上免费的剪切板工具 Bob MAC上翻译软件 LuLu MAC上强大的防火墙 hidden MAC菜单栏图标隐藏工具 Brooklyn MAC上炫酷的屏保程序 Gifski 把Video转换成Gif BackgroundMusic 音频工具,可以为每个app设定音量值 pixel-picker MAC取色软件 Itsycal MAC日历软件 SwitchHosts 快速切换机器Host,开发必备 hammerspoon 使用Lua脚本来控制电脑 squirrel 鼠鬚管,无敌的输入法 iTerm2 MAC上的终端模拟器 keycastr MAC上按键显示工具 TODO pot-app/pot-desktop: 🌈一个跨平台的划词翻译和OCR软件 | A cross-platform software for text translation and recognition. TODO jordanbaird/Ice: Powerful menu bar manager for macOS TODO qarmin/czkawka: Multi functional app to find duplicates, empty folders, similar images etc. TODO FelixKratz/SketchyBar: A highly customizable macOS status bar replacement TODO nikitabobko/AeroSpace: AeroSpace is an i3-like tiling window manager for macOS TODO Alex313031/thorium: Chromium fork named after radioactive element No. 90. Windows and MacOS/Raspi/Android/Special builds are in different repositories, links are towards the top of the README.md. TODO odlp/bluesnooze: Sleeping Mac = Bluetooth off TODO nonwill/GoldenDict-OCR: GoldenDict++:内置大量的官方版本问题的修正;先期添加了一个简单的插件机制,并基于该机制接入了多个 OCR 划词 和 音频播放 引擎;后期在增强易用性的基础上为提高查询效率、减少运行时 CPU 及 内存 占用、降低代码维护难度,完全重构了所有的实现;将来的目标是将功能扩展和词典格式处理抽象为完整的插件实现,以进一步增强应用的扩展性和可维护性。 TODO Homebrew/homebrew-bundle: 📦 Bundler for non-Ruby dependencies from Homebrew, Homebrew Cask and the Mac App Store. ungoogled-software/ungoogled-chromium: Google Chromium, sans integration with Google 生活中去google化 ...

2021-10-25 ·  (🌟Updated: 2024-04-28) · 1 min · 180 words · tomyli

让好代码生生不息-更好的使用String

开发中常用的String操作 开发中经常用到的操作有: 格式化/日志格式化 字符串判断 字符串处理,常见的如处理字符串的第一个/最后一个字符 String.format String.format()是一个格式化的方法,使用%为前缀来表示要格式化的内容占位,一般的使用方法为: String.format("test result is %s", "success"); 但是当要格式化的占位符与参数个数不同时会发生什么呢? 占位符个数与参数个数相同 如上代码,可以正常进行输出: test result is success 占位符个数少于参数个数 String.format("test result is %s", "success", "other"); 可以正常打印,输出结果为: test result is success 占位符个数多于参数个数 String.format("test result is %s %s %s", "success", "other"); 抛出了异常java.util.MissingFormatArgumentException: Format specifier ‘%s’ 问题总结 为什么占位符数少于参数个数可以正常执行,而多于参数个数却报了异常?看JAVADOC发现,如果占位符个数少于参数个数,则多余的参数被忽略,如果多于参数个数,则在进行解析时会判断待处理占位符位置与参数个数,主要代码逻辑如下: if (args != null && lasto > args.length - 1) throw new MissingFormatArgumentException(fs.toString()); 所以在使用String.format方法 切记 要参数个数多于待解析占位符的个数,这种问题常因为Copy操作后,处理了部分参数而忘记对应处理占位符 替换方案 目前看到很多的老代码打印日志时大都使用String.format(),可以改成slf4j的{} 还可以使用Apache common utils中的StringUtils.joinWith()或者Google guava的Joiner连接器 Apache commons utils-StringUtils 在StringUtils中有一个isNumeric方法,用来判断字符串是不是数字,那下面的代码会返回什么呢? ...

2021-08-23 ·  (🌟Updated: 2021-09-06) · 2 min · 221 words · tomyli

让好代码生生不息-更好的对待NULL

什么样的代码是好代码 易读的代码,行云流水的代码 JAVA中的NULL处理 众所周知,在Java代码中总是少不了一堆的判null逻辑,在代码bug中,NullPointerException出镜率也是非常高的,尤其是现在的主流分布式架构,一个web接口要调用后端的N个RPC服务来实现功能,基于防御编程的思想,判null就更重要了 在处理NULL时怎么做更好 IDE 既然无法避免null,IDE就给程序员增加了可以快速判断空的功能,比如在IDEA中,可以使用Postfix功能,在对象上o使用.nn来快速输入if(o != null) {} JAVA基础类库 近期的JDK版本也针对null判断增加了一些实用的方法 Objects类 JAVA8在Objects工具提供了isNull()和nonNull()方法,JAVA9又增加了requireNonNullElse()和requireNonNullElseGet()来给待处理对象增加设置默认值的方法 知名三方库 Apache common utils中提供了非常多的判空工具类,如针对String操作的StringUtils类和针对集合操作的CollectionUtils、MapUtils、ListUtils、SetUtils,这几个类都有一些典型的方法来进行判空处理,通用的方法如下: StringUtils isEmpty()/isNotEmpty() 判断String是否为空/不空 isBlank()/isNoneBlank() 判断String是否为空/不空,这类方法还会判断实际值是否为空串 defaultString() 此方法允许在String为null时为返回空串 defaultIfBlank()/defaultIfEmpty() 此方法允许在String为空串或null时设置一个默认值 集合类Utils isEmpty()/isNotEmpty() 判断集合是否为空/不空 emptyIfNull() 这是一个很有用的方法,当传入对象为空时则返回设置的默认对象,可以很好的根治if处理null的问题,下面两段代码演示一下 正常情况下有if判断 List<Object> values = rpcClient.getFromRpcList(); if(CollectionUtils.isNotEmpty(values)) { return values .forEach(System.out::println); } 使用emptyIfNull方法 return CollectionUtils.emptyIfNull(rpcClient.getFromRpcList()) .forEach(System.out::println); 这样保证了代码编写的连贯性,爽! 此方法在ListUtis、MapUtils、SetUtils中也有提供 defaultIfNull() 此方法允许在集合为null时设置一个默认值,也是可以链式操作 优秀的Coder 在编写通用方法时,对于有null返回的情况可以使用返回默认值来代替null 不返回空,以空对象来代替 比如返回一个new Object() ...

2021-07-17 ·  (🌟Updated: 2021-07-23) · 1 min · 60 words · tomyli

JAVA中获取调用栈帧的最优方式

前言 近期在做日志优化,需要记录业务日志,日志内容包括业务的请求、响应信息。当然还应该有具体的调用方法位置、日志的所在的方法等通用信息。 解决方案 一般情况下,在程序有异常信息时可以打印出整个调用堆栈信息,但是现在需要的是正常调用下来获取到当前方法的调用帧。 JAVA9之前 Thread.dumpStack() 这个可以打印出当前的堆栈错误信息,本质上是new一个Exception,调用了printStackTrace()方法,但是这个方法只建议用于调试。 public class StackTraceExample1 { public static void main(String[] args) { one(); } public static void one() { two(); } private static void two() { three(); } private static void three() { Thread.dumpStack(); } } 执行后输出如下: java.lang.Exception: Stack trace at java.base/java.lang.Thread.dumpStack(Thread.java:1379) at cn.imcompany.stack.StackTraceExample1.three(StackTraceExample1.java:25) at cn.imcompany.stack.StackTraceExample1.two(StackTraceExample1.java:21) at cn.imcompany.stack.StackTraceExample1.one(StackTraceExample1.java:17) at cn.imcompany.stack.StackTraceExample1.main(StackTraceExample1.java:13) 直接以异常的方式显示出来了。 ...

2021-04-20 ·  (🌟Updated: 2021-04-21) · 1 min · 154 words · tomyli

2020-ARTS-打卡第十四天

Algorithm 题目 题目描述 98.验证二叉搜索树,给定一个二叉树,判断其是否是一个有效的二叉搜索树。假设一个二叉搜索树具有如下特征: 节点的左子树只包含小于当前节点的树 节点的右子树只包含大于当前节点的树 所有左子树及右子树自身也必须是二叉搜索树 题目解答 import java.util.Stack; public class ValidBST { public boolean isValidBST (TreeNode root) { Stack<TreeNode> stack = new Stack<>(); double inorder = -Double.MAX_VALUE; while (!stack.isEmpty() || root != null) { while (root != null) { stack.push(root); root = root.left; } root = stack.pop(); if (inorder >= root.val) { return false; } inorder = root.val; root = root.right; } return true; } } 使用中序遍历(即左->根->右)来实现,从左至右进行比对,每次与上次保存的值进行对比,如果当前节点值比上次保存的值小,则可以判定此树不是二叉搜索树。时间复杂度为O(n),空间复杂度为O(n) ...

2020-04-20 · 1 min · 126 words · tomyli

2020-ARTS-打卡第十二天

Algorithm 题目 题目描述 给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。242 valid anagram 题目解答 可以使用先排序后判断的方法来实现,这样的时间复杂度为O(nlog(n))。更好的方法是借助Hash表来实现,可以达到O(n)的时间复杂度。 public class ValidAnagram { public boolean isAnagram(String s, String t) { if (null == s || null == t || s.length() != t.length()) { return false; } Map<Character, Integer> map = new HashMap<>(); final char[] chars = s.toCharArray(); for (int i = 0; i < chars.length; i++) { final char key = s.charAt(i); map.put(key, map.getOrDefault(key, 0) + 1); final char key1 = t.charAt(i); map.put(key1, map.getOrDefault(key1, 0) - 1); } for (Map.Entry<Character, Integer> entry : map.entrySet()) { if (0 != entry.getValue()) { return false; } } return true; } } Review 你可能不知道的SHELLCoolShell左耳朵耗子2012年的关于强大Shell的文章,里面列出了很多有用的命令,看完后收获颇丰。针对实际使用场景,列出我认为暂时可以直接使用的一些操作命令。 ...

2020-03-30 · 1 min · 150 words · tomyli

2020-ARTS-打卡第十一天

Algorithm 题目 题目描述 给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。返回滑动窗口中的最大值。 239 sliding-window-maximum 题目解答 一般与滑动窗口有关的问题都可以使用双端队列来处理。 import java.util.ArrayDeque; import java.util.List; import java.util.ArrayList; public class MaxSlidingWindow { private ArrayDeque<Integer> window = new ArrayDeque<>(); public int[] slidingWindowMax(int[] nums, int k) { if(nums.length == 0) { return new int[0]; } List<Integer> res = new ArrayList<>(); for(int i = 0; i < nums.length; i++) { if(i >= k && window.getFirst() <= i - k) { window.pollFirst(); } while(!window.isEmpty() && nums[window.getLast()] < nums[i]) { window.pollLast(); } window.add(i); if(i >= k - 1) { res.add(nums[window.getFirst()]); } } return res.stream().mapToInt(i->i).toArray(); } } Review Consistent_hashing一致性Hash算法。 ...

2020-03-23 · 1 min · 135 words · tomyli

2020-ARTS-打卡第十天

Algorithm 题目 题目描述 设计一个找到数据流中第K大元素的类(class)。注意是排序后的第K大元素,不是第K个不同的元素。703 数据流中的第K大元素 题目解答 public class KthLargest { private PriorityQueue<Integer> queue; private int k; public KthLargest(int k, int[] nums) { this.k = k; queue = new PriorityQueue<>(k); for(int num : nums) { add(num); } } public int add(int val) { if(queue.size() < k) { queue.offer(val); } else if (queue.peek() < val) { queue.poll(); queue.offer(val); } return queue.peek(); } } Review 与程序员相关的CPU缓存知识这是左耳朵耗子的一篇微观技术分享,讲解了程序员要知道的关于CPU缓存的知识,并举例进行了说明。 ...

2020-03-16 · 1 min · 136 words · tomyli