- 博客(55)
- 收藏
- 关注
原创 C++四种强制类型转换
操作符通常为操作数的位模式提供较低层次的重新解释,用于将一种类型转换为另一种不同的类型.进行强制类型转换. 而变量x和变量p,一个为数值类型,一个为指针类型,不相近,不能用。标准C++为了加强类型转换的可视性,引入了4种命名的强制类型转换操作符.用于非多态类型的转换(静态转换),编译器隐式执行的任何类型转换都可以用。用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)这段代码中,d变量和a变量都表示数值类型,可以使用。因此C++ 提出了自己的类型转换风格,的简称,即:运行时类型识别。
2022-12-13 12:57:35
1752
原创 C++11【包装器】
头文件中,是一个函数模板,它就像一个函数包装器(适配器),接收一个可调用对象,生成一个新的可调用对象来适应原对象的参数列表.函数看作是一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来 “适应” 原对象的参数列表.是一个逗号分隔的参数列表,对应给定的callable的参数,当我们调用。那么,包装器是如何解决了模板的效率低下,实例化了多份的问题呢?的名字,其中n是一个整数,这些参数是占位符,表示。本质是一个类模板,也是一个包装器.包装器也叫做适配器,C++中的。中的参数,它们占据了传递给。
2022-12-13 10:26:34
589
原创 多线程编程【POSIX信号量】
信号量是一个有整数值的对象,可以用两个函数来操作它在POSIX标准中,是sem_wait()和sem_post(). 因为信号量的初始值能够决定其行为,所以首先要初始化信号量,才能调用函数与之交互.sem_t s;我们定义了一个信号量,通过第三个参数,将它的值初始化为1.sem_init()的第二个参数,设置为0,表示信号量是在同一进程的多个线程共享的.可以参考man手册,了解信号量的其他用法(如何用于跨不同进程的同步访问).信号量初始化之后,我们可以调用sem_wait()和sem_post()
2022-12-12 14:40:40
732
原创 如何制作并使用动静态库
程序在编译链接时把库的代码链接到可执行文件中,程序运行的时候将不再需要静态库。:程序在运行的时候才去链接动态库的代码,多个程序共享使用库的代码。但我们的头文件和库文件都不在当前目录下,也不在系统路径中.当我们给别人使用这个静态库时,不仅要给别人静态库文件,那么了解了动静态库的概念之后,如何制作动静态库呢?使用动态库,与静态库一样,我们将我们制作的动态库与。接着,我们使用刚才的指定搜索路径的方式来编译。使用如下命令我们便可以将自己写的。为了使用静态库,我们创建一个。文件也需要,所以我们将。
2022-12-09 13:08:19
751
原创 Linux基础IO
操作文件,除了语言级别的接口,我们还可以采用系统接口来进行文件访问.open()pathname要打开或者创建的目标文件flags打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行"或"运算,构成flags.O_RDONLY:只读打开O_WRONLY:只写打开O_RDWR:读、写打开,这三个常量,必须指定一个且只能指定一个O_CREAT:若文件不存在,则创建它,需要指明mode选项,来指明新文件的访问权限O_APPEND:追加写成功:新打开的文件描述符失败:-1函数open()
2022-12-08 14:21:41
417
原创 vector深度剖析及模拟实现
这是在VS版本下的扩容机制:每次扩容1.5倍但在Linux下,它每次以2倍的方式扩容:所以,它并不是每次必须以固定的方式扩容,而是选择一个合适的数值:因为单次增容越多,插入N个值,当需要增容时,增容次数越少,但单次增容越多,可能浪费的空间就越多.单次增少了,会导致频繁扩容,效率降低.我们在对进行扩容时,需要将原来空间上的数据拷贝到新开的空间上,那么拷贝数据使用会不会有问题呢?首先来看一个简单的:可以看到,对于上述简单的vector,使用并不会带来什么问题,但是让我们看看下面这个场景:所以,在扩容时,我们
2022-12-07 12:47:20
430
原创 文件系统实现
我们想要了解文件系统在磁盘上的数据结构的整体组织,首先需要将磁盘分成块(). 简单的文件系统只使用一种块大小,我们选择常用的.因此,我们对构建文件系统的磁盘分区看法很简单:一系列块,每块大小为,在大小为N个块的分区中,这些块的地址为,假设我们有一个非常小的磁盘,只有块:那么我们需要在这些块中存储什么呢?首先需要存储用户数据,任何文件系统大多数的空间都是用户数据,我们将用于存放用户数据的块称为数据区域,所以我们将上述磁盘中的个块用来存放用户数据:文件系统还必须记录每个文件的信息,该信息是元数据的关键部分,记录
2022-12-06 11:12:32
1364
原创 虚拟内存系统【页面置换算法】
我们需要做很多工作,在每次页访问(即每次内存访问,不管是取指令还是存储)时,我们都必须更新一些数据,从而将该页移到列表的前面(最近使用),与FIFO相比,FIFO的页列表仅在页被踢出或者新页添加到列表时才被访问,为了记录哪些页是最少和最近被使用,系统必须对每次内存引用做一些记录工作,有可能会影响性能.记录每个页面的访问次数,当发生缺页中断时,将访问次数最少的页面置换出去,此方法需要对每个页面访问次数进行统计,额外开销.)无法确定页的重要性:即使页0已被多次访问,仍然会将其踢出,因为它是第一个进入内存的.
2022-12-01 22:40:58
1840
原创 虚拟内存系统【如何支持巨大的虚拟地址空间】
的所有页都被交换到了磁盘上,因此它目前没有运行,有一块交换空间是空闲的,通过这个小例子,你应该能够看出,使用交换空间是如何让系统假装比实际物理内存更大.如果存在位设置为1,则表示该页存在于物理内存中,如果存在位设置为0,则表示该页不在物理内存中,而在硬盘中. 访问不在物理内存中的页,这种行为被称为。现在我们在硬盘上有一部分交换空间,需要在系统中增加一些机制,来支持从硬盘交换页.但是,我们要支持页可以从内存交换到磁盘,必须添加更多的机制,都只有一部分有效页在内存中,剩下的在硬盘的交换空间中,进程。
2022-12-01 15:28:41
680
原创 LRU Cache【理论讲解 + 代码实现】
LRU是的缩写,意思是最近最少使用. 它是一种Cache替换算法.什么是Cache?狭义的Cache是指位于CPU和主存之间的快速RAM,通常它不像系统主存那样使用DRAM技术,而使用昂贵但较快速的SRAM技术. 广义上的Cache指的是位于速度相差较大的两种硬件之间,用于协调两者数据传输速度差异的结构. 除了CPU与主存之间有Cache,内存与硬盘之间也有Cache,乃至在硬盘与网络之间也有某种意义上的Cache-称为Internet临时文件或网络内容缓存等.
2022-12-01 00:05:19
1262
原创 深入理解死锁问题
你可能在想,上文中提到的这个死锁的例子,很容易就可以避免,例如:只要线程1和线程2都用相同的抢锁顺序,死锁就不会发生,那么,死锁为什么还会发生?运行在同一个处理器上,这种保守的静态方案会明显增加完成任务的总时间,为了避免死锁,没有让它们并发运行,付出了性能的代价.之前,都认为锁是被占有的,多个抢锁操作通常会带来麻烦,因为我们等待一个锁时,持有另一个锁.. 因此,在设计大型系统的锁机制时,你必须要仔细的去避免循环依赖导致的死锁.另一个线程可以采用相同的加锁方式,但是不同的加锁顺序,程序不会产生死锁.
2022-11-28 16:56:04
700
原创 线程池实现
线程过多会带来调度开销,进而影响缓存局部性和整体性能. 而线程池维护着多个线程,等待着管理者分配可并发执行的任务. 这。,线程池不仅能保证内核的充分利用,还能防止过分调度,可用的线程数量应该取决于可用的并发处理器,处理器内核,内存,网络。
2022-11-27 00:26:16
214
原创 多线程编程【条件变量】
调用时,这个互斥量是已上锁状态. wait的职责是释放锁,并让调用线程休眠(原子地).当线程被唤醒时(即另外某个线程发信号给它后),它必须重新获取锁,再返回调用者,这是为了避免线程在陷入休眠时,产生一些。尽管不是所有情况都严格需要,但有效且简单的做法,还是在使用条件变量发送信号时持有锁,虽然上面的例子是必须加锁的情况,但也有一些情况可以不加锁,但为了简单,请在调用。让我们来看看生产者和消费者之间的信号逻辑,当生产者想要填充缓冲区时,它等待缓冲区变空,消费者具有完全相同的逻辑,但等待不同的条件-变满.
2022-11-26 20:07:37
1311
原创 常见磁盘调度算法总结
在现代系统中,磁盘可以接受多个分离的请求,它们本身具有复杂的内部调度程序(它们可以准确地实现SPTF.在磁盘控制器内部,所有相关细节都可以得到,包括精确的磁头位置). 因此,操作系统调度程序通常会选择它认为最好的几个请求(如 16),并将它们全部发送到磁盘。磁盘然后利用其磁头位置和详细的磁道布局信息等内部知识,以最佳可能(SPTF)顺序服务于这些请求.磁盘调度程序执行的另一个重要相关任务是I/O 合并(I/O merging).
2022-11-22 17:29:10
2068
原创 Trie字典树详解
Trie树,又叫字典树,前缀树(Prefix Tree),单词查找树,是一种多叉树的结构.上图就是一颗Trie树,表示了关键字集合根节点不包含字符,除根节点外每一个节点都只包含一个字符从根节点到某一节点,路径上的字符连接起来,为该节点对应的字符串每个节点的所有子节点包含的字符都不相同.算法核心:利用字符串的公共前缀来减少查询时间,最大限度的减少无畏字符串的比较.单词检索统计和排序字符串字符串前缀搜索我们来看一个场景:当我们在浏览器的搜索框中打出一个字符串的前缀时,它便实时的单词自动补齐.对于。
2022-11-22 16:16:20
2105
原创 一致性哈希算法【图解理论 + 代码实现】
简单来说,就是比如现在我们来了一个用户请求,假如它叫张三,并被负载均衡到2号服务器上,那么2号服务器就保存了他的登录状态信息,但是如果下一次张三发出请求,他又被映射到了一号服务器上,但一号服务器上没有保存有关张三的会话信息,那么1号服务器怎么知道张三的登录状态呢?例如,服务端需要增删查看数据,如果服务端直接去数据库中查找,效率太低,所以我们需要将一些热点数据先缓存起来,以便下次查找时提高效率,假设现在我们以用户id作为。所以,综合上述的两个场景可以看出,普通的哈希算法是存在许多问题的,所以我们需要引入。
2022-11-21 18:40:54
1278
原创 结构体内存对齐详解
数据结构(尤其是栈)应该尽可能在自然边界上对齐,原因在于:为了访问未对齐的内存,处理器需要做两次访问,而对齐的内存仅需要一次访问.不是所有的硬件平台都能访问到任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。结构体的总大小为12字节。在设计结构体的时候,我们。
2022-11-17 01:44:46
239
原创 进程调度算法详解
例如,如果一个工作不断放弃CPU去等待键盘输入,这是交互型进程的可能行为,MLFQ因此会让它保持高优先级,相反,如果一个工作长时间的占用CPU,MLFQ会降低其优先级,通过这种方式,MLFQ在进程运行过程中学习其行为,从而利用工作的历史来预测它未来的行为.A(黑色)在最低优先级队列执行(长时间运行的CPU密集型工作),B(灰色)在时间T = 100时到达,并被加入最高优先级队列,由于它的运行时间很短,经过两个时间片,在被移入最低优先级队列之前,B执行完毕,然后A继续运行.如果 B 是交互型工作,
2022-11-15 23:27:02
2913
原创 Linux进程控制【概念 + 代码演示】
创建子进程后,子进程执行的是父进程的代码片段,如果我们想要创建出的子进程,执行全新的代码片段呢?函数是非常重要的函数,它从已存在进程中创建一个新进程,新进程为子进程,而原进程为父进程.如果我们使用fork创建一个子进程,子进程执行程序替换,会不会影响父进程呢?所以,在程序的任意位置调用exit()函数,进程就会立即退出,不会再执行。:若为正常终止子进程返回的状态,则为真(查看子进程是否正常退出)函数内部拿出子进程的退出信息,那么,它具体是从哪里拿到的呢?,不予以等待,若正常结束,则返回该子进程的。
2022-11-08 00:11:29
443
原创 Linux【进程地址空间】
首先,这段空间它并不是内存,它是操作系统提供的一个易用的物理内存抽象,叫做地址空间. 通过这个物理内存抽象,我们可以让每个进程都认为它有这么一段供自己使用的空间,但是它并不是真实的物理空间,那么真实的物理空间在哪里呢?因为各进程分配的只不过是虚拟内存的页面,这些页面的数据可以映射到物理页面,也可以临时保存到磁盘上而不占用物理页面,在磁盘上临时保存虚拟内存页面的可能是一个磁盘分区,也可能是一个磁盘文件,称为交换设备。的空间,实际上,在虚拟内存对应的物理内存上,可能只对应一点点的物理内存.
2022-10-29 16:44:01
832
原创 布隆过滤器
布隆过滤器的思想是将一个元素用多个哈希函数映射到一个位图中,因此被映射到的位置的比特位一定为1,所以可以按照下列方式进行查找:分别计算每个哈希值对应的比特位存储的是否为0,只要有一个0,则该元素一定不在哈希表中,否则可能在哈希表中.比如我们在浏览网站的时候,如果系统发现一个网站不在黑名单中,那它一定不在,就可以浏览,如果在,那可能误判,可以再去白名单中查找一遍。所以,简单的将要删除的数的比特位置1,是不行的.所以,我们可以试着采用存计数的方式去来支持删除元素,的文件,快速判断一个。
2022-10-29 15:49:41
943
原创 位图【概念 + C/C++实现】
加载8次,然后每加载一次都进行查找.在这个过程中,我们需要8次从磁盘将数据加载进内存,这是IO操作,所以会非常慢,而且遍历查找时间复杂度。给40亿个不重复的无符号整数,没排过序. 给一个无符号整数,如何快速判断一个数是否在这40亿个数中?,所以我们不可能一次性将它加载进内存,所以只能将这些数据分批加载,比如一次加载。但是40亿个整数,假设在32位机器下,40亿整数所占空间为。由于文件中的数据不支持随机访问,所以也不可行。
2022-10-28 21:33:12
712
原创 C++异常机制
有可能单个的catch不能完全处理一个异常,在进行一些校正处理后,希望再调给外层的调用函数来处理,catch可以通过重新抛出异常将异常传递给更上层的函数来处理.异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛异常,让函数的直接或间接的调用者来处理这个错误.如果有一个块抛出一个异常,捕获异常的方法会使用。块中的代码被称为保护代码,使用。所以:在实际中,我们可以去继承。块中放置可能抛出异常的代码,类实现自己的异常类.
2022-10-24 21:43:05
1093
原创 Linux【环境变量】
例如:我们在编写C/C++代码时,在链接的时候,我们并不知道所链接的动静态库在哪里,但是照样可以链接成功,生成可执行程序,原因就是。命令行中,会有这样一种现象,shell命令行中的可执行程序。,可以直接运行,但我们自己的可执行程序却不能,必须指定路径。当我们运行这个程序时,发生它什么都没打印,那就说明环境变量。环境变量通常具有某些特殊用途,在系统中通常具有全局特性。其实,这也是环境变量在作用的表现,表示要查看的环境变量的名称。第一种:通过命令行参数。
2022-10-18 00:45:17
115
原创 C语言常用字符串函数及模拟实现
1. 字符串函数总结2. 字符分类函数总结3. 字符串函数模拟实现📖3.1 模拟实现strlen📖3.2 模拟实现strcpy📖3.3 模拟实现strcat📖3.4 模拟实现strstr📖3.5 模拟实现strcmp📖3.6 模拟实现memcpy📖3.7 模拟实现memmove字符串已'\0'作为结束标志,strlen函数返回的是在字符串中'\0'前面出现的字符个数(不包含'\0')参数指向的字符串必须要以’\0’结束函数的返回值为size_t(无符号)} else {}函数。
2022-10-16 00:14:32
650
原创 红黑树【C/C++实现】
/节点存储的数据 Color _color;//节点的颜色 };//节点存储的数据 Color _color;//节点的颜色 };红黑树插入
2022-10-13 01:14:14
579
2
原创 C++【内存管理】
;//C语言的申请方式 A * p1 =(A *) malloc(sizeof(A));free(p1);free(p2);//C++申请方式 A * p3 = new A(2);}注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc和free不会.new和delete是用户进行动态内存申请和释放的操作符,和是系统提供的全局函数,new在底层调用全局函数来申请空间,delete在底层调用。
2022-10-10 12:43:49
411
原创 Linux shell的展开模式【实操演示】
在默认情况下,单词分割机制会在单词中寻找空格,制表符,和换行符,并把它们看作单词之间的界定符。这意味着无引用的空格,制表符和换行符都不是文本的一部分,它们只作为分隔符使用。由于它们把单词分为不同的参数,所以在上面的例子中,命令行包含一个带有四个不同参数的命令。花括号表达式本身可能包含一个由逗号分开的字符串列表,或者一个整数区间,或者单个的字符的区间。一旦加上双引号,我们的命令行就包含一个带有一个参数的命令。如果我们试一下在之前的章节中使用的技巧,我们会看到它们实际上是展开。......
2022-08-27 23:24:53
832
2
原创 C++从代码到可执行程序经历了什么?【操作系统面试题】
语法分析器只是完成了对表达式语法层面的分析,语义分析器则对表达式是否有意义进行判断,其分析的语义是静态语义——在编译期能分期的语义,相对应的动态语义是在运行期才能的语义。汇编器的汇编过程相对于编译器来说更简单,没有复杂的语法,也没有语义,更不需要做指令优化,只是根据汇编指令和机器指令的对照表一一翻译过来,汇编过程有汇编器。:但是静态链接的优点就是,在可执行程序中已经具备了所有执行程序所需要的任何东西,在执行的时候运行速度快。,将文件内容替换到它的位置,这个过程是递归进行的,文件中包含其他文件。...
2022-08-27 01:24:44
260
2
原创 Linux权限管理【理论讲解+实操演示】
这篇文章会对Linux中权限的概念以及权限管理进行讲解,着重讲解Linux中对文件权限的管理,通过在Linux系统中进行演示来介绍关于对文件权限的各种操作,比如设置文件权限、文件权限的修改等.还有关于一些关于目录权限、粘滞位的介绍
2022-08-25 15:56:53
504
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人