自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(96)
  • 收藏
  • 关注

原创 第十九章:特殊工具与技术

枚举属于字面值常量类型。C++包含两种枚举:限定作用域和不限定作用域的。限定作用域是C++11新标准引入的,定义方式为在定义的时候在enum后面加上class或struct。在限定作用域的枚举类型中,枚举成员的名字遵循常规的作用域准则,并且在枚举类型的作用域外是不可访问的(可以用作用域运算符访问);在不限定作用域的枚举类型中,枚举成员的作用域与枚举类型本身的作用域相同。默认情况下,枚举值从0开始,依次加1,不过我们也能为一个或几个枚举成员指定专门的值。枚举值不一定唯一。枚举成员是const的。

2024-01-14 09:58:46 982 1

原创 第十八章:用于大型程序的工具

异常处理机制允许程序中独立开发的部分能够在运行时就出现的问题进行通信并做出相应的处理。异常使得我们能够将问题的检测与解决过程分离开来。在C++语言中,我们通过抛出一条表达式来引发一个异常。被抛出的表达式的类型以及当前的调用链共同决定了哪段处理代码将被用来处理该异常。被选中的处理代码是在调用链终于抛出对象类型,处理完后继续执行处理代码块之后的代码。异常的处理过程是根据栈展开的过程进行的。栈展开的过程中如退出了某些块某些局部对象会被自动销毁。析构函数不应该抛出不能被它自身处理的异常。

2024-01-12 12:22:41 392

原创 第十七章:标准库特殊设施

tuple是类似pair的。不同tuple类型的成员类型不相同,一个tuple可以有任意数量的成员。每个确定的tuple类型的成员数目是固定的。tuple类型及其伴随类型都定义在tuple中。当我们定义一个tuple时,需要指出每个成员的类型。make_tuple根据初始值的类型来推断tuple的类型。要访问一个tuple的成员,就要使用一个名为get的标准库函数模板。

2024-01-11 12:38:00 861

原创 第十六章:模板与泛型编程

类模板是用来生成类的蓝图的。与函数模板的不同之处是,**编译器不能为类模板推断模板参数类型。**我们必须在模板名后的尖括号中提供额外信息用来代替模板参数的模板实参列表。定义在类模板之外的成员函数必须以关键字template开始,后接类模板参数列表。同样的,在类外定义一个成员时,必须说明成员属于哪个类,且类名需要包含模板形参。默认情况下,一个类模板的成员函数只有当程序用到它时才进行实例化。当我们使用一个类模板类型时必须提供模板实参,但在类模板自己的作用域中我们可以直接使用模板名而不提供实参。

2024-01-08 13:54:38 864

原创 第十五章:面向对象程序设计

通过使用数据抽象可以将类的接口与实现分离;使用继承可以定义相似的类型并对其相似关系建模;使用动态绑定可以在一定程度上忽略相似类型的区别,而以统一的方式使用他们的对象。基类将类型相关的函数与派生类不做改变直接继承的函数区分对待。对于某些函数,基类希望它派生类各自定义适合自身的版本,此时基类就将这些函数声明成虚函数。C++11新标准允许派生类显式地注明它将使用哪个成员函数改写基类的虚函数,具体措施是在该函数的形参列表之后加一个override关键字。

2024-01-06 12:19:10 899

原创 MIT6.S081Lab8:locks

当一个锁的竞争比较激烈而要减少竞争时,可以将这个锁分为更多较细粒度的锁,这样可以提高并行性。另外我感觉第二个部分说的有一点不清楚,提示比较模糊,尤其是ticks部分,关键是用ticks实现LRU的话要遍历所有桶,相当于O(n),而之前双向链表的方式最差才是O(n),一般是O(1)。

2024-01-05 17:09:01 395

原创 MIT6.S081Lab7:Multithreading

总的来说这几个实验都不难,只要把已有的代码看懂加上提示做出来还是没问题的,第一个实验对我的提升最大,进一步理解了ra和sp,尤其是sp,原来更改堆栈这么简单,所谓程序的状态,其实主要也就是那几个寄存器的值而已。

2024-01-04 15:11:39 329

