malloc源码解析
malloc源码解析
glibc2.35
内部结构heap/* A heap is a single contiguous memory region holding (coalesceable) malloc_chunks. It is allocated with mmap() and always starts at an address aligned to HEAP_MAX_SIZE. */typedef struct _heap_info{ mstate ar_ptr; /* Arena for this heap. */ struct _heap_info *prev; /* Previous heap. */ size_t size; /* Current size in bytes. */ size_t mprotect_size; /* Size in bytes that has been mprotected PROT_READ|PROT_WRITE. */ size_t ...
内存管理
内存管理new expression
_callnewh是用户设定的无法分配内存时的动作
Complex* pc = new Complex(1,2);// 编译器转化Complex*pc;try { void* mem = operator new(sizeof(Complex)); pc = static_cast<Complex*>(mem); pc->Complex::Complex(1,2);} catch (std::bad_alloc) { }void* operator new(size_t size, const std::nothrow_t& _THROW0()) { void*p; while((p = malloc(size)) == 0) { _TRY_BEGIN if(_callnewh(size) == 0) break; _CATCH(std::bad_alloc) return(0 ...
The Senmantics of Data
The Senmantics of Data类大小的计算
类大小的计算,遵循结构体的对齐原则;
类的大小,与普通数据成员有关,与成员函数和静态成员无关。即普通成员函数、静态成员函数、静态数据成员、静态常量数据成员,均对类的大小无影响;
虚函数对类的大小有影响,是因为虚函数表指针带来的影响;
虚继承对类的大小有影响,是因为虚基表指针带来的影响;
静态数据成员之所以不计算在类的对象大小内,是因为类的静态数据成员被该类所有的对象所共享,并不属于具体哪个对象,静态数据成员定义在内存的全局区;
空类大小
C++的空类是指这个类不带任何数据,即类中没有非静态(non-static)数据成员变量,没有虚函数(virtual function),也没有虚基类(virtual base class)。
C++标准指出,不允许一个对象(当然包括类对象)的大小为0,不同的对象不能具有相同的地址。
new需要分配不同的内存地址,不能分配内存大小为0的空间;
避免除以 sizeof(T)时得到除以0错误;
计算结果1。
第一种情况,空类的继承:当派生类继承空类后,派生类如果有自己的数据成员,而空基类的一个 ...
The Senmantics of Constructors
The Senmantics of ConstructorsDefault ConstructorMember Class Object has Default Constructor
一个class中没有constructor,但是其中的member object有一个default constructor;编译器会为该class合成一个default constructor;但是会推迟到该constructor被调用时发生
class Foo{ public: Foo(); Foo(int); //...};class Bar{ public: Foo foo; char*str; //...};void foo_bar() { Bar bar; // 编译器合成一个default constructor if(str){}}
例如类A包含两个数据成员对象,分别为:string str和char *Cstr,那么编译器生成 ...
Object Distinction
Object Distinction程序设计模型
procedural model
char boy[] = "Danny";char *p_son;p_son = new char[strlen(boy) + 1];...
abstract data type model(ADT)
String girl = "Anna";String daughter;// String::operator=();daughter = girl;
object-oriented model
void check_in(Library *pmat) { if(pmat->late()) pmat->fine();}
直接或间接处理继承体系中的一个 base class object, 但只有通过pointer或reference的间接处理,才支持OO程序设计所需的 多态性质。
Library thing1;// class Book: public Library{...}Bo ...
Zero Copy
Zero Copy
零拷贝(Zero-Copy)是一种 I/O 操作优化技术,可以快速高效地将数据从文件系统移动到网络接口,而不需要将其从内核空间复制到用户空间。其在 FTP 或者 HTTP 等协议中可以显著地提升性能。
因为两次 DMA 都是依赖硬件完成的。所以,所谓的零拷贝,都是为了减少 CPU copy 及减少了上下文的切换。
但是需要注意的是,并不是所有的操作系统都支持这一特性,目前只有在使用 NIO 和 Epoll 传输时才可使用该特性。
传统I/O操作
传统 I/O 的工作方式是,数据读取和写入是从用户空间到内核空间来回复制,而内核空间的数据是通过操作系统层面的 I/O 接口从磁盘读取或写入。
需要两次系统调用read和write
read(file, buf, len);write(socket, buf, len);
发生了四次上下文切换与四次数据拷贝
第一次拷贝,把磁盘上的数据拷贝到操作系统内核的缓冲区里,这个拷贝的过程是通过 DMA 搬运的。
第二次拷贝,把内核缓冲区的数据拷贝到用户的缓冲区里,于是我们应用程序就可以使用这部分数 ...
TCP三次握手与四次挥手
TCP三次握手与四次挥手TCP三次握手
第三次握手是可以携带数据的,前两次握手是不可以携带数据的。
一旦完成三次握手,双方都处于 ESTABLISHED 状态,此时连接就已建立完成,客户端和服务端就可以相互发送数据了。
服务器发送完 SYN-ACK 包,如果未收到客户端响应的确认包,也即第三次握手丢失。那么服务器就会进行首次重传,若等待一段时间仍未收到客户确认包,就进行第二次重传。如果重传次数超过系统规定的最大重传次数,则系统将该连接信息从半连接队列中删除。
原因
避免历史连接:如果只有两次握手,接收到SYN后,服务器就开始向客户端传递数据,直到客户端返回RST,才中断历史连接;浪费服务器资源。
同步双方的序列号:两次握手只保证了一方的初始序列号能被对方成功接收,没办法保证双方的初始序列号都能被确认接收。
序列号作用:
接收方可以去除重复的数据;
接收方可以根据数据包的序列号按序接收;
可以标识发送出去的数据包中, 哪些是已经被对方收到的(通过 ACK 报文中的序列号知道);
初始序列号不同,防止历史报文被下一个相同四元组的连接接收
避免资源浪费:两次握手时,服务器收到 ...
TCP半连接与全连接
TCP半连接与全连接TCP三次握手内核动作
listen()会初始化半连接队列
connect()发送SYN请求,server对半连接队列进行溢出判断(后面会详细讲解),没有溢出发送SYN+ACK包;client收到后发送ACK包;Server创建新的sock,从半连接队列中删除,同时将新建的sock加入全连接队列
accept()就是从全连接队列中取出一个文件描述符
半连接队列和全连接队列
半连接队列,SYN队列
全连接队列,accept队列
不管是半连接队列还是全连接队列,都有最大长度限制,超过限制时,内核会直接丢弃,或返回 RST 包。
TCP全连接队列情况
使用ss -lnt查看TCP全连接队列情况
LISTEN状态下
Recv-Q:当前全连接队列的大小,也就是当前已完成三次握手并等待服务端 accept() 的 TCP 连接;
Send-Q:当前全连接最大队列长度
非LISTEN状态下
Recv-Q:已收到但未被应用进程读取的字节数;
Send-Q:已发送但未收到确认的字节数;
溢出
溢出后的策略由tcp_abort_on_overflow 设置
0 :如 ...
TimesharingOS
TimesharingOS
MultiprogOS
Qemu把包含多个app的列表和MultiprogOS的image镜像加载到内存中,RustSBI(bootloader)完成基本的硬件初始化后,跳转到MultiprogOS起始位置
MultiprogOS首先进行正常运行前的初始化工作,即建立栈空间和清零bss段,然后通过改进的 AppManager 内核模块从app列表中把所有app都加载到内存中,并按指定顺序让app在用户态一个接一个地执行。
app在执行过程中,会通过系统调用的方式得到MultiprogOS提供的OS服务,如输出字符串等。
CoopOS
CoopOS进一步改进了 AppManager 内核模块,把它拆分为负责加载应用的 Loader 内核模块和管理应用运行过程的 TaskManager 内核模块。
TaskManager 通过 task 任务控制块来管理应用程序的执行过程,支持应用程序主动放弃 CPU 并切换到另一个应用继续执行,从而提高系统整体执行效率。
应用程序在运行时有自己所在的内存空间和栈,确保被切换时相关信息不会被其他应用破坏。如果当前应用程 ...
Hash Index -- CMU15445
Extenible Hash Table可扩展哈希,初始哈希表中只有一个directory和一个bucket,每个bucket可以容纳两条数据
Hash Table PageHash Table Header Page
存放所有的directory pages,但是这个header page容纳的directory pages是固定的
/** * Header page format: * --------------------------------------------------- * | DirectoryPageIds(2048) | MaxDepth (4) | Free(2044) * --------------------------------------------------- */static constexpr uint64_t HTABLE_HEADER_PAGE_METADATA_SIZE = sizeof(uint32_t);static constexpr uint64_t HTABLE_HEADER_MAX_DEPTH = 9;stat ...