操作系统 && C语言 每日学习记录(day1 ~ day8) 已寄
现在正式工作了,发现之前学的东西,很多一知半解,不通透,准备再好好系统学一些计算机原理的东西,每天学一学,在这里记录一下。
规划(7.17开始):
- 同学分享了个超级好的操作系统课程,每天看个一节:https://www.bilibili.com/video/BV1Cm4y1d7Ur?spm_id_from=333.337.search-card.all.click&vd_source=fc729df7865184f7b78057868a4b83f8
- C语言,虽然算法题写了超级多,但用的C++,具体C语言的很多底层细节,以及工程不晓得,需要更好地学习一下各种关键字,一些函数指针的使用,内存分配,主要是指针
- codeforces,已经闲太久,身为一个ACMer,已经脑子都不用了,那肯定完蛋,开始康复训练,一周两次。一周7天,有2天打CF,剩下5天学习另外的知识。
垃圾博客园,不知道为啥不能放图,更好的操作系统笔记放这里:https://docs.qq.com/doc/DTGRnS3ZZQWNzaWF0
为什么学习,两年后我会怎样呢?这不会只取决于我在工作上做了什么,而是日常里我做什么,保持一种学习的状态,作为一个立志独自流浪的人,我需要有自制力,但一直以来我真是毫无自制力,开始吧。
7.17
第一节:为什么学操作系统
讲的真好!!!讲操作系统的发展,我觉得在学个东西之前必须知道一个东西是干什么的才行,这个老师讲的非常清楚。
- 最开始40年代的需要用大真空管,一栋楼放置4000左右真空管,后来用晶体管,直接变小了。
- 然后再到50年代开始打孔执行,就像《那不勒斯四部曲》里的莉娜做的东西一样,打卡时代,叫做operator jobs system,一个计算机,可能会有多个人想用,这时候就得换卡片,那么就得存储结果,文件系统很自然的就出现了。
- 后来60年代出现集成电路,更大更快的内存,不用换卡片了,这时候有了大内存,但是还是一个CPU,这时候内存里放了好几个程序,那么一个程序运行完了打印出来结果这个闲置的过程干嘛?IO中断这时候自然地出现了。还有了进程的概念,防止一个坏程序又影响另个好的程序,那么就需要隔离开他们,这就是虚拟内存出现的原因。都到这一步了,都能切换了,为什么不固定时间切换呢?就出现了进程调度,multics弄出来了现代操作系统的概念。
- 1970s就时现代操作系统了,有了CISC指令集(中断,IO,异常,MMU),PC机也有了
- 当代就是更复杂的,有GPU,网卡,各种硬件机制,NUMA(Non Uniform Memory Access)
7.18
搞了一场cf,div2:https://codeforces.com/contest/1706 ,太烂拉,焯!!!就写出来两次,尬,写完两题就去看D了。
回想一下,第一题就是给你个数组arr[n],每个数在1~m范围内,给你一个字符串m个B,每次可以使arr[i]或者m+1-arr[i]变成A,求字典序最小的是啥。这玩意都想了20分钟,离谱,就是如果想让第i个和第m+1-i都变成A,那么i和m+1-i的数量大于2就行,如果只有1个,肯定让小的变成A。
第二题,一个数组,相隔偶数个数字可以连起来,求每个数最大能连多长。就一行的dp,我改了3次才改成1行的,无语。dp[x][2],dp[x][01]分别表示在偶数奇数位置上,x能连的最远是多少。直接for(i=1;i<=n;i++){cin>>x; dp[x][i&1] = max(dp[x][i&1], dp[x][!(i&1)]}
剩下的明天白天补掉!!!!!
总结,感觉就是一个东西,就是有思路,感觉就是这个方向,但是就懵逼,康复训练起来!!!
操作系统笔记在腾讯文档看排版更好些:https://docs.qq.com/doc/DTGRnS3ZZQWNzaWF0
7.19
把昨天的C题写了下,非常简单的dp,略。
第二节:操作系统上的程序 (什么是程序和编译器)
-
include其实就是把东西复制过来。GDB,layout src用法。非递归的汉诺塔,
-
什么是程序?状态机,对于C语言来说,变量+栈帧,每个栈帧有pc。对于asm(汇编)就是内存+寄存器。编译器是什么?把源代码的编译器转换成二进制代码的状态机
-
objdump -d -l a.out 用法, gcc -O2 -c test.c && objdump -d test.o
-
看手册的重要性
-
strace可以追踪所有系统调用(syscall) strace ./a.out
-
strace -f gcc a.c可以追踪编译a.c的整个过程。vim里面用%!就相当于在命令行里执行。vim set nowrap可以不换行显示。%s/ , /\r /g 可以把都好和空格换掉
7.20
这一节说的没见过的就是并发,就算你加了锁,也可能越级执行。
第三节:多处理器编程:从入门到放弃 (线程库;现代处理器和宽松内存模型)
-
以状态机的观点看CPU执行:
共享: 全局的变量, 系统调用等库函数
独占: 线程栈帧, thread_local 变量
-
多线程对程序执行流 和 一些默认假设的改变:指令不再具有原子性, 顺序性, 内存一致性
-
现代处理器指令执行:(顺序性也可能会在编译优化下消失) ,单条汇编指令也非原子的它将指令解释为 *μops*
7.21
第四节:理解并发程序执行 (Peterson算法、模型检验与软件自动化工具)
这一节跳着听的,因为一些东西已经知道了,听着很快,讲到那个peterson算法的时候,想了十几秒就懂了,就不用听全部的讲解了,比较方便。
-
peterson算法:AB去上厕所每个人的旗子互相能看到。上厕所前先举起自己的旗子,如果进到厕所里就举起来对方的棋子。开始拉屎前看看厕所外边有没有别人的旗子,如果有就是表示还有人上厕所,没有就直接拉粑粑。如果有的话,看看厕所里的是不是自己的旗子,如果是对的话也可以拉粑粑。这原理是什么呢?关键在于拉粑粑前的看旗子,比如A先到里面了,要拉粑粑,这时候防止B也拉,B举A的旗子,这样B一看不是自己的旗子,就不拉,相同的A看到B让出来了,就可以自己拉粑粑了。
-
所有的并发程序都可以用状态机把所有可能绘制出来,但是一个程序可能非常大,很多内存,用一个结构体把所有状态什么记录下来,追踪所有状态是非常难的,现在就有一些🏅论文就是可以不记录状态画图,这就比较科研了,感兴趣可以看看。
7.25
第五节并发控制:互斥 (自旋锁、互斥锁和 futex)
竟然3天,和朋友吃饭,又感冒吃药,落下了。自旋锁,互斥锁,之前也知道,然后这个futex第一次知道。
- https://developer.aliyun.com/article/6043
-
用户程序每次调用IPC机制都会产生系统调用,程序发生用户态和内核态的切换,futex 的基本思想是竞争态总是很少发生的,只有在竞争态才需要进入内核,否则在用户态即可完成。futex的两个目标是:1)尽量避免系统调用;2)避免不必要的上下文切换(导致的TLB失效等)。具体而言,任务获取一个futex 将发起带锁的减指令,并验证数值结果值是否为0(加上了锁),如果成功则可继续执行程序,失败(为已经占用的锁继续加锁)则任务在内核被阻塞。为相同futex 变量的加锁的任务被阻塞后放在同一个队列,解锁任务通过减少变量(只有一个加锁且锁队列为空)或进入内核从锁队列唤醒任务。
7.26
第六节并发控制:同步 (条件变量、信号量、生产者-消费者和哲♂学家吃饭问题)
这一节也都学过,其中有个比较有意思,最长子序列,如何改成并行的呢?拓扑图!
7.27
Codeforces Round #810 (Div. 2)
三题,说一下B,构成的图,想要保持偶数条边的话,如果总数为奇数,两种方案,一个是删除一个连着奇数边的点,另一个是删除一个边的两个点,这两个点连着的边都是偶数。遍历一遍点和边就得出答案了。