原创 第十四章:重载运算与类型转换

产生的结果一致时才定义<运算符。

2023-12-17 12:01:27 850

原创 C++Primer第十三章:动态内存

这一章我们学习C++的拷贝控制,所谓拷贝控制就是类如何控制该类型对象拷贝,赋值,移动或销毁时做什么。主要通过五种特殊的成员函数来控制这些操作:拷贝构造函数,拷贝赋值函数,移动构造函数,移动赋值函数,析构函数。所谓构造就是用一个同类型的对象来初始化本对象,所谓赋值就是将一个对象赋予同类型的另一个对象。如果自己不定义编译器会默认定义这些操作。

2023-12-15 09:14:24 341

原创 MIT6.S081Lab6:Copy on Write Fork for xv6

实验不难,但是要仔细,而且很多时候,当你觉得你的想法实现太复杂了,多半是想法有问题。

2023-12-08 18:14:11 389

原创 MIT6.S081Lab5:xv6 lazy page allocation

这个实验总的来说我觉得还是比lab3简单一点,最需要注意的就是最后一个中关于系统调用涉及到lazy allocation不会触发页面错误需要手动编写代码来分配页面。

2023-12-07 16:57:04 866

原创 MIT6.S081Lab4:traps

总的来说,lab4并不是很难,只要理解了trap的机制以及用户空间与内核在trap机制中如何转换,应该是能够写出来的。可能需要一点汇编代码的理解能力,不过应该还是能大致看懂需要用到的汇编的。在test0中我在usertrap直接执行处理函数,忽略了用户和内核页表的不一致导致出错,这一点需要注意,尤其是解引用的时候。

2023-12-06 10:32:48 345

原创 MIT6.S081Lab3:page tables

按照准备环境,即如果提示之前的修改没有提交的话可以把之前的修改去掉(备份一份)。

2023-12-05 13:54:45 857

原创 如何在自己的github仓库建立xv6-labs-2020项目

然后进入该文件夹运行git bash或者其他git控制程序,建立与自己github上仓库的连接(如果没有,在github上新建一个)查看所有远程分支(除master外所有分支都是在远程仓库上,本地没有)这个时候再去看github的仓库,已经有util分支以及对应的文件了。然后直接把util分支push到我们自己的github仓库上。然后切换到某一个分支就可以把远程分支复制到本地来。例如我们需要util这个分支,那么就。切换到util分支,这个时候适用。就可以看到本地有util分支了。

2023-11-27 10:58:35 638

原创 MIT6.S081Lab2:system calls

其实这两个实验都不是很难,根据提示来基本能在1~2小时内做出来。两个实验让我更加理解系统调用的过程,同时还让我明白了一件很重要的事情:用户空间和内核空间各有各的页表,不能互相读写内存空间。

2023-10-22 16:26:07 120

原创 MIT6.S081Lab1: Xv6 and Unix utilities

这几个实验因为中间有其他事情,所以时间跨度还是挺长的,不过我觉得MIT6.S081的实验真的很有价值,之前可能用过这些指令,但是不清楚这些指令具体怎么实现的,在实现这些指令的过程我对fork,pipe,exec这些系统调用的使用更加熟练了,之前其实没怎么使用过这些系统调用。期待下一个实验!

2023-10-18 19:54:46 241

原创 MIT6.S081的gdb调试方法

MIT6.S081的gdb调试方法

2023-10-11 16:41:37 333

原创 MIT6.S081实验环境搭建

本文参考了MIT的官方指南和知乎文章。

2023-09-05 14:54:41 865

原创 C++Primer第十二章:动态内存

在C++中,new和delete分别负责分配和释放空间。新的标准库提供了两种智能指针,shared_ptr,unique_ptr,还有一种weak_ptr。都定义在memory头文件中。智能指针也是模板。

2023-08-09 09:30:30 122

原创 C++Primer第十一章:关联容器

关联容器与顺序容器不同之处在于顺序容器是按在容器中的位置保存和访问元素,而关联容器是按关键字来保存和访问元素的。

2023-08-03 14:12:30 111

原创 C++Primer第十章:泛型算法

