当阅读一些开源服务器源码的时候, 如果不知道以下知识, 就会有知识盲点, 导致不知所云.
这篇博客会讲述一些相关的编程知识点, 把之前的笔记总结一下.
还是那句老话, 带着问题阅读是最容易让人类迅速进入状态的.
进程的内存布局是什么样的?
记忆口诀 : 文初堆栈
每个进程所分配的内存由很多部分组成,通常称之为“段( segment)”。如下所示。
- 文本段
包含了进程运行的程序机器语言指令。文本段具有只读属性,以防止进程通过错
误指针意外修改自身指令。因为多个进程可同时运行同一程序,所以又将文本段设为可
共享,这样,一份程序代码的拷贝可以映射到所有这些进程的虚拟地址空间中。 - 初始化数据段
包含显式初始化的全局变量和静态变量。当程序加载到内存时,从可执
行文件中读取这些变量的值。 - 未初始化数据段
包含了未进行显式初始化的全局变量和静态变量。程序启动之前,系统
将本段内所有内存初始化为0。出于历史原因,此段常被称为BSS段,这源于老版本的
汇编语言助记符“block started by symbol”o将经过初始化的全局变量和静态变量与未经
初始化的全局变量和静态变量分开存放,其主要原因在于程序在磁盘上存储时,没有必
要为未经初始化的变量分配存储空间。相反,可执行文件只需记录未初始化数据段的位
置及所需大小,直到运行时再由程序加载器来分配这一空间。 - 堆(heap)
是可在运行时(为变量)动态进行内存分配的一块区域盛顶端称作program break。 - 栈( stack)
是一个动态增长和收缩的段,由栈帧(stack frames)组成。系统会为每个
当前调用的函数分配一个栈帧。栈帧中存倍了函数的局部变量(所谓自动变量)、实
参和返回值。
线程的同步机制有哪些?
- 互斥量
- 条件变量
- 自旋锁
自旋锤与互斥量类似,但它不是通过休眠使进程阻塞,而是在获取镪之前一直处于忙等(自
旋)阻塞状态.自旋锁可用于“下情况锁被持有的时间短,而且线程并不希望在重新调度上花
费太多的成本。 - 读写锁(也叫做共享互斥锁)
读写锁也叫做共享互斥锁( shared-exclusive lock)。当读写锁是读模式锁住时,就可以说成是
以共享模式锁住的。当它是写模式锁住的时候,就可以说成是以互斥模式锁住的。
如何避免死锁
总结
- 顺序加锁
- 可以先释放占有的锁,然后过一段时间再试
如果线程试图对同一个互斥量加锁两次,那么它自身就会陷入死锁状态,但是使用互斥量时,
还有其他不太明显的方式也能产牛死锁。例如,程序中使用一个以上的互斥量时,如果允许一个
线程一直占有第一个互斥量,并且在试图锁住第二个互斥量时处于阻塞状态,但是拥有第二个互
斥量的线程也在试图锁住第一个互斥量。因为两个线程都在相互请求对方拥有的资源,所
以这两个线程都无法向前运行,于是就产生死锁。
可以通过仔细控制互斥量加锁的顺序来避免死锁的发生。例如,假设需要对两个互斥量A和
B同时加锁。如果所有线程总是在对互斥量B加锁之前锁住互斥量A即可,那么使用这两个瓦斥量就
不会产生死锁(当然在其他的资源上仍可能出现死锁)。
类似地,如果所有的线程总是在锁住互
斥量A之前锁住互斥量B,那么也不会发生死锁。可能出现的死锁只会发生在一个线程试图锁住
另一个线程以相反的顺序锁住的互斥量。
有时候,应用程序的结构使得对互斥量进行排序是很困难的。如果涉及了太多的锁和数据结
构,可用的函数并不能把它转换成简单的层次,那么就需要采用另外的方法。
在这种情况下,可以先释放占有的锁,然后过一段时间再试。这种情况可以使用pthread_mutex_trylock接口避免
死锁。如果已经占有某些锁而且pthread_mutextrylock接口返回成功,那么就可以前进。但
是,如果不能获取锁,可以先释放已经占有的锁,做好浦理工作,然后过一段时间再重新试。
进程间的同步机制(也就是进程间通信, 能通信就能同步了嘛)有哪些?
博客中 进程间的通信与同步有详细说明
- 管道
- 匿名管道(父子进程间使用)
- 命名管道(无亲缘关系进程间使用)
- FIFO
- 消息队列
- 信号量
- 信号
- 共享内存
- 套接字(本地进程如果用套接字通信, 一般用unix套接字)
linux的任务调度机制是什么?
Linux 分实时进程和普通进程,实时进程应该先于普通进程而运行。
而实时进程的调度机制为:
FIFO(先入先出服务调度)
RR(时间片轮转调度)。