导图社区 知识点补充
这是一篇关于菜鸟程序员知识点补充的思维导图
提示: 本内容由社区用户上传并分享。平台不对内容的真实性、合法性、知识产权归属及是否侵害第三方权利进行事前审核或保证。本内容可能包含受版权保护的图片、字体或其他第三方素材,使用前请自行确认授权范围。
知识点补充
回调函数
应用层的函数A调底层的函数B,顺便把应用层的函数C当参数传给B,而B在底层执行的时候,需要回到应用层调用C,这个过程就叫回调,而函数C就是回调函数。
乙需要用到甲提供的接口,那么,甲的接口函数给到乙的这个过程就叫注册回调函数。注册的方式主要为两种,一种是独立出注册函数,另一种是直接在参数中接收
死锁与线程同步
死锁
产生死锁的四个必要条件
互斥条件:一个资源一次只能被一个进程使用。
请求与保持条件: 进程已经保持了至少一个资源,又提出了新的资源请求,而该资源已经被其他进程占有。此时请求进程被阻塞,而对自己已获得的资源保持不放。
不可剥夺条件:进程所获得的资源在未使用完之前,不能被其他进程强行夺走,即只能由进程自己主动释放。
循环等待条件:若干进程间形成首尾相接循环等待资源的关系。
死锁产生的主要原因
系统资源竞争:资源分配不当,以及系统资源的竞争导致系统资源不足,导致死锁;
进程运行推进顺序不合适:进程在运行过程中,请求和释放资源的顺序不当,导致死锁。
同步
互斥锁
(1) 首先申请互斥锁,如果该互斥锁处于锁定状态,默认阻塞当前线程;如果处于解锁状态,则申请到该锁并立即占有该锁,使锁处于锁定状态防止其他线程访问该资源。 (2) 只有锁定该互斥锁的线程才能释放该互斥锁,其他线程试图释放操作无效。
条件变量
条件变量不能单独使用,必须配合互斥锁一起实现对资源的互斥访问。
条件变量主要包括两个动作:一个线程等待”条件变量的条件成立”而挂起;另一个线程使”条件成立”(给出条件成立信号)。
读写锁
适合于对数据结构读的次数远大于写的情况
读写锁可以有三种状态:读模式下加锁状态;写模式下加锁状态;不加锁状态
读模式:当读写锁在读模式下时,只要线程获取了读模式下的读写锁,该锁所保护的数据结构可以被多个获得读模式锁的线程读取。
写模式:当读写锁在写模式下时,它所保护的数据结构就可以被安全地修改,因为当前只有一个线程可以在写模式下拥有这个锁。
进程间通信
常见的通信方式
1.管道pipe:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间使用。进程的亲缘关系通常是指父子进程关系。
2.命名管道FIFO:有名管道也是半双工的通信方式,但是它允许无亲缘关系进程间的通信。
3.消息队列MessageQueue:消息队列是由消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
4.共享存储SharedMemory:共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运行效率低而专门设计的。它往往与其他通信机制,如信号量,配合使用,来实现进程间的同步和通信。
5.信号量Semaphore:信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段。
6.套接字Socket:套解口也是一种进程间通信机制,与其他通信机制不同的是,它可用于不同及其间的进程通信。
7.信号 ( sinal ) : 信号是一种比较复杂的通信方式,用于通知接收进程某个事件已经发生。
无名管道
1.是半双工的(即数据只能在一个方向上流动),具有固定的读端和写端。
2.只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)
3.管道的实质是一个内核缓冲区,进程以先进先出的方式从缓冲区存取数据:
4.代码例子: 父进程创建管道,并在管道中写入数据,而子进程从管道读出数据
pipe函数,创建管道
调用fork函数,复制进程
read
write
close
命名管道
内容:和无名管道的主要区别在于,命名管道有一个名字,命名管道的名字对应于一个磁盘索引节点,有了这个文件名,任何进程有相应的权限都可以对它进行访问。
创建:mknod()或makefifo()来创建一个命名管道
用select把,管道描述符和stdin假如集合,用select进行阻塞,如果有i/o的时候唤醒进程
消息队列
意义:消息队列,就是一个消息的链表,是一系列保存在内核中消息的列表。用户进程可以向消息队列添加消息,也可以向消息队列读取消息。
与管道通信相比:其优势是对每个消息指定特定的消息类型,接收的时候不需要按照队列次序,而是可以根据自定义条件接收特定类型的消息。
消息队列的常用函数:
ftok:由文件路径工程ID生成标准key
msgget:创建或者打开消息队列
msgsnd:添加消息
msgrcv:读取消息
msgctl:控制消息队列
共享内存
原理:共享内存允许两个或多个进程共享一个给定的存储区,这一段存储区可以被两个或两个以上的进程映射至自身的地址空间中,一个进程写入共享内存的信息,可以被其他使用这个共享内存的进程,通过一个简单的内存读取错做读出,从而实现了进程间的通信
作用:采用共享内存进行通信的一个主要好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝,对于像管道和消息队里等通信方式,则需要再内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次:一次从输入文件到共享内存区,另一次从共享内存到输出文件。
常用函数:
信号量
特点
信号量用于进程间同步,若要在进程间传递数据需要结合共享内存。
信号量基于操作系统的 PV 操作,程序对信号量的操作都是原子操作。
每次对信号量的 PV 操作不仅限于对信号量值加 1 或减 1,而且可以加减任意正整数。
支持信号量组。
TCP协议
三次握手
第一次握手:建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
三次握手的抓包分析
子主题
四次挥手
1)客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
2)服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
3)客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
4)服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
5)客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
6)服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。