Skip to content

Latest commit

 

History

History
77 lines (59 loc) · 6.17 KB

README.md

File metadata and controls

77 lines (59 loc) · 6.17 KB

Linux 基础知识

知识列表

零散知识点

  • linux内核锁有:原子锁,自旋锁和信号量
  • 内核调度时机有自愿调度和非自愿调度,自愿调度表示调用exit,sleep函数什么的,非自愿表示时间片用完
  • linux申请内存的方式有:malloc, calloc, realloc, kmalloc, vmalloc (kmalloc保证分配的内存在物理上是连续的,vmalloc保证的是在虚拟地址空间上的连续)
  • 登录linux,首先启动/etc/profile,然后启动用户目录下的.bash_profile, .bash_login和.profile中的一个, 如果是.bash_profile的话还会执行bashrc; 每次启动shell终端的时候都会调用/etc/bashrc和~/.bashrc文件

GDB常见指令

file:加载, r:运行, c:继续, b[行号]:设置断点, d:删除断点, s:下一步, n:下一行, p:打印变量值, i:显示各类信息, q:退出

IO复用的方法

select, poll, epoll都是IO多路复用的机制,所谓的IO多路复用机制就是通过一种机制可以见识多个描述符,一旦某个描述符就绪能通过程序进行相应的读写操作。 select和poll的实现机制类似,只是描述fd集合的方式不一样,poll使用pollfd,select使用fd_set;epoll算是select和poll的加强版。 select有三个缺点:

  1. 每次调用select时需要将fd集合从用户态拷贝到内核态,开销大
  2. select每次判断就绪都需要在内核态遍历所有传递进来的的fd,造成开销大
  3. 支持的文件描述符少,默认为1024

epoll有epoll_create, epoll_ctl, epoll_wait可以避免select的缺点,描述如下:

  1. epoll会在使用epoll_ctl注册事件时将fd拷贝到内核态,可以避免缺点一
  2. epool在设备就绪时会将就绪的fd加入到就绪链表中,可以避免每次查询所有的fd

高并发服务器的设计模式

单进程服务,使用非阻塞io

使用一个进程服务多个客户,通常与客户通信的套接字设置为非阻塞的,阻塞只发生在select()、poll()、epoll_wait()等系统调用上面。缺点是无法利用对称多处理器的优势;select的描述符集个数有限制;会进行大量的系统调用。

多进程服务,使用阻塞io

accept/fork 模型,每当有客户连线时产生一个新的进程为之服务,缺点是进程占用资源多,进程切换开销太大,进程信息共享麻烦。

多线程服务,使用阻塞io

accept/pthread_create模型,有新客户来时创建一个服务线程而不是服务进程。这解决了多进程服务的一些问题,比如它占用资源少,信息共享方便。但是麻烦在于线程仍有可能消耗光,线程切换也需要开销。

消息队列的实现机制,请求过多怎么处理?

消息队列可用在应用中以执行多种功能,比如要求服务、交换信息或异步处理等。中间件是一种独立的系统软件或服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源. 下面为个人理解: 消息队列的实现可以转化为生产者-消费者模型,可以通过STL的dqueue + 信号量等实现,可以在消息中增加超时时间戳以应对请求过多的问题。

线程如何实现同步,进程如何实现通信?

  • **线程:**互斥锁,读写锁,条件变量,信号量
  • **进程:**管道,有名管道,信号,信号量,消息队列,共享内存,套接字, "文件与记录锁"

进程间切换的步骤:

进程切换需要切换虚拟空间、内核栈、cpu寄存器、内核空间的切换。

  1. 保存程序计数其以及其他寄存器。
  2. 更新当前处于“运行态”的进程的进程控制块,把进程状态改为相应状态,更新其他相关域
  3. 把被切换进程的进程控制块移到相关状态的队列
  4. 选择另外一个进程开始执行,把该进程进程控制块的状态改为“运行态”
  5. 恢复被选择进程的处理器在最近一次被切换出运行态时的上下文,比如载入程序计数器以及其他处理器的值
  6. 进程间切换伴随着两次模式切换(用户--内核,内核--用户)

线程间切换的步骤:

线程分两种,用户级线程和内核级线程:

  • 在用户级线程中,有关线程管理的所有工作都由应用程序完成,内核没有意识到线程的存在,用户级线程间切换时,只需要保存用户寄存器的内容,程序计数器,栈指针,不需要模式切换。在进程的某个线程执行系统调用时,不仅该线程被阻塞,该线程所在进程的所有线程都被阻塞,无法利用多处理器
  • 在内核级线程中,有关线程的管理工作都是由内核完成的,应用程序部分没有线程管理的权限,内核级线程间切换时,除了保存上下文,还要进行模式切换。可以利用多处理器,线程阻塞不会导致进程阻塞

fork之后子进程独有的有哪些内容?

  1. 不同的父进程号(译者注:即子进程的父进程号与父进程的父进程号不同, 父进程号可由getppid函数得到)
  2. 自己的文件描述符和目录流的拷贝(译者注:目录流由opendir函数创建,因其为顺序读取,顾称“目录流”)
  3. 子进程不继承父进程的进程,正文(text), 数据和其它锁定内存(memory locks)(译者注:锁定内存指被锁定的虚拟内存页,锁定后,不允许内核将其在必要时换出(page out))
  4. 在tms结构中的系统时间(译者注:tms结构可由times函数获得,它保存四个数据用于记录进程使用中央处理器的时间,包括:用户时间,系统时间, 用户各子进程合计时间,系统各子进程合计时间)
  5. 资源使用(resource utilizations)设定为0
  6. 阻塞信号集初始化为空集(译者注:原文此处不明确,译文根据fork函数手册页稍做修改)
  7. 不继承由timer_create函数创建的计时器
  8. 不继承异步输入和输出

互斥量与临界区的区别?

  1. Mutexes 操作要比 Critical Section 费时的多。
  2. Mutexes 可以跨进程使用,Critical Section 则只能在同一进程中使用。
  3. 等待一个 Mutex 时,你可以指定"结束等待"的时间长度,而 Critical Section 则不行。