Linux基础知识

1. ELF格式

  Linux下二进制可执行程序的格式一般为ELF格式,使用命令readelf查看其ELF格式。Win9x和Win NT/2000/XP下的32位的可执行文件PE(Portable Executable:可移动的可执行文件)。
  ELF文件的主要内容就是由各个section和symbol表组成。最熟悉的应该是text段、data段和bss段。text段为代码段,用于保存可执行指令。data段为数据段,用来保存非0初始值的全局变量和静态变量。bss段用来保存没有初始值或初值为0的全局变量和静态变量,当程序加载时,bss段中的变量会被初始化为0。这个段并不占用物理内存——因为完全没有必要,这些变量的值固定初始化为0,因此何必占用宝贵的物理空间。
  下面介绍一下其中一些比较常见的段:
  debug段:顾名思义,用于保存调试信息。
  dynamic段:用于保存动态链接信息
  fini段:用于保存进程退出时的执行程序。当进程结束时,系统会自动执行这部分代码
  init段:用于保存进程启动时的执行程序。当进程启动时,系统会自动执行这部分代码
  rodata段:用于保存只读数据,如const修饰的全局变量、字符串常量。
  symtab段:用于保存符号表。
  其中,关于与调试有关的段,如果不使用-g选项,则不会生成,但与符号相关的段仍然会存在,这时可以使用strip去掉符号信息。

2. strace跟踪系统调用

  在Linux中,执行一个命令时,首先由shell调用fork,然后在子进程中来真正执行这个命令(这一过程在strace输出中无法体现)。strace是程序开始执行后的输出。首先是调用execve来加载程序,然后ld会分别检查ld.so.nohwcap和ld.so.preload。其中,如果ld.so.nowcap存在,则ld会加载其中未优化的库。如果ld.so.preload存在,则ld会加载其中的库——在一些项目中,我们需要拦截或替换系统调用或C库,此时就会利用这个机制,使用LD_PRELOAD来实现。之后利用mmap将ld.so.cache映射到内存中,ld.so.cache中保存了库的路径,这样就完成了所有的准备工作。接着ld加载C库——libc.so.6,利用mmap及mprotect设置程序的各个内存区域,到这里,程序运行的环境已经完成。

3. 系统调用

  系统调用是操作系统提供的服务,是应用程序与内核通信的接口。在x86平台上,有多种陷入内核的途径。最早是通过int 0x80指令来实现的,后来Intel增加了一个新的指令sysenter来代替int 0x80的一半左右。即使是这样,相对于普通的函数调用来说,系统调用的性能消耗也是巨大的。所以在追求极致性能的程序中,都在尽力避免系统调用,譬如C库的gettimeofday就避免了系统调用。
  用户空间的默认程序是通过栈来传递参数的。对于系统调用来说,内核态和用户态使用的是不同的栈,这使得系统调用的参数只能通过寄存器的方式进行传递。

4. C库函数

  C库函数为编译器解决了系统调用的问题。Linux环境下,使用的C库一般都是glibc,它封装了几乎所用的系统调用,代码中使用的“系统调用”,实际上就是调用C库中的函数。C库函数同样位于用户态,所以编译器可以统一处理所有的函数调用,而不是区分该函数到底是不是系统调用。
  在Linux平台下,系统调用的约定是使用寄存器eax来传递系统调用号的。

5. 线程安全

  线程安全,顾名思义是指代码可以在多线程环境下“安全”的执行。何谓安全?即符合正确的逻辑结果,是程序员期望的正常执行结果。为了实现线程安全,该代码要么只能使用局部变量或者资源,要么就是使用锁等同步机制,来实现全局变量或资源的串行访问。
  下面是一个经典的多线程不安全代码:
在这里插入图片描述
在这里插入图片描述
  通过加锁,可以视counter的自增指令为“原子指令”,最后的结果则是我们期望的答案。

5. 原子性

  对于计算机来说,如果变量是原子的,那么对这个变量的任何访问和更改都是原子的。如果操作是原子的,那么这个操作将是不可分割的,要么成功,要么失败,不会有任何的中间状态。原子性是事务的一个特性之一。

6. 可重入函数

  从字面上理解,可重入就是可重复进入。在编程领域,它不仅仅意味着可以重复进入,还要求在进入后能够成功执行。这里的重复进入,是指当前进程已经处于该函数中,这时程序会允许当前进程的某个执行流程再次进入该函数,而不引发问题。这里的执行流程不仅仅包括多线程,还包括信号处理、longjump等执行流程。所以,可重入函数一定是线程安全的,而线程安全函数则不一定是可重入函数。
  当函数使用锁的时候,尤其是互斥锁的时候,该函数是不可重入的,否则会造成死锁。若函数使用了静态变量,并且其工作依赖于这个静态变量时,该函数也是不可重入的,否则会造成改改函数工作不正常。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值