分类 计算机基础 下的文章

概念:

  • 内存地址空间:就是能索引到内存单元的地址合集。
  • 链接器:将应用程序与地址绑定。
  • 地址总线:CPU用来访问内存的方式
  • 地址译码器:CPU与内存地址的映射,可以是设备寄存器,也可以是内存单元。
  • 物理地址空间:就是地址总线位数所表示的数据范围。
  • 虚拟地址空间:除了CPU地址总线,操作系统都是使用虚拟地址。
  • MMU(内存管理单元):转换机构,将虚拟地址转为物理地址,CPU才能访问。

内存地址

内存地址空间

内存地址产生方式

  • 链接器对程序重定位后执行地址绑定,静态地址。
  • 代码中直接定义地址。
  • 动态分配内存,返回内存空间的首地址。

进程

进程是系统分配资源和调度的基本单位。一个应用程序为1个进程。地址独立。

内存管理

进程在内存主要分为5个区:
1.代码区 (.text) - 存放函数体的二进制代码
2.文字常量区 (.rodata) - 存放常量字符串
3.静态区 (static) - 存放全局变量、静态变量
4.堆区 (heap) - 开发者手动分配的内存空间,结构类似链表
5.栈去 (stack) - 存放函数参数、局部变量。由编译器自动管理,结构类似栈。

线程

线程是cpu调度的最小单位,一个进程内的线程间资源共享。
线程是由系统内核提供的服务,用户通过系统调用让内核启动线程,内核负责线程的调用和切换。

协程

协程是go自己管理的线程,比系统线程开销更少,速度更快。

glibc 对系统调用的封装

我们以最常用的系统调用 open,打开一个文件为线索,看看系统调用是怎么实现的。这一节我们仅仅会解析到从 glibc 如何调用到内核的 open,至于 open 怎么实现,怎么打开一个文件,留到文件系统那一节讲。
现在我们就开始在用户态进程里面调用 open 函数。
为了方便,大部分用户会选择使用中介,也就是说,调用的是 glibc 里面的 open 函数。这个函数是如何定义的呢?
int open(const char *pathname, int flags, mode_t mode)
在 glibc 的源代码中,有个文件 syscalls.list,里面列着所有 glibc 的函数对应的系统调用,就像下面这个样子:

# File name Caller Syscall name Args Strong name Weak names
open - open Ci:siv __libc_open __open open

另外,glibc 还有一个脚本 make-syscall.sh,可以根据上面的配置文件,对于每一个封装好的系统调用,生成一个文件。这个文件里面定义了一些宏,例如 #define SYSCALL_NAME open。
glibc 还有一个文件 syscall-template.S,使用上面这个宏,定义了这个系统调用的调用方式。

T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
ret
T_PSEUDO_END (SYSCALL_SYMBOL)
#define T_PSEUDO(SYMBOL, NAME, N) PSEUDO (SYMBOL, NAME, N)

这里的 PSEUDO 也是一个宏,它的定义如下:

#define PSEUDO(name, syscall_name, args) \
.text; \
ENTRY (name) \
DO_CALL (syscall_name, args); \
cmpl $-4095, %eax; \
jae SYSCALL_ERROR_LABEL

里面对于任何一个系统调用,会调用 DO_CALL。这也是一个宏,这个宏 32 位和 64 位的定义是不一样的。






- 阅读剩余部分 -

对称加密

常见的对称加密算法有DES、3DES、AES、TDEA、Blowfish、RC4、RC5和IDEA。

非对称加密

RSA、Elgamal、Rabin、D-H、ECC(椭圆曲线加密算法)等。

哈希散列

常用的Hash散列算法有:MD4、MD5、SHA1、SHA-256等。

  1. 链地址法,将冲突键以链表结构存储
  2. 开放寻址法。其中包括三种方式:线性探测再散列、二次探测再散列、伪随机再散列
  3. 再散列法。对冲突键不断散列,直到不冲突为止。消耗计算时间。