哪些只接受一个单一迭代器来表示第二个序列的算法,都假定第二个序列至少与第一个序列一样长。在C++中,无论是C风格的字符串还是字符串常量,都不能直接用==这些运算符进行比较,因为C风格的字符串和字符串常量直接比较都是相当于在比较首指针地址的大小,会出问题。。当我们使用一个迭代器向容器元素赋值时,我们覆盖了原来的值,而当我们使用插入迭代器向容器元素赋值时,这个值是添加到容器中的。

2023-08-02 09:13:12 89

原创 C++Primer第九章:顺序容器

使用front,back,下标和at返回的都是引用,如果要用auto接收引用,则要加引用符号&。因为forward_list的删除添加需要用到前一个个元素,所以它的添加和删除与其他的顺序容器不同,它没有insert,emplace,erase等操作,它的是insert_after之类的after操作,即操作后一个元素。使用resize,如果新大小小于当前大小,后部的元素会被删除,如果新大小大于当前大小,新元素会添加到后部。

2023-07-20 10:38:54 79 1

原创 数组前缀和

在这一道题目里面,中间某一段连续子数组和为k,意思即为sum[i] - sum[j - 1] = k,也即sum[i] - k = sum[j - 1],所以当我们求每一个的前缀和的时候,只需要统计对应的sum[j - 1]个数即可。前缀和就是指前缀的和,例如在数组中,从开始到 i 就是到 i 的前缀和。前缀和一般用来求中间连续某一段的和,例如sum[i] - sum[j - 1]就可以求出j 到 i 这一段的和。当然还有二维数组的前缀和,不过大致原理就是这样,通过两个前缀和求中间的和。

2023-07-18 16:37:55 412

原创 C++Primer第八章:IO库

标准库中主要定义了三个流来进行IO操作。iostream处理控制台IO;fstream处理命名文件IO;stringstream处理内存string的IO。后面两个继承自第一个。所以第一个的操作后面两个也是可以用的。例如>>

2023-06-29 11:02:00 410

原创 372.超级次方

LeetCode超级次方:你的任务是计算 ab 对 1337 取模,a 是一个正整数,b 是一个非常大的正整数且会以数组形式给出。

2023-01-28 15:27:25 103 1

原创 leetcode:4.寻找两个正序数组的中位数

给定两个大小分别为 m 和 n 的正序(从小到大)数组nums1 和nums2。请你找出并返回这两个正序数组的 中位数 。算法的时间复杂度应该为 O(log (m+n)) 。

2022-11-01 09:40:04 104

原创 基于Pthreads并行实现通用矩阵乘法、数组求和及二次方程组求解

基于Pthreads并行实现通用矩阵乘法、数组求和及二次方程组求解

2022-10-22 11:27:38 298

原创 C++Primer第七章:类

类型的基本思想是数据抽象和封装,数据抽象依赖于接口和实现分离。类的接口包括用户所能执行的操作,而类的实现包括类的数据成员,负责接口实现的函数体以及定义类所需的各种私有函数。封装实现了类的接口和实现的分离。

2022-10-20 17:07:31 535

原创 C++Primer第六章:函数

函数是一个命名了的代码块,我们可以通过调用函数执行相应的代码。每个函数都包括返回类型,名字和形参列表以及函数体。C++中函数可以被重载,从一组重载函数中选取最佳函数的过程称为函数匹配。

2022-10-16 15:28:27 509

原创 并查集总结

并查集是一种树型的数据结构,用于处理(不相交)集合的合并、查询及由此衍生的问题。其功能主要有三个:1. 寻找根节点,函数:find(int u),也就是判断这个节点的祖先节点是哪个2. 将两个节点接入到同一个集合,函数:join(int u, int v),将两个节点连在同一个根节点上3. 判断两个节点是否在同一个集合,函数:same(int u, int v),就是判断两个节点是不是同一个根节点

2022-10-15 10:04:14 90

原创 单调栈总结

