零散笔记(二)

IO多路复用

IO多路复用是指内核一旦发现进程指定的一个或者多个IO条件准备读取,它就通知该进程。

select,poll,epoll都是IO多路复用的机制。I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪,能够通知程序进行相应的读写操作。但select,poll,epoll本质上都是同步I/O,因为他们都需要在读写事件就绪后自己负责进行读写,也就是说这个读写过程是阻塞的,而异步I/O则无需自己负责进行读写,异步I/O的实现会负责把数据从内核拷贝到用户空间。

select的几大缺点:

(1)每次调用select,都需要把fd集合从用户态拷贝到内核态,这个开销在fd很多时会很大

(2)同时每次调用select都需要在内核遍历传递进来的所有fd,这个开销在fd很多时也很大

(3)select支持的文件描述符数量太小了,默认是1024

poll的机制与select类似,与select在本质上没有多大差别,管理多个描述符也是进行轮询,根据描述符的状态进行处理,但是poll没有最大文件描述符数量的限制。

epoll可以避免select的三个缺点。epoll提供了三个函数,epoll_create,epoll_ctl和epoll_wait,epoll_create是创建一个epoll句柄;epoll_ctl是注册要监听的事件类型;epoll_wait则是等待事件的产生。

对于第一个缺点,epoll的解决方案在epoll_ctl函数中。每次注册新的事件到epoll句柄中时,会把所有的fd拷贝进内核,而不是在epoll_wait的时候重复拷贝。epoll保证了每个fd在整个过程中只会拷贝一次。

对于第二个缺点,epoll的解决方案不像select或poll一样每次都把current轮流加入fd对应的设备等待队列中,而只在epoll_ctl时把current挂一遍并为每个fd指定一个回调函数,当设备就绪,唤醒等待队列上的等待者时,就会调用这个回调函数,而这个回调函数会把就绪的fd加入一个就绪链表。epoll_wait的工作实际上就是在这个就绪链表中查看有没有就绪的fd。epoll_wait也是轮询,但是轮询的数量变少了。

对于第三个缺点,epoll没有这个限制,它所支持的FD上限是最大可以打开文件的数目,这个数字一般远大于2048,具体数目可以cat /proc/sys/fs/file-max查看,一般来说这个数目和系统内存关系很大。

常见的设计模式

单例模式

主要解决一个全局使用的类的创建和销毁问题。频繁的创建和销毁会导致性能低下。三个要素,一是一个类只能有一个实例,二是它必须自行创建这个实例,三是它必须自行向系统提供这个实例。

工厂模式

工厂模式主要解决接口选择的问题。该模式下定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,使其创建过程延迟到子类进行。

观察者模式

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。

装饰器模式

对已经存在的某些类进行装饰,以此来扩展一些功能,从而动态的为一个对象增加新的功能。装饰器模式是一种用于代替继承的技术,无需通过继承增加子类就能扩展对象的新功能。使用对象的关联关系代替继承关系,更加灵活,同时避免类型体系的快速膨胀。

如何保证单例模式只有一个实例

将类的构造函数设置为private,这样子外部就无法调用构造函数来实例化对象。同时类提供一个静态方法,返回的是类的引用。当静态方法被调用时,如果引用为空则实例化一个新的对象,引用不为空则直接返回。

工厂模式的优点

解耦,代码复用,更改功能容易

C++中map和set的区别

底层实现都是红黑树。

map中元素是key-value,key是索引。set中就只有key。

set中迭代器是const的,不允许修改key的值;map也不能修改key的值,但是可以修改value的值。

map有[]操作符,set没有。如果map使用[]时key不存在,会插入一个新的key-value,其中value会调用默认构造函数。

C++迭代器删除元素

对于vector和deque来说,erase(it)后迭代器会失效,该元素之后的元素会往前移,他们的迭代器也会失效,但erase会返回下一个有效的迭代器。

对于map和set来说,erase后当前迭代器会失效,但后面元素的迭代器不会失效,因为使用的是树形结构,所以记录下一个元素的迭代器即可。

对于list来说,后面元素会前移,但是迭代器不会失效,因为使用的是不连续的内存。

C++ STL中resize和reserve的区别

resize是改变容器元素的数量(size)。扩充时,元素的值是默认值。缩小时,后面的元素直接被丢弃。

reserve是改变容器的最大容量(capacity)。如果reserve的值大于当前的capacity,则会重新分配内存,把当前的内存复制过去,然后销毁原来的内存。

发表评论

电子邮件地址不会被公开。 必填项已用*标注