前言

操作系统为编程语言提供了一系列的系统调用,使得用户程序可以间接地控制内核。此外,本文还涉及进程和线程的相关问题,

孤儿进程和僵尸进程

  • 僵尸进程:子进程先与父进程退出,但是父进程没有对子进程进行等待,导致无法获取子进程的退出状态信息,操作系统无法释放子进程资源,子进程变成僵尸进程。
  • 孤儿进程:父进程先于子进程退出,子进程变成孤儿进程,孤儿进程的父进程成为1号进程。
  • 如何处理僵尸进程:子进程退出时,向父进程发出SIGCHILD信号,父进程处理SIGCHILD信号,在信号处理函数中调用wait进程处理。

fork和vfork的区别

fork创建出来的子进程拷贝父进程的大部分资源,也有自己的虚拟地址空间,而vfork创建的子进程与父进程共享数据段。

fork的父子进程的执行顺序不确定,vfork保证子进程先运行,子进程退出后父进程才能运行。

多线程和多进程的优缺点

多线程之间共享一个进程的地址空间,线程间通信简单,线程的创建和销毁都比多进程简单,速度快,占用内存少,但是线程会互相影响,一个线程的崩溃可能会导致其他线程的终止,可靠性差。

多进程中每个进程各自有自己的虚拟地址空间,进程间不会相互影响,可靠性强,但是进程间通信复杂,进程的创建销毁复杂,占用内存多。

多线程适用于IO密集型程序,多进程适用于CPU密集型程序。

重定向

通过改变原本文件的文件描述符对应的文件描述信息,从而导致改变数据的流向,数据不再写入原本的文件而是写入新指定的文件。

软硬链接

  • 硬链接通过ln创建,硬链接文件和源文件共用一个inode节点,也就是说硬链接只是源文件的一个别名
  • 软链接通过ln -s创建,有自己独立的inode节点,是一个新的文件,这个文件的内容保存了一个文件的路径名
  • 软链接可以跨分区链接,硬链接无法跨分区链接。

如何判断大端小端

大端指的是低地址存储数据高位,小端指的是地地址存储数据的低位。

string BigOrLit(){union{int i;char c;}un;un.i=1;if(un.c)return "小端";elsereturn "大端";}

生产者和消费者模型

生产者和消费者模型常用于大量数据的产生与处理场景。通过一个缓冲队列实现的。开启一个或多个线程来生产任务,生产的任务放到缓冲队列中,再开启一个或多个线程从缓冲队列中取出任务并进行处理,这样降低了生产者和消费者之间的耦合性。

同步问题:生产者和消费者访问缓冲队列的时候都需要加锁,另外需要使用条件变量,生产者添加任务的时候发出信号唤醒等待中的消费者,消费者在消耗任务前需要等待信号。

有哪些锁

  • 互斥锁:当一个线程占据这个锁后,其他线程向加锁就会加锁失败并被阻塞,适用于加锁部分执行时间长的场景。
  • 自旋锁:任何擦黄女士获取该锁的线程会一直进行自旋,占用cpu的资源,知道获取该锁,同一时间只能有一个线程获取该锁,适用于加锁部分执行时间短的场景。
  • 读写锁:当没有线程有写锁时,读锁能被多个线程并发持有,提高资源利用率,且无线程安全问题。写锁是任何一个线程持有写锁时,其他线程获取读锁或写锁都会被阻塞。

5种IO模型

  • 阻塞IO:当进行IO请求调用时,由于请求的条件不满足,就会一直阻塞等待。
  • 非阻塞IO:当发起IO请求调用时,会每隔一段时间检测IO时间是否就绪,没有就做其他事情。
  • 信号驱动IO:通过定义信号处理函数,当进程收到SIGIO信号,就表示IO就绪,进程就会处理IO事件
  • 异步IO:将IO操作交给操作系统,做其他操作,操作系统完成IO操作后用信号通知程序IO就绪。
  • IO复用:同一时间对大量描述符进行IO事件监听,知道有IO就绪事件后才调用IO操作函数。

后记

别露出你的怯懦,别犹豫哪怕一分一秒,这里已无路可退,唯有浴血!