Linux系统编程(一) 之时间编程
这是 Linux 系统编程系列 中的第一篇, 在这个系列里面, 我想以这么个顺序来讲述每一篇的内容, 先是快速简单地了解一下 常见的使用方法, 即API如何使用, 接着再深入其中, 了解内核为API提供的帮助, 大致是 C标准库 → 系统调用 这么个学习路线.
时间的定义
首先要记住 计算机的起始时间 为 (格林威治时间)1970年1月1日0点, 被称作 GMT时间 是时区时间, 不过它是根据地球公转和自转来计算的, 不是特别准确. 在计算机世界中, 往往被称作 UTC时间, 它是以原子钟来计算时间, 简单来说就是 UTC时间 比 GMT时间要准确, 同时两个时间又恰好没有时差, 但是UTC时间又不是时区时间, 因此容易被人弄混.
C++ 内存管理 之 Loki Allocator
Loki Allocator 有三个类 这玩意对比起 pool allocator 的优点就在于 它有把内存还给系统
但是它作为一个 内存分配器 却在里面使用了 vector 作为容器… 按道理来说 应该在其内部实现一个简易版的 vector 才不会那么奇怪 但也没所谓 只是 先用了一次标准库的分配器 后续使用容器的时候 就可以用 Loki 分配器了.
- Chunk
- FixedAllocator
- SmallObjAllocator
Chunk 解剖
Chunk 是整个分配器的最底层 里面主要是三个 成员变量
1 | // 指向内存块 |
Chunk 的几个关键函数 已进行 剪裁 和 修改
Chunk 分配
分配流程很简单 就是 申请了内存以后 将每个小区块的第一个字节设置为索引 排好号
取的流程:
- 从 当前可用区块的第一块索引中取 得当前可用区块
- 当前可用区块会被返回
- 被返回的可用区块中的索引 被设置到 当前可用区块索引去(这样下一次就会使用到它)
- 可用区块数目 - 1
C++ 内存管理 之 内存池实现
为什么要实现内存池?
一方面 是为了减少 调用 malloc() 的次数(尽管 malloc() 不慢) 但是调多了 会产生(外碎片)
另一方面 是因为 每次用 malloc() 分配到的内存 是要交税的 就是上一节中讲的 cookie 里面记录着 这一块内存的大小信息(内碎片) 特别是在频繁申请小内存的时候尤为明显
最终 pool_allocator 版本
具体代码可见 Memory_Pool
C++ 内存管理 之 G4.9 扩展内存分配器
本文主要讲讲 GNU-C++ 4.9 下的扩展内存分配器
首先 GNU-C++ 4.9 有 7 个扩展的内存分配器
- new_allocator
- malloc_allocator
- pool_allocator
- __mt_alloc
- array_allocator
- debug_allocator
- bitmap_allocator
主要看看 pool_allocator array_allocator bitmap_allocator
以下源码都可在 .../ext/*.h 下找到 我将其进行了适当的 删减和修改
__gnu_cxx::new_allocator
直接用 ::operator new 和 ::operator delete 实现出来的 好处是 可以被重载 没啥特色
1 | template<typename _Tp> |
C++ 内存管理 之 STL内存分配实现原理
本文主要讲的是 各个C++版本 中的STL标准库中的默认内存分配器 的 各种实现
VC6 标准分配器实现
VC6 它什么内存管理都没做 直接调用的 operator new 而 operator new 内部实际上 调用的就是 malloc
此外 VC6 下 是以元素为单位 比如 int 的话 他就会分配 512 ints 如果是 double 则会分配 512 doubles
而 GNU-C++ 2.9 以字节为单位 GNU-C++ 4.9 以元素为单位 在 G2.9 中的容器默认分配器 被移到了 pool_allocator 中
注意 G2.9 的标准分配器 和 容器默认分配器 不一样噢!
GNU-C++ 2.9 标准分配器实现
std::allocator 标准分配器 也是什么都没做
但是 G2.9 容器使用的分配器 不是上面的那个 std::allocator 而是 std::alloc
C++ 内存管理 之 原生版本
为什么要叫原生版本?
因为我觉得这一块是 C++ 自带的表达式 表达式里面 去调用 C语言的 CRT 库中的 malloc 和 free 但这篇 只讲自带的表达式 而不去深究 CRT 中的内存分配函数 所以只叫原生版本
常见的内存分配
| 分配 | 释放 | 类属 | 可否重载 |
|---|---|---|---|
| malloc() | free() | C 函数 | 否 |
| new | delete | C++ 表达式 | 否 |
| ::operator new() | ::operator delete() | C++ 函数 | 可 |
| allocator | allocator | C++ 标准库 | 自由设计搭配的容器 |
使用示例
其中 ::operator new() 和 ::operator delete() 调用了 malloc() 和 free()
1 | void *p1 = malloc(512); |
离线安装 VSCode Remote-SSH
VSCode 近期推出了 Remote-SSH 这个工具 使得 Linux开发者 能够在本地(Windows 机)上直接对开发机源码进行修改 简直拯救了一大批人啊… 但是却没有提到 如何离线安装 因此本文可能是最早 尝试离线安装的教程
离线安装
- 本地上下载好 VSCode Insiders
- 安装
Remote-SSH插件
我所理解的子网掩码
首先 IPv4 资源是非常稀少的 大约只有 43亿 而且这还是包括了私有IP地址段的 其次 IP地址分为了五类 其中 D类地址没有主机标识 常被用于广播 E类被保留 我们不去管它
那就只剩下了 A B C 三类 问题是 A类和B类的链路允许非常多的计算机连接 实际网络架构上 根本用不到那么多 这就造成了IPv4的浪费 这个时候 子网掩码出现了
子网掩码的意义
将 A B C类网络进行更细的划分 避免浪费 IPv4地址 也可以把小的网络归并成大的网络即超网
子网掩码的理解
假设有一个财主 他有256间房子 房子的编号是 0~255 然后它的房子都在192.168.0这一条街上 现在他有8个儿子 要分家 则相当于 每个人都分得32间房子
实现 SOCKS5 网络混淆代理
在天朝这么久 你曾为网络状况不佳而烦恼过吗? 平时使用的 Shadowsocks 是怎么实现?
这篇讲的就是 如何用 Golang 实现一个最为基础的 Shdowsocks 的功能的软件 我将本文实现的软件取名叫 GoSocksProxy
老规矩先介绍一遍 什么是 GoSocksProxy? 它是怎么来的?
GoSocksProxy
一个 Golang 所写的网络混淆代理 是学习 SOCKS5 协议时的副产品 为此还做了一张图
