- 博客(142)
- 收藏
- 关注
原创 页表和线程详解
假设我有一个32位的机器,那么内存大小应该是2^32=4GB。管理物理内存是将内存按4KB的大小分成一个一个的页,那么就一共有1M个物理页。操作系统管理物理页是用全局struct page数组来管理,假设一个struct page有40B,那这个数组就有40MB。
2025-05-26 10:45:11
911
原创 IPC进程间通信详解
匿名管道的本质就是内存里一块缓冲区创建一个struct pipe_inode_info,创建两个struct file,struct file的void* private_data指向struct pipe_inode_info,第一个file绑定读端,第二个file绑定写端,最后将两个file的文件描述符按照读写的顺序返回给int fd[2]数组// 文件路径(含dentry和挂载点)// 实际指向 pipe_inode_info(管道专属数据)
2025-05-24 13:59:21
1078
原创 从程序加载到代码执行,命令行参数和环境变量
2.调用__libc_start_main函数,该函数会调用main并传递参数,并最后将main的return值作为参数,调用exit退出进程。3.初始化pc指针为ELF头的入口地址(_start),将命令行参数和环境变量加载进新栈。1.解析栈里面的命令行参数和环境变量,将main的参数保存到寄存器里。1.摧毁当前内存空间,包括堆栈、代码段、数据段等。2.加载新程序的代码段和数据段并创建新的堆栈。
2025-05-23 20:48:59
83
原创 ext2文件系统详讲
C:cylinder,确定一个柱面H: header, 确定一个磁头,也就是磁道S: sector, 确定扇区凭借(c,h,s)就可以定位一个扇区。
2025-05-22 22:51:23
1155
原创 基础IO详解
1.FILE是文件的用户级数据结构,创建在堆上2.FILE里有维护一个用户级缓冲区,这个用户级缓冲区是为了减少系统调用的次数3.进程一般会有三个标准FILE*流,stdin,stdout,stderr,对应文件描述符一般是0,1,24.FILE里保存有对应的文件描述符fd。
2025-05-22 16:30:36
257
原创 fork 和 写时拷贝
1.fork是一个系统调用,父进程调用fork,触发软中断,然后陷入内核,将cpu寄存器保存在内核栈中,去中断向量表中找软中断处理函数,然后软中断处理函数根据寄存器里的系统调用号,去系统调用表里执行对应系统调用。创建子进程pcb,拷贝父进程内核栈,将父进程内核栈里的eax,也就是返回值寄存器里的值改成子进程pid,将子进程内核栈里eax的值改成0,然后将pcb加入运行队列2.父进程fork系统调用执行完后从内核栈中恢复寄存器,然后返回用户态。
2025-05-21 20:53:26
193
原创 进程的调度
在linux2.6内核中,每一个cpu都有一个运行队列,即内核变量struct runqueue,并且每个cpu都有一个全局变量struct task_struct*,用来保存cpu正在运行的进程是谁。
2025-05-18 21:40:59
413
原创 进程状态并详解S和D状态
define TASK_RUNNING 0x0000 // 运行或就绪(在运行队列)#define TASK_INTERRUPTIBLE 0x0001 // 可中断睡眠(S状态)#define TASK_UNINTERRUPTIBLE 0x0002 // 不可中断睡眠(D状态)#define __TASK_STOPPED 0x0004 // 暂停(收到 SIGSTOP)#define __TASK_TRACED 0x0008 // 被调试器追踪。
2025-05-18 19:31:59
496
原创 C语言中的文本读写和二进制读写接口
从文件中读取一个字符- 向文件写入一个字符- 从文件中读取一行- 向文件写入一行- 格式化输出到文件- 从文件格式化输入。
2025-05-09 14:56:18
490
原创 C++ 文本读写与二进制读写的底层机制
1.文本打开在windows中,写入时会将\n换成\r\n,读出时\r\n会读出\nlinux对\n读写不做处理2.二进制打开对\n读写不做处理。
2025-05-09 14:44:46
169
原创 c++的四种类型转换
失败时返回 nullptr(指针)或抛出异常(引用)// 移除 const(已知不会修改时)修改原始 const 对象是未定义行为。用于编译器允许的隐式转换的显式表达。// 类层次结构上行转换(安全)// 添加 const(较少用)运行时检查类型信息(RTTI)// 移除 volatile。最危险的转换,应谨慎使用。// void* 转换。不进行任何类型安全检查。// 不相关类指针转换。在编译时进行类型检查。执行低级别的重新解释。// 指针与整数互转。父类至少有一个虚函数。
2025-05-09 12:06:47
860
原创 auto_ptr和unique_ptr
/ p1 变为 nullptr。// 接管 other 的资源。// p1 变成 nullptr,p2 接管资源。:由于不安全的拷贝行为,C++11 起被废弃,C++17 移除。// 释放所有权(返回原始指针,并置空)// 拷贝构造函数(转移所有权)// 重置指针(先删除旧资源)// 赋值操作(转移所有权):同一时间只能有一个。
2025-05-08 22:23:06
815
原创 可变参数包 和 lambda表达式
/ 相当于 auto lambda = [](int x, int y) { ... };void bar(Types... values) { // values 是形参参数包。template <typename... Types> // 类型参数包。template <typename... Args> // Args 是类型参数包。void print(Args... args) { // args 是形参参数包。
2025-05-08 17:13:56
658
原创 default和delete final和override
default1.生成默认成员函数(如构造函数、析构函数、拷贝/移动操作等)delete1.删除函数2.(不限于特殊成员函数)
2025-05-07 22:08:01
243
原创 ()初始化 和 { }初始化
调用构造函数去初始化先创建const T[ ] 数组,然后用数组头指针和元素个数去创建initializer_list<T>对象,再用initializer_list<T>去初始化自定义类型,也就是参数为initializer_list<T>的构造函数。
2025-05-07 14:33:59
176
原创 位图和布隆过滤器的设计
位图就像是一个元素是位的数组,非类型模板参数指明有多少个位,这些位的下标是从0开始。也就是说一个参数为N的位图,就有N个位,位的下标是0~N-1。
2025-05-07 13:12:35
299
原创 unordered_map和unordered_set的设计
3.接口就封装一下就是了,值得一说的就是operator[ ],底层是用insert去插入<key, V()>的键值对,然后无论插入成功还是失败,返回迭代器对应节点的数据的值V的引用。2.unordered_map封装的是哈希表对象,并且封装的是链地址法开散列实现的哈希表,所以模板参数参数,第一个键类型,第二个节点数据类型,剩下两个不说了。1.unordered_map的模板参数,键类型K,值类型V,把K变成size_t的仿函数类类型Hash,
2025-05-06 22:59:41
201
原创 哈希表的设计
哈希表是一种通过将元素的键(Key)映射到存储位置的数据结构。的作用:通过键值计算存储位置,公式一般为。:不同的键可能被映射到同一个位置(例如),这种情况称为或。:如果目标位置已被占用,就按照某种探测方法在哈希表内冲突时,依次检查下一个位置:冲突时,按平方步长跳跃检查:第一个哈希函数计算基础地址,使用第二个哈希函数计算步长:所有数据都存在哈希表内,。(标记为“逻辑删除”),否则会破坏探测链。(如 ≤0.7),否则性能急剧下降。:将哈希表的每个槽作为,冲突的元素直接追加到链表中。
2025-05-06 22:40:56
774
原创 AVL树 和 红黑树 的插入算法
按照二叉搜索树的规则找到要插入的位置并插入,插入过后看是父节点的左还是右孩子,然后把父节点的平衡因子-1或+1,调整后如果父节点的平衡因子是0,那就说明这颗子树的高度插入前后不变,上面的就不用调整平衡因子了,到此结束。如果调整后如果父节点的平衡因子是1或-1,那就说明该子树的高度变化了,那就往上走。走了之后看是左孩子还是右孩子,然后给父节点的平衡因子-1/+1,然后看调整后的结果,如果是0或+/-1那和上一次处理一样,不再多说,如果是+/-2,那就开旋~,记该节点为Parent。
2025-05-05 19:45:06
702
原创 红黑树和AVL树封装map和set的细节 以及 map的operator[]重载的底层
AVL树的insert是 pair<iterator, bool> insert(const K& key, const V& value),节点的数据是 pair<K,V>AVL树的insert是 pair<iterator, bool> insert(const K& key, const V& value),节点的数据是 pair<K,K>红黑树的insert是 pair<iterator, bool> insert(const T& data),节点的数据是 pair<K,V>
2025-05-05 17:32:28
197
原创 AVL树的设计
AVL树有两个模板参数K和V,K是avl树节点排序用的类型,pair<K,V>是AVL树节点里数据的类型。而红黑树有三个模板参数 红黑树节点排序所用的类型K,红黑树节点里数据的类型T, 把T变成K的仿函数类类型KeyOfT。有三个指针,一个数据,一个平衡因子,这都没问题,但红黑树的节点只有一个模板参数也就是数据类型T,而AVL节点有两个模板参数K和V,avl树节点里数据的类型是pair<K,V>用AVL树去适配map和set。
2025-05-05 17:11:14
438
原创 二叉搜索树 AVL树 红黑树 的性质
左子树的所有节点值 < 当前节点值,右子树的所有节点值 > 当前节点值,左右子树也必须满足 。中序遍历,得到的序列是有序的1.根节点是黑色2.不能有相邻的红色节点3.每条路径的黑色节点数目相同首先是二叉搜索树,其次是满足红黑树的性质每个结点的平衡因子的绝对值不超过1,一个节点的平衡因子是右子树高度减左子树高度首先是二叉搜索树(BST),其次是满足AVL的性质
2025-05-05 16:13:46
218
原创 map和set的设计以及红黑树的设计
红黑树的迭代器和list一样是封装了结点指针的类,第一个模板参数是为了形成结点指针类型,二、三模板参数则是为了实例化出迭代器和const迭代器类。1.封装map,节点来排序的类型是K,节点里数据的类型pair<const K,V>,还有把T变成K的仿函数类。第一个是节点排序所用的类型K,第二个是节点里数据的类型T,第三个是把T变成K的仿函数类型。2.封装set,节点用来排序的类型是K,节点里数据的类型还是K,还有把T变成K的仿函数类。但是我上面代码的实现并没有设计哨兵节点,也没有节点个数,就一个根节点。
2025-05-05 15:15:47
361
原创 普通函数调用和虚函数调用
源文件.cpp经过编译变成目标文件,函数保存在目标文件的代码段,符号表保存在只读数据段,这时代码段和数据段中的函数调用的地址都是临时地址,链接时目标文件合并,函数地址固定下来,重定位修改临时地址为新地址,源文件.cpp经过编译变成目标文件,子类虚函数表是拷贝父类虚表,存在只读数据段,虚函数在代码段,重写虚函数会覆盖原来子类虚函数表里的指针,链接合并目标文件,重定位表记录了目标文件中需要修改的地址(如函数调用、变量引用),指导链接器或加载器在链接或运行时修正这些地址。:需要修改的指令或数据的偏移地址。
2025-05-04 19:21:16
756
原创 模板特化详解与示例代码
模板特化可以减少模板参数数量全特化使用template<>且没有模板参数偏特化可以特化参数的类型模式(如指针、容器等)函数模板特化参数可以显式指定、推导或使用缺省值类模板特化参数可以显式指定或使用缺省值。
2025-05-04 12:38:05
533
原创 list的设计
/ 指向下一个节点。// 指向前一个节点。// 重载操作符(如 *、->、++ 等)// Debug 模式下可能包含校验信息。每个节点包含两个指针和一个数据成员。与 MSVC 类似,但字段命名不同。的类(因为链表节点在内存中不连续)。:可能添加迭代器校验字段(如。// 直接操作节点指针。),但不支持随机访问(如。),因此是双向迭代器。
2025-05-03 21:47:32
708
原创 string的vs和g++实现方式以及g++方式的代码
_Bx._Buf[16] | // 或 _Bx._Ptr (长字符串)| [可能的填充] (4 bytes) | // 对齐到 28/32 字节,向8字节对齐。// 4字节:容量(或 SSO 时复用)// 16字节:短字符串优化(SSO)的缓冲区。// 4字节:总容量(不包括结尾的 '\0')| _Mysize (4 bytes) | // 实际字符数。| _Myres (4 bytes) | // 总容量。
2025-05-03 14:54:23
539
原创 getline
/ 读取一行,最多99个字符 + '\0'std::getline(std::cin, line);// 读取一行到 string。从输入流中读取一行数据,存储到 std::string。自动扩展内存,无需预分配固定大小。从输入流中读取一行数据,存储到。:最多读取的字符数(包括结尾的。:需预先分配足够大的固定数组。:无需担心缓冲区溢出。
2025-05-03 14:23:52
297
原创 >>流提取运算符重载
/ 实际实现更复杂。内置类型是语言原生支持的,标准库直接在其类内定义成员函数即可。如果定义为自定义类的成员函数,调用方式会反直觉(如。// 成员函数重载 >> 用于内置类型。的成员函数,无法直接访问其他类的私有成员。需要访问该类的私有成员(如。
2025-05-03 14:19:36
492
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人