一个Linux 动态库常见bug
遇到的问题 对于正在运行的程序,当更新动态库尝试重新加载时,可能会导致程序 CoreDump 。 case: 我们的一个开发环境中有多个进程依赖同一个动态库.so, 我更新这个so的时候,直接用 cp new.so old.so 导致多个进程同时core,😮😮😮 这里简单解释下其原因,以及规避方案。 简介 在加载动态库 …
继续阅读浏览文章
22 项
遇到的问题 对于正在运行的程序,当更新动态库尝试重新加载时,可能会导致程序 CoreDump 。 case: 我们的一个开发环境中有多个进程依赖同一个动态库.so, 我更新这个so的时候,直接用 cp new.so old.so 导致多个进程同时core,😮😮😮 这里简单解释下其原因,以及规避方案。 简介 在加载动态库 …
继续阅读CSAPP 机器级表示 汇编 两个抽象 硬件 指令集 ISA 的抽象 虚拟内存 大数组 汇编与高级语言的区别 暴露的可操作 程序计数器 rip 条件寄存器 整数寄存器 ATT 汇编与 intel 汇编区别 intel 省略了 指示大小的后缀 Intel省略了 寄存器前的 % Intel 有很多不同的方法 描述内存的位置 …
继续阅读概述 对于大型的工程项目,依赖许多人的配合,包含大量不同的代码库与服务,有的我们能够访问程序的源代码,有的可以访问程序的可重定位文件,有的可以访问到可执行文件及其环境,假如我们想在在不同的层面改变或者添加一些逻辑,操作系统、编译器以及程序语言、代码库等都提供了 一些机制使得 开发者可以 方便的 增加或替换代码逻辑,对于 …
继续阅读什么是系统调用 系统调用是应用程序(包含运行库)与操作系统内核的接口,它决定了应用程序如何与内核打交道。在现在的操作系统系统里,程序运行的时候,本身是没有权利访问系统的资源,由于系统有限的资源有可能被不同的应用程序同时访问,因此,如果不加以保护,各个应用程序的冲突在所难免。所以现代操作系统都尽可能的把冲突的资源保护起来 …
继续阅读进程的建立 从操作系统的角度看,一个进程最关键的特征是它拥有独立的虚拟地址空间,这使得它有别于其他进程,很多时候一个程序程序被执行同时伴随着一个新进程的创建,在有虚拟存储的情况下,创建一个进程,然后加载可执行文件并且执行,需要做三件事: 创建一个独立的虚拟地址空间 读取可执行文件头,并且建立虚拟空间与可执行文件的映射关 …
继续阅读原子操作 自增(++i)操作在多线程环境下出现错误是因为这个操作被编译成的代码不止一条指令,因此在执行的时候可能执行到一半被系统调度打乱,去执行别的代码。我们把单指令的操作称为原子的(atomic),因为无论如何,单条指令的执行时不会被打乱的,为了避免出错,很多体系结构都提供了一些常用操作的原子指令。 同步与锁 为了避 …
继续阅读内存管理初步 物理内存 认为的先规划成两部分,用户的物理内存和内核的物理内存,专项专用,内核有方法去占用用户的内存,但是规定两部分内存是专用的,内核只使用自己的物理内存。 物理内存的内核、用户部分分别用 bitmap 来统计管理。 虚拟内存 首先,虚拟内存也是需要管理的,毕竟程序要申请堆上的内存,假定我们只支持512M …
继续阅读用C语言写内核 无论什么语言,要编译成 ELF文件格式(或者定一个其他的标准) int main() { while(1){}; return 0; } 链接可以指定最终生成的可执行文件的起始虚拟地址,我们 指定 内核加载到 0x1500的地方,内核初始化的时候跳转内核要跳转到这个地方。 ld …
继续阅读规划内核的内存分布 MBR、loader部分 我们把 加MBR、Loader以及后面需要加载的内核都放到 物理内存的 0-1M 这个空间里面,其中,MBR执行完了以后,我们把它覆盖掉,如下面的图。 图1: MBR,loader的物理内存定位 图二: 覆盖MBR位置写kerner.bin 分离用户空间和内核空间 用保护模 …
继续阅读原始进程 Linux下有3个特殊的进程,idle进程(PID = 0), init进程(PID = 1)和kthreadd(PID = 2) idle进程 由系统自动创建, 运行在内核态 idle进程其pid=0,其前身是系统创建的第一个进程,也是唯一一个没有通过fork或者kernel_thread产生的进程。完成加 …
继续阅读Linux2.6以前的线程 在Linux内核2.6出现之前进程是(最小)可调度的对象,当时的Linux不真正支持线程。Linux 2.4内核中不知道什么是“线程”,只有一个“task_struct”的数据结构,就是进程。 Linux内核有一个系统调用指令clone(),这个指令产生一个调用调用的进程的复件,而且这个复件 …
继续阅读中断分类 按照中断的来源分类,来自CPU外部的中断称为外部中断,来自CPU内部的称为内部中断;细分的话,外部中断根据严重程度,分为可屏蔽中断和不可屏蔽中断;内部中断按照是否正常分为软中断和异常。 外部中断 外部中断来自CPU的外部的某个硬件,因此又被称为硬件中断,比如网卡收到了一个数据包,它就会通知CPU,CPU得到通 …
继续阅读函数调用约定 编译器一般使用堆栈实现函数调用,每个进程都有自己的栈,用栈来传递参数,会带来以下问题: 参数存储在栈中,那么谁来负责回收参数所占的栈空间,是调用者?还是被调用者 当参数很多的时候后,主调函数将参数以什么样的顺序传递 高级语言有调用的约定: 举例: int sub(int a , int b){ // 被调 …
继续阅读文件描述符限制 文件描述符 Linux的核心思想之一就是”一切皆文件”。即Linux中所有的内容都是以文件的形式保存和管理的,它为不同类型的文件提供了统一的操作接口,对于不同类型的文件,我们都可以使用fopen()/fclose()/fwrite()/fread()等对这些文件进行读写处理。在Linux中,普通文件、目 …
继续阅读内核与C语言 写内核能用C标准库吗? 我们开发用户应用程序的时候,有标准库可以用,最典型的就是GUN C库,标准库一般是系统调用的封装,表面上是通过标准库访问系统资源,实际上是通过系统调用实现的。Linux的系统调用一般是先往eax寄存器写入系统调用号,然后通过0x80中断来实现。中断向量号为0x80称为系统中断门,更 …
继续阅读设计自己的页表 只针对32位的操作系统,设计一个二级页表,目的是构建一个简易的能跑起来的操作系统。对于4G的地址空间,每个页大小是4K,模仿Linux早期的做法,32位地址的前10位为页目录项,中间10位为页表,后面10位为偏移量。 |--目录项----|--页表-----|---地址偏移-| …
继续阅读保护模式 为什么要有保护模式 实模式是有很大弊端的,首先,直接操作物理内存,这样的话每次只能运行一个程序,并且不安全;另外,内存最大使用到1M,限制太大。 保护模式下,程序不能直接访问物理地址,程序的虚拟地址需要被转换为物理地址后再去访问,地址转换是由处理器和操作系统协作完成的,处理器在硬件上提供地址转换部件,操作系统 …
继续阅读熟悉MBR引导 MBR的512字节里面也是代码,他被BIOS加载执行,自身执行的时候加载操作系统的loader,我们在没有操作系统loader的情况下先写一段测试程序,体验一下。 实现的功能如下: BIOS 加载 MBR中的代码,执行,用BIOS 中断 INT 0x10显示字符串 MBR的代码 ;主引导程序 ; 起始编 …
继续阅读环境准备工作 有一台win10的笔记本,调试想选择在Linux环境下,选择配置虚拟机,然后安装bochs调试内核 需要准备的软件: VirtualBox和增加工具包 安装CentOS 6.8minimal 设置CentOS的网卡,使之能上网 用yum安装开发工具和GNOME 安装bochs 进入GNOME,在GNOME …
继续阅读操作系统引导 MBR 接上一篇BIOS启动,BIOS完成了基础的硬件检测和硬件的中断向量表的初始化,然后BIOS找到MBR并且把MBR加载在内存中,跳转到该位置。加载的位置在内存中的0x7C00,至于为什么是这个位置,主要是因为历史的原因吧,最初的内存只有32K,历史选择了0x7C00(31k)。 MBR引导扇区的内容 …
继续阅读硬件与BIOS流程 硬件 传统来说,主板上两个主要芯片,靠上方的叫北桥,靠下方的叫南桥。 大体上说:北桥负责与CPU通信,并且连接高速设备(内存/显卡),并且与南桥通信;南桥负责与低速设备(硬盘/USB)通信,时钟/BIOS/系统管理/旧式设备控制,并且与北桥通信。 Intel从第一代Core i7 (i7 9xx)开 …
继续阅读