- 博客(139)
- 收藏
- 关注
原创 传输层协议UDP
UDP是在网络协议中传输层的一种协议。它位于操作系统内部。我们在网络基础那里了解过,UDP是一种无连接,不可靠,面向数据报的协议,其设计目标是高效传输数据,而非保证可靠性。它直接将应用层数据封装成UDP数据报发送,不建立连接,不确认数据,不重传丢失报文,适用于对实时性要求高(如直播)或数据量小(如DNS查询)的场景。
2025-05-18 22:06:44
925
原创 应用层协议http
在互联网世界中,HTTP(HyperText Transfer Protocol,超文本传输协议)是一个至关重要的协议。它定义了客户端(如浏览器)与服务器之间如何进行通信,以交换或传输超文本。
2025-05-17 18:36:54
1123
原创 【Linux】序列化与反序列化、会话与进程组、守护进程
协议其实就是结构化的数据。但是再网络通信中,我们不直接发送结构化的数据给对方。我们一般会将,然后通过网络在发送出去。而接收方收到之后,要对,即还原成结构化的样子。那么我们可以直接发送二进制对象么,这个结构化数据双方都能认识啊?可以,但不建议。可以是因为在操作系统内部,协议都是直接传递的结构体,因为所有的操作系统都是C语言写的。不会存在差异。不建议是因为通信双方可能是不同的语言实现的,这导致它们对结构体的对齐规则可能有差异。导致接受的数据可能不完整。
2025-05-16 18:01:38
804
原创 【Linux】网络基础与socket编程基础
协议其实就是一个结构体!!!在两个主机在进行通信的时候,其实就是A主机填充结构化数据,然后通过网络协议栈发送到网络,再通过网络发送到B主机的网卡。B主机在从底向上将该结构化数据拿出来,因为该结构体是一个协议,所以AB主机都能认识,B主机就可以拿到A主机发送的结构化数据。因为协议是分层的,所以每一层都有协议,同层之间可以认识对方的协议。
2025-05-15 21:33:22
1002
原创 【Linux】日志与策略模式、线程池
在了解了线程的基本概念和线程互斥与同步之后,我们可以以此设计一个简单的线程池。线程池也是一种池化技术。提前申请一些线程,等待有任务时就直接让线程去执行,不用再收到任务之后再创建线程。
2025-05-04 11:44:58
841
原创 【Linux】线程同步与互斥
在生产者和消费者模型中,一共有三种关系(生产-生产,消费-消费,生产-消费),两种角色(生产者和消费者,都由线程来承担),1个交易场所(1个共享的内存空间)。
2025-05-02 14:18:35
809
原创 【Linux】线程
我们可以想想之前的FILE* fp = open;打开一个文件,其实就是为我们申请了一个FILE结构体对象,充当用户级缓冲区。所以对于在库中定义了线程,可以理解为我们使用pthread_create创建一个新线程,本质上就是为我们申请了一个strcut tcb结构体对象。我们之间还说过,线程共享地址空间,但仍有自己独立的资源。比如独立的栈空间,独立的存储位置。
2025-04-27 16:51:52
631
原创 【Linux】信号
我们将1~31号信号全部都进行自定义步骤,然后借助shell脚本,向该进程发送1~31号信号,判断那些信号会被自定义捕捉,那些信号不会!std::cout << "我是" << signal << "号信号" << std::endl;int main()// 自定义捕捉所有的普通信号i<32;return 0;i=1;sleep 1;((i++));done我们看上图,9号信号和19号信号是不可以被自定义捕捉的。
2025-04-21 22:30:47
1100
原创 【Linux】进程池bug、命名管道、systemV共享内存
我们在之前进程池的创建中是通过循环创建管道,并且让子进程与父进程关闭不要的读写段以构成通信信道。但是我们这样构建的话会存在一个很深的bug。我们在销毁进程池时是先将所有的信道的写端关闭,让其子进程read返回值为0,并退出,此时我们在进行等待子进程,就完成了销毁的行为。按照我们实现的逻辑图来看,我们可以对一个信道先进行关闭在进行子进程的回收,然后再对下一个信道进行关闭操作。但是因为这个bug的存在,如果我们将关闭信道和回收子进程放在一起时,就会导致进程死循环。
2025-04-15 19:46:24
855
原创 二叉树——队列bfs专题
我们之前遇到过二叉树的层序遍历,只需要用队列先进先出的特性就可以达到层序遍历的目的。而这里不是二叉树,也就是说让节点的孩子入队列时不仅仅是左右孩子了,而是它的所有孩子。而我们看这棵多叉树的构造,它的孩子是存储在数组中的。所以我们在让孩子入队时只需要依次让数组中的所有节点入队列即可。而这道题的要求是返回一个二维数组,数组的元素就是每一层的层序遍历结果。
2025-04-06 22:04:42
586
原创 【Linux】进程间通信、匿名管道、进程池
是指在操作系统中,不同进程之间进行数据交换和同步的机制。由于每个进程通常拥有独立的内存空间,进程间无法直接访问对方的内存,因此需要通过特定的机制来实现通信和协作。
2025-04-05 22:25:17
622
原创 【Linux】ELF文件与库的加载
了解了动静态库的制作与使用后,我们直到库本质上就是.o文件的集合。我们在开发过程中,也经常将所有的源代码先编译成.o后统一进行链接,为什么不直接将所有的.c源文件编译成可执行程序呢?
2025-04-02 18:43:25
1060
原创 【Linux】动静态库的制作与使用
我们学习c/c++至今,每一次代码的编写都使用到了c/c++的标准库。库其实就是将一些常用的方法总结了起来,并进行实现,之后当我们再需要使用该方法时,就直接使用库中实现好的即可。所以,库其实就是常用方法的二进制集合。本质上,库是一种可执行代码的二进制形式,可以被操作系统载入内存执行。静态库Linux(.a) windows(.lib)动态库Linux(.so) windows(.dll)1.动静态库中,其实根本不需要包含main函数,所有的库不论动静,本质上都是源文件对应的.o目标文件。
2025-03-31 17:00:43
821
原创 【Linux】Ext文件系统
在之前,我们已经了解了进程以及文件IO方面的知识,但是这些都是在内存中进行的。而文件在加载到内存之前都是存储在外设——磁盘(disk)中的。那文件是怎么在磁盘中存储的呢?我们在下面一起讨论。
2025-03-30 10:59:09
753
原创 【Linux】基础IO
首先我们已经知道,在Linux下,一切皆文件。文件 = 文件内容 + 文件属性,所以一个文件的内容为0kb,但是其也占磁盘空间。所以对文件的操作其实就是对文件的内容和属性进行一系列的操作。对文件操作,需要先打开文件,而打开文件的不是别人就是进程。所以对文件的操作,本质上是进程对文件操作。一个进程有可能同时会打开多个文件,且一个文件可能同时被多个进程打开。所以操作系统要对打开的文件进行管理——先描述,在组织。C语言里面的库函数fopen/fclose等文件操作的函数,本质上是对系统调用的封装。
2025-03-27 13:02:49
1068
原创 自定义minshell
我们在前面已经了解了进程的概念,以及如何进行进程控制。接下来我们就使用这些知识,来自己实现一个shell即命令行解释器!!!
2025-03-24 21:26:35
719
原创 进程控制~
我们可以通过./cmd来运行我们的程序,而我们运行的程序就是bash进程常见的子进程。当然我们也可以通过fork()系统调用来创建进程。NAMESYNOPSISfork会对子进程和父进程返回不同的返回值,对子进程返回0,对父进程返回子进程的pid,如果返回值小于0,则说明子进程创建失败。
2025-03-19 21:04:17
860
原创 栈(LIFO)算法题
注意,我们需要重复处理,而不是处理一次相邻的相同元素就结束了。对示例来说,如果只进行一次处理,结果为aaca,但是处理之后又出现了相邻的重复元素,我们还得继续处理,最后结果就是ca。解法:借助栈来模拟我们可以将字符串中的元素依次入栈,元素入栈前判断是否与栈顶元素相等,如果相等就弹出栈顶元素,继续判断下一个元素。等到字符串全部入栈,栈中的就是最终答案。但是我们没有必要弄一个stack出来,因为这样最终结果是逆序的,我们可以采用string来模拟栈的行为。
2025-03-16 22:08:23
721
原创 字符串算法题
题目要求找出所有字符串的公共前缀,如果没有公共的前缀就返回空字符串。我们以第一个字符串为标准,依次比较所有字符串的每一位,如果都相同,则比较下一个位置,如果不同,那么前一个位置就是最长的公共前缀。在纵向比较的时候要避免越界,因为第一个字符串的长度有可能比后面的字符串长,所以除了字符不相等外,i越界,也是一个判断条件。两个两个字符串进行比较,用它们得出的前缀和与第三个字符串继续比较。重复该过程。如果在某一个比较过程中发现前缀和的长度变为0,那就说明所有字符串没有公共的前缀和。
2025-03-16 20:57:40
894
原创 【Linux】进程
按课本上来说,一个正在执行的程序的实例就是一个进程;按操作系统内核来说,使用了CPU资源的实体,就是一个进程。这样说还是有点抽象。程序其实就是一个又一个的二进制文件,当它们还没有被运行时存储在磁盘中,所以我们通过./cmd的方式,将它们加载到了内存中,此时内存中就会有一份该程序的代码和数据的拷贝,那么一个程序被加载到了内存中是否就是一个进程呢?首先我们要知道的是,可能同时有多个程序被加载到了内存中如果这些都是进程的话,那么操作系统就要对这些进程管理,而操作系统对任何软硬件的管理都是先描述在组织。
2025-03-15 16:34:05
680
原创 哈希表算法题
因为数组是无序的,所以我们无法直接使用双指针。找两个数之和为target,我们可以固定一个数x,然后在其前面找有没有一个数等于target-x。如果没有,我们x就走到下一个位置。然后重复找前面有没有一个数等于target-x的过程。这个算法是否正确呢?答案是肯定的。因为如果我们从后往前看的话,就知道,其实就相当于是个反向的暴力。我们在反向遍历的过程中,一直在找该数的前面有没有target-x的这个数出现过。
2025-03-15 12:34:40
564
原创 链表算法题目
cur2指向头节点,cur1指向空,然后用cur2遍历原链表,遍历的同时,让cur2的next指向cur1,实现逆置,然后让cur1走到cur2的位置,然后cur2走到下一个位置。所以我们也要保证进位不为0。返回的过程中,将该层的head的next的next指针指向自己即head的前一个节点的next指针指向自己,此时就达到了后一个指向前一个,接着将head的next指针指向空,避免成环。简单来说,对于原链表来说,每两个一组的节点,第一个节点是新链表的第二个节点,第二个节点是新链表的头节点。
2025-03-08 21:20:39
948
原创 【Linux】冯诺依曼体系结构-操作系统
我们所使用的计算机,如笔记本等都是按照冯诺依曼来设计的:截止目前,我们所知道的计算机都是由一个一个的硬件组装起来的,这些硬件又由于功能的不同被分为了输入设备,输出设备,存储器和cpu。:键盘,鼠标,话筒,摄像头,网卡,磁盘等等……:显示器,网卡,磁盘,打印机等等……而存储器其实就是我们所说的内存,而CPU是由运算器和控制器组成的。
2025-03-04 16:48:51
878
原创 分治——快速排序算法题
分治解决问题的思想就是大事化小,将一个大问题分解成若干个子问题。这道题其实就是让我们对数组进行操作,使操作之后的数组呈现出三段区间[0,left],[left+1,right-1],[right,size-1],这三个区间的元素分别都是0,1,2.既然是进行数组分块,我们就可以使用双指针的思想来解决:首先定义一个指针i;然后在分别创建两个指针和我们的目的是将数组分为三块,。
2025-02-24 17:08:48
970
原创 模拟算法题
模拟算法题我们只需要按照题目的意思一步一步走,将这些步骤转换成代码即可题目要求将字符串中所有的问号都改为其他字母,但是要求不能与左右两边的字母重复,返回一种结果即可。遍历原字符串,当遍历到问号时,我们遍历26个英文字母,找到既不与前面相同也不与后面相同的字母,修改该位置,继续遍历。在遍历的过程中需要注意首元素以及尾元素,它们只需要判断相邻的一个元素即可,要避免越界访问。
2025-02-06 18:12:20
722
原创 位运算算法题
法一:我们直接借助一个字符数组来模拟哈希表统计字符串即可,并且我们没有必要先将所有字符都放入字符数组中,边插入边判断,当我们要插入某个字符的时候,发现其已经出现了,此时必然重复,直接返回false。法二:因为字符串只包含26个小写字母。我们可以用一个int变量的26个bit位来依次表示26个小写字母。0表示没出现,1表示出现,如果遍历到那个字符,发现其对应的二进制位为1,表示该字符重复出现,返回false。我们首先定义一个int变量mark来记录字符的出现次数。
2025-02-02 17:40:50
986
原创 基础位运算
左移操作符,使二进制向左边移动指定位数,同时在其右侧补0左移操作符可以用来提高乘法的效率:2*n -> 1<<n,x*2*n -> x << n。
2025-01-30 21:08:34
768
原创 前缀和——矩阵区域和
我们这里的mat数组是从0,0位置开始的。而我们在预处理dp数组时,为了避免边界情况(计算后的下标小于0),下标是从1,1开始的。所以我们在预处理时加最后的d时,其实对应的是mat数组的mat[i-1][j-1]还有就是使用dp数组时,answer返回数组的下标是从0,0开始的,而dp数组从1,1开始才是有效数据。就如示例一种answer的(0,0)位置的值,它的左上下标已经越界了,所以我们要对其进行处理。题目所求的矩阵, 本质就是需要求一段矩阵的和,所以快速求矩阵的和我们就可以使用二维前缀和来解决问题。
2025-01-26 16:39:55
1013
原创 前缀和——连续数组
因为最终结果ret = i - dp[sum].说明此时(0,i)这个区间满足要求,长度是i+1.而直接用公式i-mp[sum] = i.为了满足结果,所以dp[0] = -1.但是我们在遍历的过程中,可能有很多相等的sum,它们对应的下标不同,但是如果哈希表中已经有了sum,就没必要再插入了,因为后面插入的sum对应的下标更大,最终的结果就更小。我们可以对数组进行转换,让我们找0,1相等的数组,我们可以将0变为-1,此时问题就转变为求和为0的最长的子数组。经过转换,这道题就类似于求和为k的子数组了。
2025-01-24 17:01:33
326
原创 前缀和——和可被k整除的子数组
所以我们的问题就转化为了,当遍历到i位置的时候,其实sum%k就已知了,我们只需要在(0,i-1)这个区间里面,找有多少个前缀和的余数 == sum%k的即可。还有就是有可能导致漏答案:[-1,2,7] k = 2,当遍历到2时,此时-1%2 = -1,如果不进行修正,2这个答案就漏掉了,但是我们对余数进行修正—— (-1+2)%2 = 1,与当前位置的前缀和1的余数相等。第三点就是C++负数对正数取模,它的结果是一个负数,我们需要对其进行修正,所以我们让其加上一个k,sum%k +k。
2025-01-24 17:00:57
292
原创 前缀和——和为k的子数组
当right走到了结尾之后,此时left++,right又要回到left的位置重新遍历,所以left和right并不是向同一方向移动,所以不能使用滑动窗口解决问题。我们将数组分为两部分,一部分是以i为结尾的子区间,另一部分是x区间,而这两个区间之和就是dp[i],所以满足k+x = dp[i]。所以如果以i为结尾的子数组和为k的话,则x子数组一定满足dp[i]-k。所以我们需要借助一个哈希表,将前缀和存在里面,我们只需要在里面找到有几个和为dp[i]-k的即可。找一段连续的子区间,该子区间的和为k。
2025-01-23 15:35:30
442
原创 初识——【Linux】make和makefile
make和makefile是linux系统里用于自动化编译和构建程序的工具。们通过定义一系列的规则来指定如何编译和链接程序,从而简化了编译过程,尤其是有多个源文件的时候。
2025-01-23 14:47:41
965
原创 前缀和——除自身以外数组的乘积
但是我们需要对数组f,g 数组进行特殊处理,当i分别为0和n-1时,f,g数组会分别越界,所以我们可以对这两个位置进行特殊处理:f[0]表示(0,-1)这个区间的积,该区间不存在,所以我们可以将其置为1。我们要计算某个位置左右区间所有元素的积,那么我们就可以分别记录下左右区间的积,最后将两个值相乘即可。同样,我们借助来个数组来存储f,g。f[i]表示(0,i-1)这段区间的积,g[i]表示(i+1,n-1)这段区间的和。时间复杂度:处理前后缀积数组需要遍历两边数组,最后遍历下标也需要遍历一边数组,综上,
2025-01-21 20:52:36
450
原创 初探——【Linux】程序的翻译与动静态链接
我们所写的C/C++程序计算机是看不懂的,它只认识0101这样的机器码。所以我们就需要借助编译器对这些源代码进行翻译,使之成为计算机能够执行的二进制指令。这个过程通常分为几个关键步骤:预处理、编译、汇编和链接。
2025-01-21 20:12:37
786
原创 前缀和——模板 二维前缀和
A区域就是dp[i-1][j-1],D区域其实就是arr[i][j],现在剩下的就是C和B了。这里的dp[i][j]表示的是从(1,1)~(i,j)这个区间的和。输入一个m行n列的矩阵,然后进行q次操作,每次操作输入4个数,作为两个点的坐标,计算这两个点为对角线的矩阵的和。因为我们这里的下标是从1开始的,所以我们在申请空间的时候,行和列都得多申请一行/列。时间复杂度:处理dp数组时,我们需要遍历一遍数组m*n,接着我们进行q次操作,但是每次操作的时间复杂度都是O(1),所以综上,暴力解法那我们就遍历贝。
2025-01-19 14:18:07
815
原创 【Linux】权限
linux操作系统下有两种用户:超级用户root和普通用户。既然有两种不同的用户那就涉及不同用户的权限问题。而在,所以用户的权限都体现在对文件的操作上。下面我们就来了解一下文件的权限。
2025-01-19 02:30:00
687
原创 前缀和——【模板】前缀和
题目还是很好理解的,先分别输入两个数,一个是数组的长度,一个是操作的次数。我们接着下面的图来分析,要求2~4这个区间的和,其实就是红色线对应区间的值减去绿色线对应的区间的值。题目已经给了我们区间的起始位置和结束位置,我们只需要遍历一遍数组,从子区间的起始位置开始计算,直到子区间的结束位置即可。我们该题下标从1开始,我们开数组的时候开n+1个空间,第一个空间的值赋为0即可,不会影响dp数组和最后的结果。当我们有了前缀和数组,让我们求l~r这个区间的和,其实就是前缀和数组dp[r] - dp[l-1]的结果。
2025-01-18 12:10:59
820
原创 【C++】异常和智能指针
C++11提供了一套新的错误处理机制——异常。在C语言阶段,当程序出现错误时是通过返回错误码来表示程序出错的类型,我们还需要去查询错误码来找到错误,最后才能解决错误。而C++提供的异常机制可以通过try、catch、throw关键字来发现错误,同时抛出一个错误对象,里面包含错误的具体信息,并在catch里面进行解决问题。
2025-01-18 10:38:21
1108
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人