操作系统
目录
3 什么是文件描述符、文件描述符在使用时的原则、文件描述符最大能有多大... 2
4 标准IO中对于文件的访问 r,r+,w,w+,a,a+都是什么意思... 2
11、进程间的通信方式有哪些?各自有什么优缺点?哪种方法效率最高?... 5
18、什么是线程互斥与同步?一般用什么方式实现互斥与同步?... 9
26、什么是TCP/IP、UDP、socket?... 11
27、TCP/ IP 协议的四层结构:应用层,传输层,网络层、设备驱动和硬件层... 11
1 文件IO和标准IO的区别
- 文件IO是Linux系统调用(内核API),而标准IO是C语言库函数;
- 文件IO不带缓冲,标准IO带有缓
- 文件IO操作的是文件描述符,标准IO操作的是流FILE
- 文件IO和标准IO所使用的的函数名不同
系统IO和标准IO的区别
- 标准IO 是系统IO的包装,在标准IO的实现中,实际上调用了系统IO提供的函数。
- 标准IO只能处理普通文件( 文本文件,二进制文件)
系统IO不仅可以处理普通文件,还可以处理设备文件,网络文件。
2 什么是流?、你如何理解标准IO中的流
-
-
- 输入输出的过程。
- 数据的流动,数据是没有边界的 Linux对于流的操作称为IO操作
-
3 什么是文件描述符、文件描述符在使用时的原则、文件描述符最大能有多大
ulimit –n
①是一种访问文件的方式②一般遵循最小分配原则③用于标识正在运行程序所访问的文件
4 标准IO中对于文件的访问 r,r+,w,w+,a,a+都是什么意思
r 以只读的方式打开文件,打开后光标在文件头的位置 如果文件不存在,返回错误 文件存在,返回FILE类型的指针
r+ 读写
rt+ 不覆盖的写入
w 只写 文件存在:清空文件内容,指针在文件头的位置 不存在:会创建文件
w+ 读写
a 以追加的方式打开文件,打开之后,文件的指针在末尾 文件不存在:会创建文件
a+ 以追加 读写 的方式打开
返回值: FILE* 的类型
打开成功:返回一个 FILE* 的指针
打开失败:返回NULL,会设置 errno 的全局变量
5、4种常见的IO模型
1. 阻塞型IO:最常见,最简单,效率最低
对读来说,有数据读,就直接返回, 没有数据,就等待(阻塞)
对写来说,有空间可写,就直接返回,没有空间,就等待(阻塞)
2. 非阻塞IO:
对于读来说, 有数据读,就返回, 没有数据读,直接返回 一个错误码 : open("fifo", O_NONBLOCK,) 反正就是 不等待。
对于写来说, 有空间可写,就返回,不可写(如空间不够了),直接返回一个错误码。
非阻塞的IO: 如果一定要读到数据,则需要一个循环。
3. IO多路复用: 允许同时对多个 IO 进行监控。
4. 异步通知(信号驱动IO)
6 IO多路复用是什么?作用?
核心思想就是利用一组资源做很多件事,IO多路复用是指使用一个线程来检查多个文件描述符(Socket)的就绪状态,比如调用select和poll函数,传入多个文件描述符,如果有一个文件描述符就绪,则返回,否则阻塞直到超时。
作用是:应用程序通过IO复用函数向内核注册一组事件,内核通过IO复用函数把其中的就绪事件通知给应用程序。
7. 操作系统中程序的内存结构
.text : 代码段 :主要存放代码 只读且共享,这段内存在程序运行期间不会释放
.data : 数据段(已经初始化的数据) 存放 已初始化 的全局变量,和已初始化 的 static变量 可读可写,这段内存在程序运行期间一直存在,不会释放
.bss : 数据段(未初始化的数据) 主要存放 未初始化 的全局变量,和 未初始化 的 static变量 可读可写,这段内存在程序运行期间一直存在,不会释放
可执行程序在运行时又多出两个区域:栈区和堆区。
栈区 stack: 主要存放局部变量 可读可写,这段空间会自动释放(代码块执行完了,代码块中的局部变量的空间会自动释放)
堆区 heap: 主要存放 malloc / realloc 动态分配的空间 可读可写,这段内存在程序运行期间 一旦分配,一直存在,直到手动 free
8、 fork 和 vfork 的区别
Fork:创建一个和当前进程映像一样的进程可以通过 fork( )系统调用:
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
成功调用 fork( )会创建一个新的进程,它几乎与调用 fork( )的进程一模一样,这两个进程都会继续运行。
在子进程中,成功的 fork( )调用会返回 0。Pid=0;
在父进程中 fork( )返回子进程的pid。如果出现错误,fork( )返回一个负值
- fork():无参数,资源全部复制,父进程所有的资源都全部通过数据结构的复制,传递给子进程。
- vfork():无参数,除了task_struct结构和系统空间堆栈外,其他的资源全部通过数据结构指针的方式进行复制遗传,所以vfork()出来的是线程而不是进程。
- fork与vfork都可以创建一个进程,但vfork是由fork封装得来的。
9、进程状态转换
正在上传…重新上传取消
1) 创建状态:进程正在被创建
2) 就绪状态:进程被加入到就绪队列中等待 CPU 调度运行
3) 执行状态:进程正在被运行
4) 等待阻塞状态:进程因为某种原因,比如等待I/O,等待设备,而暂时不能运行。
5) 终止状态:进程运行完毕
10、进程和程序有什么区别
进程是对运行时程序的封装,是系统进行资源调度和分配的的基本单位,实现了操作系统的 并发;
进程的状态:就绪态,运行态。阻塞态(等待)
- 程序是静态的,存放不动;进程是动态的,是运行着的程序
- 程序在磁盘中,进程在内存中运行
- 进程 = 程序 + PCB(进程控制块)+ 时间片
11、进程间的通信方式有哪些?各自有什么优缺点?哪种方法效率最高?
进程间通信主要包括管道(有名,无名)、系统 IPC(包括消息队列、信号量、信号、共享内存)、套接字 socket。
1、pipe 无名管道
1)它是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端
2)它只能用于具有亲缘关系的进程之间的通信(也是父子进程或兄弟进程)
3)它可以看成是一种特殊的文件,对于它的读写也可以使用普通的 read、write 等函数。但是它不是普通的文件,并不属于其他任何文件系统,并且只存在于内存中。
fifo 有名管道
1) FIFO 可以在任意进程之间交换数据
2) FIFO 有路径名与之相关联,它以一种特殊设备文件形式存在于文件系统中
2、系统IPC:在内核中,建一个数据缓冲区,提供一个操作他的函数接口
3、信号:用于通知某个事件已经发生,除了用于进程间通信外,进程还可以发送信号给进程本身。
常用信号:1)。SIGHUP:用户从终端注销,所有已启动进程都将收到该进程。系统缺省状态下对该信号的处理是终止进程。
(2)SIGINT:程序终止信号。程序运行过程中,按Ctrl+C键将产生该信号。
(3)SIGQUIT:程序退出信号。程序运行过程中,按Ctrl+\键将产生该信号。
(4)SIGBUS和SIGSEGV:进程访问非法地址。
(5)SIGFPE:运算中出现致命错误,如除零操作、数据溢出等。
(6)SIGKILL:用户终止进程执行信号。shell下执行kill -9发送该信号。
(7)SIGTERM:结束进程信号。shell下执行kill 进程pid发送该信号。
(8)SIGALRM:定时器信号。
(9)SIGCLD:子进程退出信号。如果其父进程没有忽略该信号也没有处理该信号,则子进程退出后将形成僵尸进程。
4、消息队列:
基本原理:A 进程要给 B 进程发送消息,A 进程把数据放在对应的消息队列后就可以正常返回了,B 进程需要的时候再去读取数据就可以了
进程间通过消息队列通信,主要是:创建或打开消息队列,添加消息,读取消息和控制消息队列
与管道不同的是,消息队列存放在内核中,只有在内核重启或人工删除时,该消息队列才会被删除
5、信号量:
- 信号量是一个计数器。用于实现进程间的互斥与同步,而不是用于存储进程间通信数据
- 信号量用于进程间同步时,若要在进程间传递数据需要结合共享内存
- 信号量基于操作系统PV操作,程序对信号量的操作都是原子操作
- 支持信号重组
- 6、共享内存:指两个或多个进程共享一个给定的存储区
- 它是一种最快的IPC,应为进程是直接对内存进行存取
如信号量配合使用,来实现进程间的同步和通信
正在上传…重新上传取消
共享内存有2种实现方式:1.内存映射 2.共享内存机制
7、套接字socket: 也是一种进程间通信机制,用于不同主机之间的进程通信。是应用层和传输层之间的桥梁
套接字的特性由3个属性确定,它们分别是:域(一是AF_INET,它指的是Internet网络。另一个域AF_UNIX,表示UNIX文件系统)、端口号、协议类型
12、各种通信方式的优缺点
PIPE管道(无名):速度慢,容量有限,只有父子进程能通讯
FIFO:任何进程间都能通讯,但速度慢
消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题
信号量:不能传递复杂消息,只能用来同步
共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,
13、共享内存和内存映射的区别与用途
共享内存,顾名思义,就是预留出的内存区域,它允许一组进程对其访问。 共享内存是system v IPC中三种通信机制最快的一种,也是最简单的一种
内存映射,一般指的是为了加快文件操作,将文件系统上某个文件的一段内容映射到内存中,用户可以在核外地址空间直接读写内核地址空间的地址对应的内容,这样进程在读写文件时,少了一次拷贝开销。这个一般是用在一个进程内的。
用途:sharedMemory用于多个进程共享同一块地址空间,实现多个人访问同一个区域,目的是共享。mmap内存映射的目的是加快访问速度。这两个并不冲突,所以可以组合到一起使用。
14、介绍一下 正常进程,孤儿进程,僵尸进程
正常进程
正常情况下,子进程是通过父进程创建的,子进程再创建新的进程。子进程的结束和父进程的运行是一个异步过程,即父进程永远无法预测子进程到底什么时候结束。 当一个进程完成它的工作终止之后,它的父进程需要调用 wait()或者 waitpid()系统调用取得子进程的终止状态。
Unix提供了一种机制可以保证只要父进程想知道子进程结束时的状态信息, 就可以得到:在每个进程退出的时候,内核释放该进程所有的资源,包括打开的文件,占用的内存等。 但是仍然为其保留一定的信息,直到父进程通过 wait / waitpid 来取时才释放。保存信息包括:
1 进程号 the process ID
2 退出状态 the termination status of the process
3 运行时间 the amount of CPU time taken by the process 等
孤儿进程
个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进 程将被 init 进程(进程号为 1)所收养,并由 init 进程对它们完成状态收集工作
僵尸进程
一个进程使用 fork 创建子进程,如果子进程退出,而父进程并没有调用wait 或 waitpid 获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵尸进程
僵尸进程是一个进程必然会经过的过程:这是每个子进程在结束时都要经过的阶段。
15、线程的概念?特点?
1. 线程是比进程更小的活动单位,它是进程的一个执行路径(执行分支)。
2. 线程同进程内其他的线程 共享进程的地址空间。
特点:
1.创建一个线程 比 创建一个进程开销小得多。 1/30 的开销。
2. 实现线程间通信十分方便,因为 一个进程创建多个线程直接共享进程的内存区域。
3. 线程是一个动态的概念。进程内部的一个执行单位, C语言指令必须在函数内部 ===> 线程 对应 一个函数(线程函数)
线程的主要工作就是去执行那个 线程函数。如果线程函数执行完了,那么线程就完了。
4. 在进程内 创建多个 线程函数。 可以提高系统的并行处理能力, 加快进程的处理速度。
迅雷下载:开多个线程同时下载一个文件。
5. 进程默认会有一个主线程(main函数), 在进程运行过程中 可以创建其他的线程。
线程是CPU调度的最小单位
16、线程出现的原因
进程可以使多个程序能并发执行,以提高资源的利用率和系统的吞吐量;但是其具有一些缺点:
进程在同一时间只能干一件事,
进程在执行的过程中如果阻塞,整个进程就会挂起,即使进程中有些工作不依赖于等待的资源, 仍然不会执行
因此,操作系统引入了比进程粒度更小的线程,作为并发执行的基本单位,从而减少程序在并发执行时所付出的时空开销,提高并发性。
17. 线程间的通信方式有哪些
线程间通信有两种情况:1. 一个进程中的线程与另一个进程中的线程通信 2. 同一个进程中的两个线程进行通信
线程安全:多线程访问同一段代码不会产生不确定的结果
线程同步:当一个线程可以修改变量,其他线程也可以读取或修改的时候,需要对这些线程进行同步,确保访问变量的存储内容时不会访问到无效的值
- 锁机制(互斥):互斥锁、条件变量、读写锁
互斥锁提供了以排他方式防止数据结构被并发修改
读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
条件变量可以阻塞进程,直到某个特定条件为真为止。对条件的测试是在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用
- 信号量机制:无名线程信号量、命名线程信号量
线程信号量和进程类似
3. 信号机制:类似进程间的信号处理 同步
4. 条件变量:线程的另一种同步机制。互斥量用于上锁,条件变量用于等待。同步
18、什么是线程互斥与同步?一般用什么方式实现互斥与同步?
互斥:某一资源,同时只允许一个访问者对其访问,具有唯一性和排他性。但访问是无序的
同步:线程同步并不是说线程同时运行,而是让线程按照一定的顺序执行,使得最后的数据能达到同步。有序访问
实现同步的方式
1、使用互斥量(Mutex):采用互斥对象机制,只有拥有互斥对象的线程才有访问公共资源的权限。因为互斥对象只有一个,所以可以保证公共资源不会被多个线程同时访问。
2、使用信号量(Semphares) :它允许同一时刻多个线程访问同一资源,但是需要控制同一时刻访问此资源的最大线程数量
19.线程的共享资源以及独立资源
共享资源
- 进程申请的堆内存
- 进程打开的文件描述符
- 进程的全局数据(可用于进程间通信)
- 进程ID 进程组ID
- 进程目录
- 信号处理器
独占资源
- 线程ID
- 寄存器组的值
- 线程堆栈
- 错误返回码
- 信号屏蔽码
- 线程的优先级
20.进程和线程关系与区别
联系:
- 进程包含线程,一个进程中可以有一个或者多个线程。
- 进程和线程都是为了解决并发编程。但线程的效率要高于进程,因为多个线程可以共享一份资源,而进程和进程之间是独立的,进程的创建和销毁是一定需要消耗资源的。
区别:
- 进程是操作系统分配资源的最小单位,线程是操作系统调度的最小单位。
- 进程具有独立性,进程A的崩溃不会影响到进程B的崩溃;在一个进程中的多个线程是共享一份资源的,一个线程的崩溃可能会影响到该进程中其他线程的崩溃,进而导致整个进程崩溃。
3. 进程间的通信需要在内核中进行,而线程因为共享一份资源可以直接进行通信。
21、线程安全的单例模式
单例模式:只有一个实例,并且自己负责创建自己的对象,这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象
- 懒汉式:用到的时候才去创建,“比较懒”,用的时候才去检查有没有实例,如果有则返回,没有则新建。
- 饿汉式:在初始化的时候就已经建好了,不管你有没有用到,都先建好了再说。好处是没有线程安全的问题,坏处是浪费内存空间
22、怎么实现线程池
1.设置一个生产者消费者队列,作为临界资源
2.初始化 n 个线程,并让其运行起来,加锁去队列取任务运行
3.当任务队列为空的时候,所有线程阻塞
4.当生产者队列来了一个任务后,先对队列加锁,把任务挂在到队列上,然后使用条件变量去通知阻塞中的一个线程
23、使用线程池可以带来以下几个好处:
1. 降低资源消耗。通过重复利用已创建的线程,降低线程创建和销毁造成的消耗。
2. 提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
3. 增加线程的可管理型。线程是稀缺资源,使用线程池可以进行统一分配,调优和监控。
24、线程池目前有5个状态:
RUNNING:接受新任务并处理排队的任务。
SHUTDOWN:不接受新任务,但处理排队的任务。
STOP:不接受新任务,不处理排队的任务,并中断正在进行的任务。
TIDYING:所有任务都已终止,workerCount 为零,线程转换到 TIDYING 状态将运行 terminated() 钩子方法。
TERMINATED:terminated() 已完成
25、网络协议层结构
分层: 按功能模块。 工程分为不同的代码块,实现不同的功能。
OSI 七层模型:
应用层 表示层 会话层 传输层 网络层 数据链路层 物理层
26、什么是TCP/IP、UDP、socket?
TCP/IP:传输控制协议、网间协议,是一个工业标准的协议集,是为广域网设计的
UDP:用户数据报协议。是与TCP相对应的协议,属于TCP/IP协议族的一种
Socket:是应用层和传输层中间的抽象层,是一组接口
27、TCP/ IP 协议的四层结构:应用层,传输层,网络层、设备驱动和硬件层
1) 应用层:
网络上的应用程序的 私有协议
2) 传输层:(tcp, udp)
规定数据是怎么传输的
## TCP:transport control protocol 传输控制协议
-
-
-
- 是一种 面向连接 的传输层协议,提供高可靠性
- 通信 (数据无误,无丢失,无失序,无重复)
- 面向连接:发送数据之前,先建立连接。(三次握手)
- 应答机制:接收方在收到数据之后,要应答
-
-
ack:确认包 syn:同步包
- 第一次握手:建立连接时,客户端发送一个 syn(syn = j) 到服务器,并进入 SYN_SENT 状态。 等待服务器确认:SYN 同步序列编号
- 第二次握手:服务器收到了 syn 包,必须确认客户的 SYN(ack = j+1) ,同时自己也发送一个 syn(syn = k) 包,即(ack + syn 包),此时服务器进入SYN_RECV 状态
- 第三次握手: 客户端收到服务器的 ack+syn包,同时向服务器发送一个确认包 ACK(ack = k+1)次包发送完毕,客户端和服务器进入 ESTABLESHED (TCP 连接成功)状态,完成三次握手
- 完成三次握手:客户端和服务端可以传送数据
通俗理解三次握手
A 发送 syn 包:A朝对面人群 微笑
B 发送一个 SYN 包(B朝A 微笑) ,并且发送一个 ack包(挥手)
A 发送一个 ACK 包(挥手)
A B 建立 TCP连接, 传输数据(对话)
## UDP :user datagram protocol 用户数据包协议
是不可靠的无连接协议
"不需要连接","不需要应答机制"
==>高效的数据传输,数据有可能丢失,可能有误,失序,重复(发信件)
实时网络应用:丢了就丢了
3) 网络层
(ip, icmp, igmp)intrnet 组管理协议称为 IGMP 协议
IGMP 协议:internet Control Message protocol : internet 控制报文协议
它是TCP/IP 的一个子协议,用于 IP主机,路由器之间传递 控制信息。
控制信息是指网络通不通,主机是否到达,路由是否可用等网络本身的消息
IP 协议:ipv4 ,ipv6
通过给网络上的每台主机一个 虚拟的id,用来表示者台主机
虚拟的id: ip地址
发送方 ip, 接收方 ip
4) 设备驱动和硬件层
网卡, mac地址: 网卡的物理地址是全世界唯一的
28、TCP 与UDP 的区别
1.TCP是面向对象连接;而UDP是无面向对象连接
2.TCP确保所传输的数据一定会到达目的地,但时间却不能保证;而UDP不确保数据会按原来顺序到达,但具有实时性
3.TCP的使用场景是不在意传输数据速度,但在意传输数据准确;而UDP的使用场景则是对实时性要求较高
4.TCP的首部开销大,占用20字节;而UDP的首部开销小,只占用8个字节
5.TCP只支持点对点的数据传输;而UDP支持一对一、一对多、多对多等各种场景
6.TCP有拥塞控制和流量控制来确保数据的安全性,但如果网络拥塞的话,速度会比较慢;UDP即使在网络拥塞的时候,传输速度也不会慢
29、socket编程的API函数中的TCP流程
服务器:创建套接字-填充服务器地址信息-绑定-侦听-接受连接请求-数据收发-关闭
客户端:创建套接字-填充服务器地址信息-连接-数据收发-关闭
TCP server:服务器的流程
1. server:创建一个套接字
2. bind:为套接字指定一个地址(IP地址 + port号) ip:32位 4字节 port:2字节
如果不调用 bind(也会有一个 IP+port,只不过是内核分配的)
作为TCP服务端。必须绑定一个"众所周知"的端口号,好让客户连接
- listen: 要套接字进入一个 监听 模式(查看有什么客户连接我)
4. accept: 接收从客户端发起的连接请求。(阻塞函数)
发送数据: write/ send/ sendto
接收数据: read/ recv/ recvfrom
5.关闭连接:close
shutdown
TCP client:客户端流程
1. socket:创建套接字,返回一个特殊的文件描述符
你不主动的bind, 你的 socket 也会有一个 地址+端口号。
这个地址是 内核自动分配给你的。 只要你 socket 就一定会有一个 地址。
2. connect : 连接服务器
发送数据: write / send/ sendto
接收数据: read / recv / recvfrom
关闭连接:close
Hutdown
30、三次握手,四次挥手
三次握手:
- 客户端发送 syn 服务端接收 (syn_recv)
- 服务端发送 ack 客户端接收
- 客户端发送 ack 服务端接收 连接成功
四次挥手:TCP 的连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),客户端或服务器均可主动发起挥手动作
1. 客户端 发送 FIN 报文,报文指定一个序列号(FIN=1, seq=u)
2. 服务端 接收FIN,发送 ACK(Ack=1,确认号ack=u+1, 序号 seq=V) 服务端: CLOSE_WAIT 状态
3. 若服务端想断开,类似客户端第一次挥手,发送FIN,指定一个序列号(FIN=1,ACK=1,seq=w, 确认号ack=u+1) 服务端: LAST_ACK (最后确认)状态
4. 客户端接收FIN,发送ACK(ACK=1,seq=u+1,确认好ack=w+1) 客户端:TIME_WAIT(时间等待)状态。 等待服务器接收到 ACK后进入 CLOSED 状态
31、TCP怎么保证可靠性
- 校验和
发送的数据包的二进制相加,且前面的进位不丢弃,补在后面,最后取反。目的是检测数据在传输过程中的任何变化
- 确认应答+序列号
TCP给发送的每一个包进行编号,接收方对数据包进行排序,把有序数据传给应用层
- 超时重传
TCP发出一个段后,会启动一个定时器,等待目的端确认收到这个报文段。如果不能及时确认,重新发送
- 流量控制
TCP连接的每一方都有 固定大小的缓冲空间。Tcp的接收端只允许发送端 发送 接收端缓冲区 可以接纳的数据。如果接收方来不及处理发送方的数据,能提示对方降低发送速率,防止包丢失。
TCP使用的流量控制协议是可变大小的滑动窗口协议。
即接收方有滑动窗口,随ACK报文发送
- 拥塞控制
网络阻塞时,减少数据的发送
TCP接收端会丢弃重复的数据
慢启动、拥塞避免、拥塞发送、快速恢复
相较于UDP,TCP有以下区别:
- 可靠传输 2. 流量控制
这两个功能都是依靠滑动窗口来实现的
滑动窗口:只要处于发送窗口范围中的数据包都可以被发送,不需要等待前面数据包的ack包。
32、UDP怎么实现有序传输
UDP不属于连接协议,具有资源消耗少,处理速度快的优点。
传输层无法保证数据的可靠传输,只能通过应用层实现。实现的方式仿照tcp可靠性传输的方式,只是实现不在传输层,实现转移到了应用层。
即在应用层模仿tcp的可靠性传输
- 添加 seq/ack 机制,确保数据发送到对端
- 添加发送和接收缓冲区,主要是用户 超时重传
- 添加超时重传机制