- 博客(97)
- 收藏
- 关注
原创 Linux47:网络基础+Socket编程预备
• TCP/IP 协议的本质是一种解决方案• TCP/IP 协议能分层,前提是因为问题们本身能分层网络的引入导致距离变长了,所以我们引入协议来解决问题所以究竟什么是协议?协议本质:就是约定好的结构体问题:主机 B 能识别 data,并且准确提取 a=10,b=20,c=30 吗?回答:答案是肯定的!因为双方都有同样的结构体类型 struct protocol。也就是说, 用同样的代码实现协议,用同样的自定义数据类型,天然就具有”共识“,能够识别 对方发来的数据,这不就是约定吗?关于协议的朴素理解。
2026-03-24 20:19:26
562
原创 Linux44+45:日志和线程池
是一种常用的软件设计模式,用于确保一个类只有一个实例,并提供一个全局访问点来获取这个实例。这种模式在多线程环境中尤其有用,因为它可以确保资源的唯一性和线程安全。
2026-03-24 19:08:38
350
原创 Linux44:POSIX信号量:
1.回顾一下相关概念POSIX信号量是一个标准,和System V是一样的。信号量概念:信号量本质是一个计数器,是对特定资源的预定机制。----->申请信号量成功,预定资源。
2026-03-19 13:53:57
420
原创 Linux:45线程同步lesson33
2-1 条件变量• 当⼀个线程互斥地访问某个变量时,它可能发现在其它线程改变状态之前,它什么也做不了。• 例如⼀个线程访问队列时,发现队列为空,它只能等待,只到其它线程将⼀个节点添加到队列 中。这种情况就需要⽤到条件变量。2-2 同步概念与竞态条件• 同步:在保证数据安全的前提下,让线程能够按照某种特定的顺序访问临界资源,从⽽有效避免 饥饿问题,叫做同步• 竞态条件:因为时序问题,⽽导致程序异常,我们称之为竞态条件。在线程场景下,这种问题也 不难理解高频的申请锁和释放锁,但不作为,
2026-03-19 09:43:28
351
原创 高并发内存池
所谓“池化技术”,就是程序先向系统申请过量的资源,然后⾃⼰管理,以备不时之需。之所以要申请过量的资源,是因为每次申请该资源都有较⼤的开销,不如提前申请好了,这样使⽤时就会变得⾮常快捷,⼤⼤提⾼程序运⾏效率。类比生活费,与每天索取相比,一个月一次给完的效率更高。在计算机中,有很多使⽤“池”这种技术的地⽅,除了内存池,还有连接池、线程池、对象池等。以服务器上的线程池为例,
2026-03-05 10:01:49
386
原创 Linux:缓冲区_glibc封装
本来,./a.out是要通过stout在显示器上显示的,但是由于文件描述符1被log.txt占用导致,原先在stdout显示的,只能显示显示在文件中,这样完成了写入,这也是重定向的原理。printf, write向C语言缓冲区写入,但后面close(fd), 关闭后, 进程退出,由于fd被关闭了,找不到对应fd地内核缓冲区,所以无法打印。1.外设,磁盘,显示器等,一定有读写方法,但是实现方法不一样,一切外设设备都需要读写。(2)./a.out > log.txt, 是普通文件,则是全缓冲,子进程的。
2025-12-20 20:44:12
914
原创 Linux:基础IO(18+19)+文件描述符
struct file 表示被打开的文件, 对文件的管理就变成了对struct file链表的增删查改。文件打开 -- 内核创建struct file内容加载到文件缓冲区, 属性初始化到struct file系统初始化,创建一个文件描述符表:struct files_struct里面包含一个对象, struct file* fd_array[]指向不同的被打开的文件。文件描述符的本质就是数组下标。
2025-12-18 19:30:42
635
原创 Linux:进程控制
退出码(退出状态)可以告诉我们最后⼀次执⾏的命令的状态。在命令结束以后,我们可以知道命令 是成功完成的还是以错误结束的。其基本思想是,程序返回退出代码 0 时表⽰执⾏成功,没有问题。代码 1 或 0 以外的任何代码都被视为不成功。
2025-12-17 17:49:05
686
原创 Linux:环境变量
如:我们在编写C/C++代码的时候,在链接的时候,从来不知道我们的所链接的动态静态库在哪 ⾥,但是照样可以链接成功,⽣成可执⾏程序,原因就是有相关环境变量帮助编译器进⾏查找。环境变量通常具有某些特殊⽤途,还有在系统当中通常具有。
2025-12-15 18:51:26
686
原创 Linux:44线程互斥lesson32
原则:尽量加锁的范围粒度要细,尽量不要加太多非临界区代码我们用swap,exchange将内存中的变量,交换到CPU的寄存器中“本质是当前线程/进程,在获取锁,因为是交换,不是拷贝,所以1只有1份,所以谁申请到,谁的al > 1,mutex就jiaohuan谁持有锁”锁就是mutex的内容1,谁的%al持有1,谁就持有锁。释放锁,就是向mutex里面写1就可以了。代码3:自动释放锁。
2025-05-11 11:02:11
872
原创 Linux:41线程控制lesson29
1. 如果thread线程通过return返回,value_ptr所指向的单元⾥存放的是thread线程函数的返回值。2. 如果thread线程被别的线程调⽤pthread_cancel异常终掉,value_ptr所指向的单元⾥存放的是常 数PTHREAD_CANCELED。3. 如果thread线程是⾃⼰调⽤pthread_exit终⽌的,value_ptr所指向的单元存放的是传给 pthread_exit的参数。
2025-04-23 20:52:32
1197
原创 Linux:42线程控制lesson30
ID:线程控制块的起始地址返回值:线程执行完,的返回值,被join回收分离:joinable = 0线程分离joinable!=0,线程不分离joinable线程标记位。
2025-04-23 20:51:00
913
原创 Linux:40线程理解_页表转换
让我们现在总结⼀下:单级⻚表对连续内存要求⾼,于是引⼊了多级⻚表,但是多级⻚表也是⼀把双 刃剑,在减少连续存储要求且减少存储空间的同时降低了查询效率。有没有提升效率的办法呢?计算机科学中的所有问题,都可以通过添加⼀个中间层来解决。MMU 引⼊ 了新武器,江湖⼈称快表的 TLB (其实,就是缓存) 当 CPU 给 MMU 传新虚拟地址之后, MMU 先去问 TLB 那边有没有,如果有就直接拿到物理地址发到 总线给内存,⻬活。
2025-04-21 10:14:35
830
原创 Linux:39内核与用户--信号-lesson28
DFL:默认。子进程给父进程发送,SIG_CHLD,父进程处理用的是缺省 的ign如果不理解可以认为:两种是不一样的系统默认->僵尸手动默认->可以做到后面的20分钟方案一和方案二。
2025-04-13 21:13:56
1025
1
原创 Linux:38信号捕捉_穿插中断
a.处理信号的合适时机:进程由内核态返回到用户态的时候b.如果是默认/忽略:照常c.捕捉过程,实际上就如右上所示当执行自定义方法的时候,要进行身份切换(由内核态转化为用户态,以免在用户态写一些非法操作需要(内核权限才可以进行的操作))
2025-04-13 15:43:53
829
原创 Linux:35.其他IPC和IPC原理+信号量入门
---------------------------------------------------------------------------------------------------------------------------------这种相似性,叫做system V标准。 ----------------------------------------------------------------------------------------------------------
2025-04-12 20:20:29
721
原创 Linux:37信号lesson26
信号量集第一个成员*sem.base:起始信号量可以malloc多个信号量sem_nsems:有多少个信号量。
2025-04-12 19:53:29
1156
原创 图论:多源最短路
1. 状态表⽰: f[k][i][j] 表⽰:仅仅经过[1, k] 这些点,结点i ⾛到结点j 的最短路径 的⻓度。2. 状态转移⽅程:• 第⼀种情况,不选新来的点: f[k][i][j] = f[k - 1][i][j];• 第⼆种情况,选择新来的点: f[k][i][j] = f[k - 1][i][k] + f[k - 1][k][j],i->k的路径+k到j的路径之和,把k作为中转点。找以k为中转点,i到j是否存在更小的路径,存在的话,那就更新,不在的话,那就维持原判。
2025-04-07 16:47:49
730
原创 图论:拓扑排序
拿最大的进行更新,因为大的做完了,小的也就做完了。记录ret:是餐厅里的摄像头,in不为0。加了一个标记要砸坏的bool st[]进队列:是餐厅里的摄像头,并且没有前辈。最短时间,所有情况下,取最大值。
2025-04-07 16:43:36
535
原创 图论:最小生成树
由于克鲁斯卡尔算法要把所有的边进行排序没所以我们要创建一个起点,终点,边的结构体。dfs:把所有的路径都找到。(遍历到一条边就加入路径)瓶颈树:生成所有生成树中,最大边权值最小的那棵树。用胶囊把所有可以到的点统计到。->生成最小生成树。最小生成树:利用dfs找到的路径据生成最小生成树。距离最短->所有距离的总和。--->最小生成树。选边的时候,优先去往高的位置的边,其次才是距离。最小生成树的最大边值也就是最终结果。题目没有明确给出那就自己创建。
2025-04-07 16:41:58
813
原创 图的储存+图的遍历
和树的存储⼀模⼀样,只不过如果存在边权的话,我们的vector数组⾥⾯放⼀个结构体或者是pair即 可。和树的存储⼀模⼀样,只不过如果存在边权的话,我们多创建⼀维数组,⽤来存储边的权值即可。
2025-04-07 16:39:53
429
原创 动态规划:区间dp
k把点分成左右两端,左端的代价,加右端的代价,加把两个合在一起的代价和f[i][j]一起取最小值,即可。把f[i][i] 初始化成0,是根据实际,单独一个不需要合并,代价为0。先全部初始化成无穷大,因为避免取最小值时产生影响。处理环行问题的常见技巧:倍增/复写。
2025-04-07 16:06:37
479
原创 动态规划:背包问题
背包问题是动态规划中最经典的问题,很多题⽬或多或少都有背包问题的影⼦。它的基本形式是:给 定⼀组物品,每个物品有体积和价值,在不超过背包容量的情况下,选择物品使得总价值最⼤。背包问题有多种变体,主要包括:1. 01背包问题:每种物品只能选或不选(选0次或1次)。2. 完全背包问题:每种物品可以选择⽆限次。3. 多重背包问题:每种物品有数量限制。4. 分组背包问题:物品被分为若⼲组,每组只能选⼀个物品。5. 混合背包:以上四种背包问题混在⼀起。
2025-04-07 16:04:48
1517
原创 动态规划:经典线性dp
f[i][j]表示:s的【1,i】区间内,以及t的【1,j】区间内,所有子序列中,最长公共子序列。增加:也就是[ i ] 变成 [ j - 1],把b[j] 插入到 [i]后面 ,i++,j不变。跟上面的类似,f[i][j]是指把1-i变成到1-j的最小操作数。a[i] == a[j]相等->那就前面的操作数一样。删除:也就是[ i - 1] 编程[ j ]修改 :[i- 1] 变成 [ j - 1]到 1~i-1和1~j-1找最长公共子序列。(1)1~i+1~j-1里面拿。根据实际意义进行初始化。
2025-04-07 16:01:38
453
原创 第四章:动态规划
比方说,我们要凑 j = 1,a[i] = 9, a[i]%5 == 4, j - a[i] = -3,我们本来是要找-3的位置的,使得取模 == 1但是我们是找不到的,但是我们可以反向的向前找2,4+2 == 6 ,取模 == 1。4. 输出具体⽅案。f[i][j]表示:s的【1,i】区间内,以及t的【1,j】区间内,所有子序列中,最长公共子序列。选,就找[j - a[i]]的,注意,这里会出现负数的情况,但在这道题中,负数也是有意义的。然后用f[i][j-b[i]]+w[i]替代max的第二部分!
2025-03-30 15:20:51
1263
原创 Trie树(字典树)/(前缀树)
注意:(1)在一条边上存字符(2)如果前缀相同的话,就可以实现复用。(3)从根节点出发到某个节点的路径就代表一个字符串(4)有->复用没有->创建(5)维护信息:pass:标记当前节点一共经过多少次end:b=标记当前节点是以多少个字符串作为结尾。
2025-03-23 18:17:21
410
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