所谓单调栈,指的是栈中的值保持着单调,当有一个新值到来时,需要比较新值与栈顶元素,如果不符合单调性,需要一直弹出栈顶元素直至符合单调性或者栈空才能压入新值。单调栈一般用来求左边或右边第一个比自己大或小的元素的位置。使用单调栈主要要想清楚三种情况,当新值大于等于小于栈顶元素的情况。

2022-10-14 16:16:17 380

原创 C++Primer第五章:语句

一般来说,语句是顺序执行的,但仅有顺序执行远远不够,因此,C++语言提供了一组控制流语句以支持更复杂的执行路径。

2022-10-11 16:14:01 472

原创 动态规划总结

动态规划区别于贪心的是它的当前每一个状态(除了初始化)一定是由上一个状态推导出来的。​ 动规解题步骤:1:确定dp数组及其下标的含义;2:确定递推公式;3:dp数组如何初始化;4:确定遍历顺序;5:举例推导dp数组。

2022-10-11 11:03:50 139

原创 C++Primer第四章:表达式

C++提供了丰富的运算符作用于内置类型,同时运行自定义的类型定义这些运算符。本章介绍语言本身定义的,用于内置类型的一些运算符以及几种标准库定义的运算符。表达式由一个或多个对象组成,对表达式求值可得一个结果。变量和字面值是最简单的表达式,其值为自身。

2022-10-09 16:46:24 468

原创 C++Primer第三章:字符串、向量和数组

之前介绍的都是C++的内置类型,由C++语言直接定义,直接实现到计算机硬件中。而标准库还定义了一些具有更高级性质的类型,本章介绍两种最重要的,即string和vector。

2022-10-05 09:29:43 855

原创 C++Primer第二章:变量和基本类型

C++11新标准规定,可以为类(或结构体)内的数据成员提供一个类内初始值。没有初始值的成员将被默认初始化。为了确保各个文件中的类的定义一致,类通常被定义在头文件中,而且类所在头文件的名字应与类的名字一样。确保头文件多次包含仍能安全工作的常用技术是预处理器,#include是一项预处理器功能,当预处理器看到#include标志时会用指定的头文件的内容代替#include。还有一项预处理器的功能是头文件保护符,头文件保护符依赖于预处理变量,预处理变量有两种状态:已定义和未定义。

2022-09-26 17:22:36 716

原创 贪心算法总结

​ 贪心的本质是选择每一阶段的局部最优,从而达到全局最优。难点在于如何通过局部最优推出全局最优。如果感觉能用贪心的话可以手动模拟试一试。我觉得贪心的套路就是当前要保持一个什么最值,然后遇到什么情况要更新这个最值。

2022-09-25 11:18:44 374

原创 第三章:用MPI进行分布式内存编程

​ 散射:有时候我们并不需要把所有数据发送给所有进程,而是把相应数据发送到相应进程,这个时候可以使用散射,所谓散射就是将数据的一部分发送给某个进程,然后把数据的另一部分发送给另一个进程,MPI为散射提供的API为MPI_Scatter,目前我们所学的这个函数值适用于块划分以及n可以整除comm_sz的情况。​ 通信子:指一组可以互相发送消息的组合,用户启动的所有进程所组成的通信子成为MPI_COMM_WORLD,一个通信子中进程发送的消息不能被另一个通信子中进程接收。

2022-09-19 09:50:58 1125

原创 第二章:并行硬件和并行软件

​ 因为cache每次取不是取一个变量,往往取一个高速缓存行,所以当高速缓存行一个变量的状态发生改变时,cpu会把整个高速缓存行的变量的状态都改变,所以明明有些变量没有变,但其他核访问这些变量的时候发现状态改变还是会重新从主存中读取,降低了效率,即有些变量明明不是共享变量,但因为与其他变量处于同一个高速缓冲行表现为共享变量,所以叫做伪共享。​ 概述:在多核系统中,各个核的cache存储相同变量的副本,当一个核更新一个变量副本的时候,其他核应该知道该变量已更新。分为静态多发射和动态多发射。

2022-09-19 09:48:43 884

原创 第一章:为什么要并行计算

​ 单处理器性能提升有限,晶体管传递速度过快能耗过高发热,所以需要继承多个处理器在芯片中。

2022-09-19 09:45:32 305

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除