├── img ├── clip_image002.png ├── clip_image004.jpg ├── clip_image006.jpg ├── clip_image008.jpg ├── clip_image010.jpg ├── clip_image012.jpg ├── clip_image014.jpg ├── clip_image016.jpg ├── clip_image018.jpg ├── clip_image020.jpg ├── clip_image022.jpg ├── clip_image024.jpg ├── clip_image026.jpg ├── clip_image028.jpg ├── clip_image030.jpg └── image-20220831174424416.png ├── disk-scheduling ├── img │ ├── image-20220516165413706.png │ ├── image-20220516165427090.png │ ├── image-20220516165439802.png │ ├── image-20220516165509562.png │ └── image-20220516165648074.png ├── Makefile ├── README.md └── main.cpp ├── file-system-call ├── img │ ├── image-20220516194815622.png │ ├── image-20220516194823862.png │ ├── image-20220516194829611.png │ ├── image-20220516194835318.png │ ├── image-20220516194840599.png │ └── image-20220516194846589.png ├── Makefile ├── README.md ├── main.cpp └── mzd.txt ├── page-replacement ├── img │ └── image-20220516201124108.png ├── Makefile ├── README.md └── main.cpp ├── process-management ├── img │ └── image-20220523120506624.png ├── Makefile ├── README.md └── main.c ├── process-communication ├── img │ ├── image-20220524111821698.png │ ├── image-20220524111828171.png │ └── image-20220524111834463.png ├── Makefile ├── README.md └── main.c ├── README.md └── .gitignore /img/clip_image002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image002.png -------------------------------------------------------------------------------- /img/clip_image004.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image004.jpg -------------------------------------------------------------------------------- /img/clip_image006.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image006.jpg -------------------------------------------------------------------------------- /img/clip_image008.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image008.jpg -------------------------------------------------------------------------------- /img/clip_image010.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image010.jpg -------------------------------------------------------------------------------- /img/clip_image012.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image012.jpg -------------------------------------------------------------------------------- /img/clip_image014.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image014.jpg -------------------------------------------------------------------------------- /img/clip_image016.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image016.jpg -------------------------------------------------------------------------------- /img/clip_image018.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image018.jpg -------------------------------------------------------------------------------- /img/clip_image020.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image020.jpg -------------------------------------------------------------------------------- /img/clip_image022.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image022.jpg -------------------------------------------------------------------------------- /img/clip_image024.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image024.jpg -------------------------------------------------------------------------------- /img/clip_image026.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image026.jpg -------------------------------------------------------------------------------- /img/clip_image028.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image028.jpg -------------------------------------------------------------------------------- /img/clip_image030.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/clip_image030.jpg -------------------------------------------------------------------------------- /img/image-20220831174424416.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/img/image-20220831174424416.png -------------------------------------------------------------------------------- /disk-scheduling/img/image-20220516165413706.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/disk-scheduling/img/image-20220516165413706.png -------------------------------------------------------------------------------- /disk-scheduling/img/image-20220516165427090.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/disk-scheduling/img/image-20220516165427090.png -------------------------------------------------------------------------------- /disk-scheduling/img/image-20220516165439802.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/disk-scheduling/img/image-20220516165439802.png -------------------------------------------------------------------------------- /disk-scheduling/img/image-20220516165509562.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/disk-scheduling/img/image-20220516165509562.png -------------------------------------------------------------------------------- /disk-scheduling/img/image-20220516165648074.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/disk-scheduling/img/image-20220516165648074.png -------------------------------------------------------------------------------- /file-system-call/img/image-20220516194815622.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/file-system-call/img/image-20220516194815622.png -------------------------------------------------------------------------------- /file-system-call/img/image-20220516194823862.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/file-system-call/img/image-20220516194823862.png -------------------------------------------------------------------------------- /file-system-call/img/image-20220516194829611.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/file-system-call/img/image-20220516194829611.png -------------------------------------------------------------------------------- /file-system-call/img/image-20220516194835318.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/file-system-call/img/image-20220516194835318.png -------------------------------------------------------------------------------- /file-system-call/img/image-20220516194840599.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/file-system-call/img/image-20220516194840599.png -------------------------------------------------------------------------------- /file-system-call/img/image-20220516194846589.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/file-system-call/img/image-20220516194846589.png -------------------------------------------------------------------------------- /page-replacement/img/image-20220516201124108.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/page-replacement/img/image-20220516201124108.png -------------------------------------------------------------------------------- /process-management/img/image-20220523120506624.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/process-management/img/image-20220523120506624.png -------------------------------------------------------------------------------- /process-communication/img/image-20220524111821698.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/process-communication/img/image-20220524111821698.png -------------------------------------------------------------------------------- /process-communication/img/image-20220524111828171.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/process-communication/img/image-20220524111828171.png -------------------------------------------------------------------------------- /process-communication/img/image-20220524111834463.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zzering/OS-course-design/HEAD/process-communication/img/image-20220524111834463.png -------------------------------------------------------------------------------- /page-replacement/Makefile: -------------------------------------------------------------------------------- 1 | cc = g++ 2 | TARGET =a.out 3 | out=*.out 4 | 5 | $(TARGET): main.cpp 6 | @$(cc) main.cpp -o $(TARGET) 7 | @echo "\nBuild completed successfully" 8 | 9 | clean: 10 | rm $(out) 11 | @echo "\nClean completed successfully" -------------------------------------------------------------------------------- /process-management/Makefile: -------------------------------------------------------------------------------- 1 | cc = g++ 2 | TARGET =a.out 3 | out=*.out 4 | 5 | $(TARGET): main.c 6 | @$(cc) main.c -o $(TARGET) 7 | @echo "\nBuild completed successfully" 8 | 9 | clean: 10 | rm $(out) 11 | @echo "\nClean completed successfully" -------------------------------------------------------------------------------- /disk-scheduling/Makefile: -------------------------------------------------------------------------------- 1 | cc = g++ 2 | TARGET =a.out 3 | out=*.out 4 | 5 | $(TARGET): main.cpp 6 | @$(cc) main.cpp -o $(TARGET) 7 | @echo "\nBuild completed successfully" 8 | 9 | clean: 10 | rm $(out) 11 | @echo "\nClean completed successfully" 12 | -------------------------------------------------------------------------------- /process-communication/Makefile: -------------------------------------------------------------------------------- 1 | cc = gcc 2 | TARGET =a.out 3 | out=*.out 4 | 5 | $(TARGET): main.c 6 | @$(cc) main.c -o $(TARGET) 7 | @echo "\nBuild completed successfully" 8 | 9 | clean: 10 | rm $(out) 11 | @echo "\nClean completed successfully" -------------------------------------------------------------------------------- /file-system-call/Makefile: -------------------------------------------------------------------------------- 1 | cc = g++ 2 | TARGET =a.out 3 | out=*.out 4 | 5 | $(TARGET): main.cpp 6 | @$(cc) main.cpp -o $(TARGET) 7 | @echo "\nBuild completed successfully" 8 | 9 | clean: 10 | @rm $(out) aaa bbb ccc 11 | @echo "\nClean completed successfully" -------------------------------------------------------------------------------- /process-management/README.md: -------------------------------------------------------------------------------- 1 | # process-managment 2 | 3 | #### 一、程序功能 4 | 5 | 父进程使用pipe()建立一个管道,然后调用fork()创建子进程1和子进程2 6 | 子进程1每隔1秒通过管道向子进程2发送数据“I send message x times” 7 | 子进程2从管道读出信息,并显示在屏幕上 8 | 父进程用系统调用signal()来捕捉中断信号,用kill()向两个子进程发出信号,子进程输出如下信息后终止: Child Process 1 is killed by Parent! Child Process 2 is killed by Parent! 9 | 父进程等待两个子进程终止后,释放管道并输出Parent Process is Killed! 10 | 11 | #### 二、设计思路 12 | 13 | 定义两个进程 14 | 定义两个缓存区msg和buffer 15 | 子进程1中输出字符串到msg中,调用write函数将其写入到fd[1]中 16 | 子进程2调用read函数将fd[0]中的数据读入到buffer中, 然后将其输出 17 | 两进程中都使用signal(SIGINT, SIG_IGN);屏蔽系统定义的结束, 通过signal(SIGUSR1, userDefinedSignal);来调用自定义的信号对应的结束的函数 18 | 19 | #### 三、运行结果 20 | 21 | ![image-20220523120506624](img/image-20220523120506624.png) 22 | 23 | -------------------------------------------------------------------------------- /process-communication/README.md: -------------------------------------------------------------------------------- 1 | # process-communication 2 | 3 | #### 一、程序功能 4 | 5 | 1.使用管道来实现父子进程之间的进程通信 6 | 2.使用消息缓冲队列来实现 client 进程和 server 进程之间的通信 7 | 3.使用共享存储区来实现两个进程之间的进程通信 8 | 9 | #### 二、设计思路 10 | 11 | #### 1.通过管道通信 12 | 13 | 定义两个缓存区msg和buffer 14 | 子进程1中输出字符串到msg中,调用write函数将其写入到fd[1]中 15 | 父进程调用read函数将fd[0]中的数据读入到buffer中, 然后将其输出 16 | 17 | #### 2.通过消息缓冲队列通信 18 | 19 | ###### server端 20 | 21 | server 进程先建立一个关键字为 SVKEY(如 75)的消息队列,然后等待接收类型为 REQ(例如 1)的消息; 22 | 在收到请求消息后,它便显示字符串“serving for client”和接收到的 client 进程的进程标识数,表示正在为 client 进程服务; 23 | 然后再向 client 进程发送应答消息,该消息的类型是 client 进程的进程标识数,而正文则是 server 进程自己的标识ID。 24 | 25 | ###### client端 26 | 27 | client 进程则向消息队列发送类型为 REQ 的消息(消息的正文为自己的进程标识 ID) 以取得 sever 进程的服务,并等待 server 进程发来的应答; 28 | 然后显示字符串“receive reply from”和接收到的 server 进程的标识 ID 29 | 30 | #### 3.通过共享缓存区通信 31 | 32 | ###### server端 33 | 34 | server创建共享存储区, 然后获取其首地址, 使用while (*addr == -1)阻塞自身, 用于进程同步 35 | 36 | ###### client端 37 | 38 | client打开共享存储区, 然后获取其首地址, 使用while (*addr != -1)阻塞自身 39 | 40 | #### 三、运行结果 41 | 42 | ![image-20220524111821698](img/image-20220524111821698.png) 43 | 44 | ![image-20220524111828171](img/image-20220524111828171.png) 45 | 46 | ![image-20220524111834463](img/image-20220524111834463.png) 47 | -------------------------------------------------------------------------------- /disk-scheduling/README.md: -------------------------------------------------------------------------------- 1 | # disk_scheduling 2 | 使用FIFO(先来先服务)、SSTF(最短寻道优先)以及SCAN(电梯调度算法)进行磁盘调度 3 | 4 | #### 一、要求 5 | 6 | 1、对于如下给定的一组磁盘访问进行调度: 7 | 请求服务到达 A B C D E F G H I J K L M N 8 | 访问的磁道号 30 50 100 180 20 90 150 70 80 10 160 120 40 110 9 | 2、要求分别采用先来先服务、最短寻道优先以及电梯调度算法进行调度 10 | 3、要求给出每种算法中磁盘访问的顺序,计算出平均移动道数 11 | 4、假定当前读写头在90号,电梯调度算法向磁道号增加的方向移动 12 | 13 | #### 二、函数说明 14 | 15 | ###### (1)average函数 16 | 17 | 将每次寻道的距离数组length[]传入函数, 将其累加求平均值 18 | 19 | ###### (2)first_come_first_server函数 20 | 21 | 先来先服务算法 22 | 定义visit[]数组, 来记录请求是否被处理, 若处理过, 则查看下一个请求 23 | 求出每次寻道的距离, 将其放入length[]中 24 | 25 | ###### (3)shortest_seek_time_first函数 26 | 27 | 最短寻道时间优先算法 28 | 定义flag记录当前最短路径下标 29 | 用for循环找没有访问过的中最近的 30 | 每找到一个将其放入length[]中, 并设为已访问 31 | 32 | ###### (6)scan函数 33 | 34 | 扫描算法 35 | 调用sort函数将所有请求按从小到大排序 36 | 通过for循环找到离当前磁头最近的请求磁道, 随后往递增方向访问, 全部访问完成, 再往递减方向访问 37 | 每次访问完更新磁头位置 38 | 39 | #### 三、运行结果 40 | 41 | ![image-20220516165413706](img/image-20220516165413706.png) 42 | 43 | ![image-20220516165427090](img/image-20220516165427090.png) 44 | 45 | ![image-20220516165439802](img/image-20220516165439802.png) 46 | 47 | ![image-20220516165648074](img/image-20220516165648074.png) 48 | 49 | ![image-20220516165509562](img/image-20220516165509562.png) 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /page-replacement/README.md: -------------------------------------------------------------------------------- 1 | # page-replacement 2 | 分页系统中的先进先出页面置换(FIFO), 最近最久未使用(LRU), 最佳页面置换(Optimal)算法 3 | 4 | #### 一、要求 5 | 6 | ###### 1.通过如下方法产生一指令序列,共 320 条指令 7 | 8 | A.在[1,32k - 2]的指令地址之间随机选取一起点, 访问 M; 9 | B.顺序访问M + 1; 10 | C.在[0,M - 1]中随机选取M1,访问 M1; 11 | D.顺序访问M1 + 1; 12 | E.在[M1 + 2,32k - 2]中随机选取M2,访问 M2; 13 | F.顺序访问M2 + 1; 14 | G.重复 A—F,直到执行 320 次指令。 15 | 16 | ###### 2.指令序列变换成页地址流 17 | 18 | (1)页面大小为 1K; 19 | (2)分配给用户的内存页块个数为 8页到 32 页, 步长为1页; 20 | (3)用户虚存容量为 32K。 21 | 22 | ###### 3.计算并输出下述各种算法在不同内存页块下的命中率 23 | A.先进先出(FIFO)页面置换算法 24 | B.最近最久未使用(LRU)页面置换算法 25 | C.最佳(Optimal)页面置换算法 26 | 27 | #### 二、程序功能 28 | 29 | 要求在随机生成的指令序列,页面大小为 1K,分配给用户的内存页块个数为 8 页到 32 页, 步长为1页。用户虚存容量为 32K。分别计算先进先出(FIFO)页面置换算法,最近最久未使用(LRU)页面置换算法,最佳(Optimal)页面置换算法在不同内存页块下的命中率。 30 | 31 | 32 | #### 三、设计思路 33 | 34 | 实现三种算法 35 | 设计一个取指令函数,得到320个随机的指令序列 36 | 主函数中设计一个循环, 依次输出计算出的值 37 | 38 | ###### 1.FIFO算法 39 | 40 | 用链表模拟队列。初始化之后,每次取得下一个指令,检查队列中存在对应的页号,如果存在命中次数加1,否则**删除队列中第一个页号**,插入当前页号。 41 | 42 | ###### 2.LRU算法 43 | 44 | 选择最近且最久未被使用的页面进行淘汰。利用局部性原理,根据一个作业在执行过程中过去的页面访问历史来推测未来的行为。它认为过去一段时间里不曾被访问过的页面,在最近的将来可能也不会再被访问。所以,这种算法的实质是:当需要淘汰一个页面时,总是选择在最近一段时间内最久不用的页面予以淘汰。 设置一个结构体,保存指令所在的页号和在队列中没有被访问的次数。如果需要淘汰,每次**淘汰没有被访问次数最多的页号**。 45 | 46 | ###### 3.OPT算法 47 | 48 | 从主存中移出永远不再需要的页面;如无这样的页面存在,则选择最长时间不需要访问的页面。于所选择的被淘汰页面将是以后永不使用的,或者是在最长时间内不再被访问的页面,这样可以保证获得最低的缺页率。每次淘汰时,评估每一个页号将来的位置,**淘汰最长时间不需要访问的页面**。 49 | 50 | ###### 4.取指令函数 51 | 52 | 取用srand(time(0)); 设定时间种子。使用随机函数rand() % M得到0~M - 1的随机数(M < MAX_INT),当指令到达320时,停止生成指令。**由于产生的为地址,最后需要除以1024得到所在的页号。 ** 53 | 54 | 55 | #### 四、运行结果 56 | 57 | ![image-20220516201124108](img/image-20220516201124108.png) 58 | -------------------------------------------------------------------------------- /process-management/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | pid_t pid1, pid2; //进程类型定义 10 | int fd[2]; // fd[0] 用于读取管道,fd[1] 用于写入管道 11 | int cnt = 0; 12 | 13 | void handler(int signo) 14 | { 15 | if (signo == SIGINT) 16 | { 17 | kill(pid1, SIGUSR1); //发出信号 18 | kill(pid2, SIGUSR2); 19 | } 20 | if (pid1 == 0 && signo == SIGUSR1) 21 | { 22 | printf("\nChild Process 1 is killed by Parent!\n"); 23 | exit(0); //进程正常终止 24 | } 25 | if (pid2 == 0 && signo == SIGUSR2) 26 | { 27 | printf("\nChild Process 2 is killed by Parent!\n"); 28 | exit(0); 29 | } 30 | } 31 | 32 | int main() 33 | { 34 | char buffer[1 << 8]; // 2的8次方 35 | char msg[1 << 8]; 36 | memset(buffer, 0, sizeof(buffer)); 37 | memset(msg, 0, sizeof(msg)); 38 | if (pipe(fd) < 0) 39 | { 40 | perror("pipe"); // perror(s) 用来将上一个函数发生错误的原因输出到标准设备(stderr) 41 | exit(1); 42 | } 43 | signal(SIGINT, handler); //当接收到一个类型为sig的信号时,就执行handler所指定的函数 44 | pid1 = fork(); 45 | if (pid1 == 0) 46 | { 47 | //子进程 48 | // SIG_ING 代表忽略SIGINT信号,SIGINT信号代表由InterruptKey产生,通常是CTRL +C 或者是DELETE 49 | signal(SIGINT, SIG_IGN); //屏蔽系统的结束 只能通过用户自定义的信号结束 50 | signal(SIGUSR1, handler); 51 | while (1) 52 | { 53 | close(fd[0]); //只写 关闭读 54 | sprintf(msg, "I send message %d times", ++cnt); 55 | write(fd[1], msg, strlen(msg)); 56 | sleep(1); 57 | } 58 | } 59 | else if (pid1 > 0) 60 | { 61 | pid2 = fork(); 62 | if (pid2 == 0) 63 | { 64 | signal(SIGINT, SIG_IGN); 65 | signal(SIGUSR2, handler); 66 | while (1) 67 | { 68 | close(fd[1]); //只读 关闭写 69 | read(fd[0], buffer, sizeof(buffer)); 70 | printf("%s\n", buffer); 71 | } 72 | } 73 | //等两个子进程结束 74 | waitpid(pid2, NULL, 0); 75 | waitpid(pid1, NULL, 0); 76 | close(fd[0]); 77 | close(fd[1]); 78 | printf("Parent Process is killed!\n"); 79 | } 80 | else 81 | { 82 | perror("fork"); 83 | exit(1); //不正常退出 84 | } 85 | return 0; 86 | } 87 | -------------------------------------------------------------------------------- /file-system-call/README.md: -------------------------------------------------------------------------------- 1 | # file-system-call 2 | 通过编写文件工具filetool调用文件系统 3 | 4 | #### 一、要求 5 | 6 | 使用文件系统调用编写一个文件工具 filetools,使其具有以下功能: 7 | 1.创建新文件 8 | 2.写文件 9 | 3.读文件 10 | 4.修改文件权限 11 | 5.查看当前文件权限 12 | 0.退出 13 | 14 | #### 二、程序功能 15 | 16 | 实现文件调用系统,实现linux文件系统调用 17 | 支持输入文件名,实现打开或创建文件(如果该文件不存在) 18 | 支持文件写入,在打开文件或者新建文件之后,用户可以如何任何内容加入到当前文件的后面 19 | 支持读文件功能,展现文件信息 20 | 支持修改权限文件功能 例如777表示所有者,所属者和其他人都存在读写执行的权限 21 | 支持查看文件类型,格式为-rwxrwxrwx- 22 | 支持退出当前文件,重新打开或者创建新的文件 23 | 24 | #### 三、设计思路 25 | 26 | ###### 1.创建新文件函数 27 | 28 | umask(0000); //建立新文件时的权限遮罩 29 | 通过open(filename, O_RDWR | O_CREAT, 0666)函数创建文件 30 | 得到的文件权限为0666-0000 31 | fd<0时, 提示创建失败 32 | 33 | ###### 2.写文件函数 34 | 35 | 通过open(filename, O_WRONLY);打开指定文件, 权限是只写 36 | write(fd, buffer, strlen(buffer));将缓存区的内容写入 37 | 38 | ###### 3.读文件函数 39 | 40 | open(filename, O_RDONLY); 打开指定文件, 权限是只读 41 | lseek(fd, 0, SEEK_SET); lseek函数定位一个已经打开的文件, 第2 3参数将读写位置移到文件开头 42 | 创建缓存区 43 | read(fd, buffer, 1 << 15);读取内容到缓存区 44 | 打印缓冲区内容 45 | 46 | ###### 4.修改文件权限函数 47 | 48 | 打开指定文件 49 | 十进制转八进制 50 | int mode_u = mode / 100; // user 51 | int mode_g = mode / 10 % 10; // group 52 | int mode_o = mode % 10; // others 53 | mode = (mode_u * 8 * 8) + (mode_g * 8) + mode_o; 54 | chmod(filename, mode);修改权限 55 | 56 | ###### 5.查看文件权限 57 | 58 | 打开指定文件 59 | char *pargv[4] = {"ls", "-l", NULL, NULL}; 60 | 需要将文件名传到*pargv[2] 61 | pargv[2] = (char *)malloc(50); 62 | strcpy(pargv[2], filename); 63 | 查看指定文件的权限 64 | execv("/bin/ls", pargv); 65 | 66 | ###### 6.输入处理函数 67 | 68 | 通过sstream流, 处理输入的字符 69 | 取touch cat echo chmod ll 的前两个字母通过s.find来查找字符中是否存在对应的关键字, 若存在, 就调用对应函数 70 | 71 | #### 四、运行结果 72 | 73 | 交互界面 74 | 75 | ![image-20220516194815622](img/image-20220516194815622.png) 76 | 77 | 新建文件 78 | 79 | ![image-20220516194823862](img/image-20220516194823862.png) 80 | 81 | 写入文件 82 | 83 | ![image-20220516194829611](img/image-20220516194829611.png) 84 | 85 | 查看文件 86 | 87 | ![image-20220516194835318](img/image-20220516194835318.png) 88 | 89 | 改变文件权限 90 | 91 | ![image-20220516194840599](img/image-20220516194840599.png) 92 | 93 | 查看文件权限 94 | 95 | ![image-20220516194846589](img/image-20220516194846589.png) 96 | 97 | #### 五、相关信息: 98 | 99 | 系统需要根据用户提供的参数来查找文件的目录项,并由目录项找到文件的磁盘 i 结点,再将它调到内存 i 结点,才能建立用户进程与该文件之间的联系。 100 | 同样,在文件操作完毕后要关闭文件,以切断用户进程与文件的联系,释放相关资源。 101 | Open 系统调用 102 | int open(const char *path, int flags); 103 | int open(const char *path, int flags,mode_t mode); 104 | 一般情况下使用两个参数的格式,只有当打开的文件不存在时才使用 3 个参数的格式。参数: 105 | Path 指向所要打开的文件的路径名指针。 106 | int close(int fd) 107 | Fd 为打开文件时系统返回的文件标识符 108 | 系统执行该系统调用时,根据 fd 值在该进程的进程打开文件表中找到 fd 标识,根据指针找到系统打开文件表,再找到内存 i 结点表中相应的 i 结点,对其 i_count 进行减 1 操作, 109 | 然后释放系统打开文件表中的表项和进程打开文件表的表项 返回结果:调用成功返回 0 110 | 111 | 打开文件,首先输入文件名新建文件 112 | 113 | 写文件,首先判断文件是否打开,否则必须调用功能打开文件,然后使用过write(fd, buffer, strlen(buffer))系统函数写入文件。 114 | 115 | 修改文件权限,首先判断文件是否打开,否则必须调用功能打开文件。输入格式为777(或者其他权限),首先对模式分解,调用系统函数chmod。修改是否成功给出提示信息。 116 | 117 | 读文件,首先判断文件是否打开,否则必须调用功能打开文件。清空缓冲区,打印到界面。 118 | 119 | 查看文件权限,首先判断文件是否打开,否则必须调用功能打开文件。调用execv系统功能函数。 120 | 121 | 122 | 123 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 操作系统课设 2 | 3 | #### 实验一:为Linux系统增加系统调用 4 | 5 | 通过修改Linux 0.11系统文件, 实现增加一个简单的系统调用 6 | 7 | ###### 0.环境配置 8 | 9 | 在Ubuntu20.04.1虚拟机上, 用Bochs运行Linux0.11编译出的image文件 10 | 编译Linux0.11需要32位gcc环境, 附一个简单可行的环境配置链接: https://gitee.com/cn-guoziyang/oslab 11 | 12 | ###### 1.程序功能 13 | 14 | 通过修改Linux 0.11系统文件(使用Bochs运行), 实现增加一个简单的系统调用 15 | 此处是调用nameout.c输出”Hello, I’m lwh” 16 | 17 | ###### 2.设计思路 18 | 19 | 在用户层面编写程序nameout.c,通过syscall这个宏开启调用系统函数的窗口,调用sys_nameout系统函数。 20 | 编写函数sys_nameout,以name.c的文件格式保存在了linux0.11系统kernel中; 21 | sys_nameout调用了printk()完成打印输出。 22 | 修改Makefile文件让我们添加的 kernel/who.c 可以和其它 Linux 代码编译链接到一起 23 | 24 | ![img](img/clip_image002.png) 25 | 26 | 详细步骤: 27 | 添加iam和whoami系统调用编号的宏定义(_NR_xxxxxx) 28 | 29 | 文件路径:/linux-0.11/**include/unistd.h 30 | ** ![img](img/clip_image004.jpg) 31 | 32 | 33 | 34 | 修改系统调用总数 35 | 文件路径:/linux-0.11/**kernel/system_call.s 36 | ** ![img](img/clip_image006.jpg) 37 | 38 | 39 | 40 | 为新增的系统调用添加系统调用名并维护系统调用表 41 | 文件路径:/linux-0.11/**include/linux/sys.h** 42 | 43 | ![img](img/clip_image008.jpg) 44 | 45 | 46 | 47 | 为新增的系统调用编写代码实现,创建一个文件 `name.c` 48 | **文件路径****: /linux-0.11/kernel** 49 | 50 | ![img](img/clip_image010.jpg) 51 | 52 | name.c中写入printk(”Hello, I’m lwh”) 53 | 54 | 55 | 56 | 修改 Makefile 57 | 58 | 要想让我们添加的 kernel/who.c 可以和其它 Linux 代码编译链接到一起,必须要修改 Makefile 文件 59 | 60 | 文件路径: / linux-0.11/kernel/Makefile 61 | 62 | ![img](img/clip_image012.jpg) 63 | 64 | 65 | 66 | 编写测试程序 67 | 68 | 到此为止,内核中需要修改的部分已经完成,接下来需要编写测试程序来验证新增的系统调用是否已经被编译到linux-0.11内核可供调用 69 | 70 | 文件路径:/oslab/namein.c /oslab/nameout.c 71 | 72 | 73 | 74 | ![img](img/clip_image014.jpg) 75 | 76 | 77 | 78 | /* nameout.c */ 79 | 80 | \#define __LIBRARY__ 81 | 82 | \#include 83 | 84 | \#include 85 | 86 | \#include 87 | 88 | \#include 89 | 90 | \#include 91 | 92 | 93 | 94 | _syscall2(int, nameout,char *,name,unsigned int,size); 95 | 96 | 97 | 98 | int main(int argc, char *argv[]) 99 | 100 | { 101 | 102 | char username[64] = {0}; 103 | 104 | /*调用系统调用nameout()*/ 105 | 106 | nameout(username, 24); 107 | 108 | printf("%s\n", username); 109 | 110 | return 0; 111 | 112 | } 113 | 114 | 115 | 116 | 采用挂载方式实现宿主机与虚拟机操作系统的文件共享,在 `oslab` 目录下执行以下命令挂载hdc目录到虚拟机操作系统上 117 | 118 | ![img](img/clip_image016.jpg) 119 | 120 | 121 | 122 | 编译linux内核 123 | 文件路径: /oslab/linux 124 | 125 | 终端执行 make命令 126 | ![img](img/clip_image018.jpg) 127 | 128 | Make成功 129 | 130 | 131 | 132 | 运行Bochs虚拟机 133 | 文件路径: /oslab/ 134 | 终端执行 run命令 135 | ![img](img/clip_image020.jpg) 136 | 137 | 138 | 为linux-0.11新增调用号 139 | 文件路径: 虚拟机中/usr/include/unistd.h(也可以挂载后在图形界面中修改) 140 | ![img](img/clip_image022.jpg) 141 | 142 | (若在虚拟机中修改) 143 | ![img](img/clip_image024.jpg) 144 | (若挂载后在主机的图形界面中修改) 145 | 146 | ![img](img/clip_image026.jpg) 147 | 148 | gcc运行 成功输出案例文字 149 | 150 | ![img](img/clip_image028.jpg) 151 | 152 | ###### 3.程序运行情况及截图 153 | 154 | ![image-20220831174424416](img/image-20220831174424416.png) 155 | 156 | 157 | 158 | #### 实验二:磁盘调度算法 159 | 160 | 使用FIFO(先来先服务)、SSTF(最短寻道优先)以及SCAN(电梯调度算法)进行磁盘调度 161 | 162 | 显示调度顺序, 计算出平均移动磁道数 163 | 164 | 165 | 166 | #### 实验三: Linux系统文件调用接口 167 | 168 | 使用文件系统调用编写一个文件工具 filetools,使其具有以下功能: 169 | 170 | 创建新文件, 写文件, 读文件, 修改文件权限, 查看当前文件权限, 退出 171 | 172 | 173 | 174 | #### 实验四: 进程管理 175 | 176 | 使用管道来实现父子进程之间的进程通信 177 | 178 | 179 | 180 | #### 实验五: 请求分页系统中的置换算法 181 | 182 | 产生320条指令序列 183 | 184 | 将指令序列变换成页地址流 185 | 186 | 分别计算先进先出(FIFO)页面置换算法,最近最久未使用(LRU)页面置换算法,最佳(Optimal)页面置换算法在不同内存页块下的命中率 187 | 188 | 189 | 190 | #### 实验六: 进程通信 191 | 192 | 使用管道来实现父子进程之间的进程通信 193 | 194 | 使用消息缓冲队列来实现 client 进程和 server 进程之间的通信 195 | 196 | 使用共享存储区来实现两个进程之间的进程通信 -------------------------------------------------------------------------------- /page-replacement/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | 12 | const int minn = 8; 13 | const int maxx = 32; 14 | const int N = 320;//指令执行次数 15 | int ins[2 * N]; 16 | double hit_num = 0; 17 | const int max_add = 32766;//32k-2 18 | 19 | struct node { 20 | int id; 21 | int num; 22 | }; 23 | 24 | void get_input() 25 | { 26 | int cnt = 0; 27 | srand(time(0)); 28 | while (cnt < N) { 29 | //在[1,32k - 2]间选取一起点 30 | int m = rand() % max_add + 1; 31 | ins[cnt++] = m; 32 | if (cnt >= N)break; 33 | ins[cnt++] = m + 1; 34 | if (cnt >= N)break; 35 | //在[0,M-1]间选取一起点 36 | int m1 = rand() % m; 37 | ins[cnt++] = m1; 38 | if (cnt >= N)break; 39 | ins[cnt++] = m1 + 1; 40 | if (cnt >= N)break; 41 | //在[M1 + 2,32k - 2]中选取一起点 42 | //(max_add +1 - 2 - m1) + (m1 + 2); 43 | int m2 = rand() % (max_add - 1 - m1) + (m1 + 2); 44 | ins[cnt++] = m2; 45 | if (cnt >= N)break; 46 | ins[cnt++] = m2 + 1; 47 | if (cnt >= N)break; 48 | } 49 | for (int i = 0; i < N; i++) { 50 | //产生的为地址,除以1024得到所在的页号 51 | ins[i] = ins[i] / 1024; 52 | } 53 | } 54 | 55 | double FIFO(int page) 56 | { 57 | hit_num = 0; 58 | listtemp;//双向循环链表 59 | //用-1初始化 60 | for (int i = 0; i < page; i++) { 61 | temp.push_back(-1); 62 | } 63 | for (int i = 0; i < N; i++) { 64 | list::iterator it = find(temp.begin(), temp.end(), ins[i]); 65 | //检查队列中存在对应的页号 66 | if (it == temp.end()) { 67 | //不存在时,删除队列中第一个页号,插入当前页号 68 | temp.pop_front(); 69 | temp.push_back(ins[i]); 70 | } 71 | else { 72 | hit_num++; 73 | } 74 | } 75 | hit_num = hit_num / N; 76 | hit_num *= 100; 77 | return hit_num; 78 | } 79 | 80 | //最近最久未使用算法 81 | double LRU(int page) 82 | { 83 | hit_num = 0; 84 | listtemp; 85 | for (int i = 0; i < page; i++) { 86 | temp.push_back(node{ -1,0 }); 87 | } 88 | list::iterator it; 89 | for (int i = 0; i < N; i++) { 90 | for (it = temp.begin(); it != temp.end(); it++) { 91 | //每轮循环使num增大,最大的是最久未使用 92 | it->num++; 93 | } 94 | bool flag = false; 95 | //查找分页是否存在 96 | for (it = temp.begin(); it != temp.end(); it++) { 97 | //分页存在时 98 | if (it->id == ins[i]) { 99 | flag = true; 100 | it->num = 0;//设置为最近使用过 101 | hit_num++; 102 | break; 103 | } 104 | } 105 | //分页不存在时 106 | if (!flag) { 107 | //找一个最大的 108 | list::iterator max_it = temp.begin(); 109 | for (it = temp.begin(); it != temp.end(); it++) { 110 | if (it->num > max_it->num) { 111 | max_it = it; 112 | } 113 | } 114 | temp.erase(max_it);//淘汰最久未使用的分页 115 | temp.push_back(node{ ins[i],0 }); 116 | } 117 | } 118 | hit_num = hit_num / N; 119 | hit_num *= 100; 120 | return hit_num; 121 | } 122 | 123 | //最佳页面置换算法 124 | double OPT(int page) 125 | { 126 | listtemp; 127 | hit_num = 0; 128 | for (int i = 0; i < page; i++) { 129 | temp.push_back(-1); 130 | } 131 | for (int i = 0; i < N; i++) { 132 | list::iterator it = find(temp.begin(), temp.end(), ins[i]); 133 | if (it == temp.end()) { 134 | int max_id = -1; 135 | list::iterator ans; 136 | for (it = temp.begin(); it != temp.end(); it++) { 137 | int cur = 0x3f3f3f3f;//若未查找到下标为无穷大 138 | //从当前页面之后开始查找 139 | for (int j = i + 1; j < N; j++) { 140 | if (ins[j] == *it) { 141 | cur = j;//记录下标 142 | break; 143 | } 144 | } 145 | //更新最大下标对应的页面 146 | if (cur > max_id) { 147 | max_id = cur; 148 | ans = it; 149 | } 150 | } 151 | temp.erase(ans);//淘汰最长时间不需要访问的页面 152 | temp.push_back(ins[i]); 153 | } 154 | else { 155 | hit_num++; 156 | } 157 | } 158 | hit_num = hit_num / N; 159 | hit_num *= 100; 160 | return hit_num; 161 | } 162 | 163 | int main() 164 | { 165 | get_input(); 166 | cout << "\t\t\t\t命中率结果" << endl; 167 | cout << "内存页块\t\tFIFO(%)\t\t\tLRU(%)\t\t\tOPT(%)" << endl; 168 | for (int i = minn; i <= maxx; i++) { 169 | printf("%d\t\t\t%.2f\t\t\t%.2f\t\t\t%.2f\n", i, FIFO(i), LRU(i), OPT(i)); 170 | } 171 | return 0; 172 | } 173 | -------------------------------------------------------------------------------- /file-system-call/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #pragma execution_character_set("utf-8") 12 | 13 | using namespace std; 14 | 15 | //定义全局变量 16 | const int MAX = 0x3f3f3f; 17 | char filename[50]; 18 | int fd; //打开文件时系统返回的文件标识符 19 | bool opened = false; 20 | char *pargv[4] = {"ls", "-l", NULL, NULL}; 21 | 22 | void create_open_file(char *filename) 23 | { 24 | //建立新文件时的权限遮罩 25 | umask(0000); 26 | //以读写方式 | 如果文件不存在则创建该文件,若存在则忽略 27 | fd = open(filename, O_RDWR | O_CREAT, 0666); //真实权限:mode-umask 28 | //当打开的文件不存在时使用 3 个参数的格式 29 | if (fd < 0) 30 | { 31 | printf("文件创建失败\n"); 32 | } 33 | else 34 | { 35 | printf("文件创建成功\n"); 36 | } 37 | close(fd); 38 | } 39 | 40 | void write_file(char *buffer, char *filename) 41 | { 42 | //只写打开 43 | fd = open(filename, O_WRONLY); 44 | if (fd < 0) 45 | { 46 | printf("文件打开失败\n"); 47 | return; 48 | } 49 | int returnnum = write(fd, buffer, strlen(buffer)); 50 | if (returnnum != -1) 51 | { 52 | printf("写入成功!\n"); 53 | } 54 | else 55 | { 56 | printf("写入失败!\n"); 57 | } 58 | } 59 | 60 | void mode_file(int mode, char *filename) 61 | { 62 | //以any方式打开 63 | fd = open(filename, O_RDONLY, 0666); 64 | if (fd < 0) 65 | { 66 | printf("文件打开失败\n"); 67 | return; 68 | } 69 | // 10-base number-> 8-base number 70 | int mode_u = mode / 100; // user 71 | int mode_g = mode / 10 % 10; // group 72 | int mode_o = mode % 10; // others 73 | mode = (mode_u * 8 * 8) + (mode_g * 8) + mode_o; //八进制转换 74 | int returnnum = chmod(filename, mode); 75 | if (returnnum == -1) 76 | { 77 | printf("修改权限失败\n"); 78 | } 79 | else 80 | { 81 | printf("修改权限成功\n"); 82 | } 83 | } 84 | 85 | void read_file(char *filename) 86 | { 87 | //只读打开 88 | fd = open(filename, O_RDONLY); 89 | if (fd < 0) 90 | { 91 | printf("文件打开失败\n"); 92 | return; 93 | } 94 | char buffer[1 << 15]; // 2的15次方 95 | memset(buffer, 0, sizeof(buffer)); 96 | // lseek定位一个已经打开的文件 97 | //第2 3参数将读写位置移到文件开头 98 | lseek(fd, 0, SEEK_SET); 99 | int returnnum = read(fd, buffer, 1 << 15); 100 | if (returnnum != -1) 101 | { 102 | printf("文件内容为:\n"); 103 | printf("%s\n", buffer); 104 | } 105 | else 106 | { 107 | printf("文件读取失败\n"); 108 | } 109 | close(fd); 110 | } 111 | 112 | void view_mode(char *filename) 113 | { 114 | fd = open(filename, O_RDONLY); 115 | if (fd < 0) 116 | { 117 | printf("文件打开失败\n"); 118 | return; 119 | } 120 | pargv[2] = (char *)malloc(50); 121 | // pargv的第三参数是文件名 122 | strcpy(pargv[2], filename); 123 | printf("文件权限为"); 124 | int returnnum = execv("/bin/ls", pargv); //执行文件函数 125 | if (returnnum == -1) 126 | { 127 | printf("查看失败\n"); 128 | } 129 | else 130 | { 131 | printf("文件权限为:\n"); 132 | } 133 | } 134 | 135 | void shell() 136 | { 137 | // system("chcp 65001"); 138 | system("clear"); 139 | do 140 | { 141 | cout << "Welcome to Zerin's Filetool\n"; 142 | cout << "Usage:\n"; 143 | cout << "touch a.cpp\n"; 144 | cout << "cat a.cpp\n"; 145 | cout << "echo \"hello\" >> a.cpp\n"; 146 | cout << "chmod 777 a.cpp\n"; 147 | cout << "ll a.cpp\n\n"; 148 | string to = "touch", ca = "cat", ch = "chmod", ec = "echo", ll = "ll"; 149 | string cmd; 150 | char *name = new char[20]; 151 | getline(cin, cmd); 152 | istringstream str(cmd); 153 | // touch命令 154 | // find查找失败返回的值比max大 155 | if (cmd.find(to) < MAX) 156 | { 157 | str >> cmd; 158 | str >> cmd; //覆盖前一次>>中的touch,得到name 159 | strcpy(name, cmd.c_str()); 160 | create_open_file(name); 161 | } 162 | // cat命令 163 | else if (cmd.find(ca) < MAX) 164 | { 165 | str >> name; //此处也可>>cmd 166 | // str >> cmd;//覆盖前一次>> 得到name 167 | // strcpy(name, cmd.c_str()); 168 | str >> name; //更好的方法 不需复制 169 | read_file(name); 170 | } // echo 171 | else if (cmd.find(ec) < MAX) 172 | { 173 | string buffer_raw; 174 | char *buffer = new char[1 << 10]; 175 | str >> buffer_raw; 176 | str >> buffer_raw; //覆盖前一次>> 得到buffer 177 | str >> name; 178 | str >> name; //覆盖前一次>> 得到name 179 | //去除"" 180 | buffer_raw = buffer_raw.substr(1, buffer_raw.length() - 2); 181 | strcpy(buffer, buffer_raw.c_str()); 182 | write_file(buffer, name); 183 | } // chmod 184 | else if (cmd.find(ch) < MAX) 185 | { 186 | int mode; 187 | str >> cmd; 188 | str >> mode; 189 | str >> name; 190 | mode_file(mode, name); 191 | } // ll 192 | else if (cmd.find(ll) < MAX) 193 | { 194 | str >> cmd; 195 | str >> name; 196 | view_mode(name); 197 | } 198 | else 199 | { 200 | cout << cmd << ": command not found\n"; 201 | } 202 | //2022.9.21 modify 203 | //cin.get(); 204 | //system("clear"); 205 | } while (1); 206 | } 207 | 208 | int main() 209 | { 210 | shell(); 211 | return 0; 212 | } 213 | -------------------------------------------------------------------------------- /process-communication/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // const int SVKEY = 75; 12 | #define SVKEY 75 //定义关键字SVKEY 13 | #define REQ 1 14 | const int SIZE = 1 << 8; 15 | 16 | struct msgform 17 | { 18 | long long mtype; 19 | char mtext[250]; 20 | } msg; 21 | 22 | // for creating process 23 | int i; 24 | // for 通过共享缓存区通信 25 | int shmid; 26 | char *addr; 27 | 28 | void pipeComm() 29 | { 30 | pid_t pid; 31 | int fd[2]; // fd[0] 用于读取管道,fd[1] 用于写入管道 32 | char buf[SIZE]; 33 | char msg[SIZE]; 34 | memset(buf, 0, SIZE); 35 | memset(msg, 0, SIZE); 36 | if (pipe(fd) < 0) 37 | { 38 | perror("pipe"); 39 | exit(1); 40 | } 41 | pid = fork(); 42 | if (pid == 0) //子 43 | { 44 | close(fd[0]); // write only 45 | sprintf(msg, "%d is sending a message to parent %d by PIPE\n", getpid(), getppid()); 46 | write(fd[1], msg, strlen(msg)); 47 | exit(0); 48 | } 49 | else if (pid > 0) 50 | { 51 | close(fd[1]); // read only 52 | read(fd[0], buf, SIZE); 53 | printf("%s", buf); 54 | } 55 | else 56 | { 57 | perror("fork"); 58 | exit(1); 59 | } 60 | } 61 | 62 | void qServer() 63 | { 64 | int c_pid, s_pid, msgqid; // client的pid 和 消息队列识别码 65 | struct msgform msg; 66 | msgqid = msgget(SVKEY, 0777 | IPC_CREAT); //创建 75#消息队列 67 | while (1) 68 | { 69 | msgrcv(msgqid, &msg, 250, 1, 0); //接收client进程标识数消息 70 | c_pid = *(int *)msg.mtext; //获得 cilent 进程标识数 71 | if (msg.mtype == REQ) 72 | { 73 | printf("(server):serving for client pid=%d\n", c_pid); 74 | break; 75 | } 76 | } 77 | msg.mtype = c_pid; //消息类型为 client 进程标识数 78 | s_pid = getpid(); 79 | *(int *)msg.mtext = s_pid; //获取 server 进程标识数 80 | msgsnd(msgqid, &msg, sizeof(int), 0); //发送消息 81 | exit(0); 82 | } 83 | 84 | void qClient() 85 | { 86 | int pid, msgqid; // client的pid 和 消息队列识别码 87 | struct msgform msg; 88 | msgqid = msgget(SVKEY, 0777); //打开 75#消息队列 89 | 90 | pid = getpid(); //获取client进程标识符 91 | *(int *)msg.mtext = pid; // pint指针指向client进程标识符 92 | msg.mtype = REQ; //消息类型为 1 93 | msgsnd(msgqid, &msg, sizeof(int), 0); //发送消息msg入msgqid消息队列 94 | while (1) 95 | { 96 | msgrcv(msgqid, &msg, 250, pid, 0); //从队列msgqid接收消息msg 97 | if (msg.mtype != REQ) 98 | { 99 | printf("(client):receive reply from pid=%d\n", *(int *)msg.mtext); //显示 server进程标识数 100 | exit(0); 101 | } 102 | } 103 | } 104 | 105 | void msgQueueComm() 106 | { 107 | i = fork(); //创建进程 1 108 | if (!i) //子进程中 fork返回0 109 | qServer(); 110 | i = fork(); //创建进程 2 111 | if (!i) 112 | qClient(); 113 | } 114 | 115 | void sServer() 116 | { 117 | shmid = shmget(SVKEY, 1024, 0777 | IPC_CREAT); /*创建共享存储区*/ 118 | addr = shmat(shmid, 0, 0); /*获取首地址*/ 119 | do 120 | { 121 | *addr = -1; 122 | while (*addr == -1) 123 | ; //阻塞,用于进程同步 124 | printf("(server) received\n"); 125 | } while (*addr); 126 | shmctl(shmid, IPC_RMID, 0); /*撤消共享存储区,归还资源*/ 127 | exit(0); 128 | } 129 | 130 | void sClient() 131 | { 132 | int i; 133 | shmid = shmget(SVKEY, 1024, 0777); /*打开共享存储区*/ 134 | addr = shmat(shmid, 0, 0); /*获得共享存储区首地址*/ 135 | for (i = 9; i >= 0; i--) 136 | { 137 | while (*addr != -1) 138 | ; //阻塞,用于进程同步 139 | printf("(client) sent\n"); 140 | *addr = i; 141 | } 142 | exit(0); 143 | } 144 | 145 | void sharedMemComm() 146 | { 147 | while ((i = fork()) == -1) 148 | ; 149 | if (!i) 150 | sServer(); 151 | system("ipcs -m"); 152 | while ((i = fork()) == -1) 153 | ; 154 | if (!i) 155 | sClient(); 156 | // wait(0); 157 | // wait(0); 158 | } 159 | 160 | int main() 161 | { 162 | int choice; 163 | while (1) 164 | { 165 | system("clear"); 166 | printf(" 进程通信程序 "); 167 | printf("\n选择操作\n"); 168 | printf("1.管道通信\n"); 169 | printf("2.消息队列\n"); 170 | printf("3.共享储存区\n"); 171 | scanf("%d", &choice); 172 | switch (choice) 173 | { 174 | case 1: 175 | pipeComm(); 176 | getchar(); 177 | getchar(); 178 | break; 179 | case 2: 180 | msgQueueComm(); 181 | getchar(); 182 | getchar(); 183 | break; 184 | case 3: 185 | sharedMemComm(); 186 | getchar(); 187 | getchar(); 188 | break; 189 | default: 190 | printf("INPUT ERROR!\n"); 191 | break; 192 | } 193 | } 194 | return 0; 195 | } -------------------------------------------------------------------------------- /disk-scheduling/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define MAX 100 6 | using namespace std; 7 | 8 | //求平均寻道长度 9 | double average(int *length, int n) 10 | { 11 | double sum = 0; 12 | int i; 13 | for (i = 0; i < n; i++) 14 | sum += length[i]; 15 | return sum / n; 16 | } 17 | 18 | void show(int num, int next[], int length[]) 19 | { 20 | int i; 21 | cout << endl 22 | << "下一个磁道" 23 | << "\t\t\t" 24 | << "移动距离" << endl; 25 | for (i = 0; i < num; i++) 26 | { 27 | cout << next[i] << "\t\t\t\t" << length[i] << endl; 28 | } 29 | cout << "平均寻道长度:"; 30 | printf("%.2f\n\n", average(length, num)); //输出两位float后的小数 31 | } 32 | 33 | //先来先服务算法 34 | void first_come_first_server(int *a, int n, int now) 35 | { 36 | int i, j = 0; 37 | int num = n; //调度请求数目 38 | int next[MAX], length[MAX]; 39 | int visit[MAX] = {0}; 40 | while (num--) 41 | { 42 | for (i = 0; i < n; i++) 43 | { 44 | //省略已处理的请求 45 | if (visit[i]) 46 | { 47 | continue; 48 | } 49 | else 50 | { 51 | length[j] = abs(a[i] - now); // abs绝对值 52 | next[j++] = a[i]; 53 | visit[i] = 1; 54 | now = a[i]; //更新now值 55 | } 56 | } 57 | } 58 | show(n, next, length); 59 | } 60 | //最短寻道时间优先算法 61 | void shortest_seek_time_first(int *a, int n, int now) 62 | { 63 | int i, min, j = 0; 64 | int flag; //当前最短路径的下标 65 | int t = n; 66 | int next[MAX], length[MAX]; 67 | int visit[MAX] = {0}; //访问数组,已经访问过的为1 68 | //寻道n次 69 | while (t--) 70 | { 71 | min = 9999999; //每次循环将min重置 72 | //找没有访问过的中最近的 73 | for (i = 0; i < n; i++) 74 | { 75 | if (visit[i]) 76 | continue; 77 | if (abs(a[i] - now) < min) 78 | { 79 | flag = i; 80 | min = abs(a[i] - now); 81 | } 82 | } 83 | length[j] = min; //移动的距离 84 | next[j++] = a[flag]; //下一个被访问的磁道号 85 | visit[flag] = 1; //访问过的置1 86 | now = a[flag]; //磁道移动到当前位置 87 | } 88 | show(n, next, length); 89 | } 90 | 91 | //扫描算法 92 | void scan(int *a, int n, int now) 93 | { 94 | int i, flag = 0, j = 0; // flag是当前磁道下标 95 | //避免改变原始序列,影响后面的算法 96 | int temp_a[MAX]; 97 | for (int j = 0; j < n; j++) 98 | { 99 | temp_a[j] = a[j]; 100 | } 101 | int next[MAX], length[MAX]; 102 | sort(temp_a, temp_a + n); //从小到大排序 103 | //寻找开始磁道 104 | for (i = 0; i < n; i++) 105 | { 106 | if (temp_a[i] >= now) 107 | { 108 | flag = i; 109 | break; 110 | } 111 | } 112 | //往递增方向访问 113 | for (i = flag; i < n; i++) 114 | { 115 | next[j] = temp_a[i]; 116 | length[j++] = abs(temp_a[i] - now); 117 | now = temp_a[i]; //磁道移动到当前位置 118 | } 119 | //回来往递减方向访问 120 | for (i = flag - 1; i >= 0; i--) 121 | { 122 | next[j] = temp_a[i]; 123 | length[j++] = abs(temp_a[i] - now); 124 | now = temp_a[i]; //磁道移动到当前位置 125 | } 126 | show(n, next, length); 127 | } 128 | 129 | void circle_scan(int *a, int n, int now) 130 | { 131 | int i, flag = 0, j = 0; 132 | //避免改变原始序列,影响后面的算法 133 | int temp_a[MAX]; 134 | for (int j = 0; j < n; j++) 135 | { 136 | temp_a[j] = a[j]; 137 | } 138 | int next[MAX], length[MAX]; 139 | sort(temp_a, temp_a + n); //从小到大排序 140 | for (i = 0; i < n; i++) 141 | { 142 | if (temp_a[i] >= now) 143 | { 144 | flag = i; 145 | break; 146 | } 147 | } 148 | //往递增方向访问 149 | for (i = flag; i < n; i++) 150 | { 151 | next[j] = temp_a[i]; 152 | length[j++] = abs(temp_a[i] - now); 153 | now = temp_a[i]; 154 | } 155 | //循环往递增方向访问 156 | for (i = 0; i < flag; i++) 157 | { 158 | next[j] = temp_a[i]; 159 | length[j++] = abs(temp_a[i] - now); 160 | now = temp_a[i]; 161 | } 162 | show(n, next, length); 163 | } 164 | 165 | //适用于懒狗的输入函数 166 | void lazyDogInput(int a[], int &num) 167 | { 168 | int i, order; 169 | cout << "请选择输出磁道请求序列方式:\n"; 170 | cout << "1.随机生成:\n"; 171 | cout << "2.生成指定序列:\n"; 172 | cout << "3.手动输入序列:\n"; 173 | cin >> order; 174 | switch (order) 175 | { 176 | case 1: 177 | cout << "请输入磁道数:" << endl; 178 | cin >> num; 179 | cout << "生成随机磁道:" << endl; 180 | srand((int)time(0)); 181 | for (i = 0; i < num; i++) 182 | { 183 | a[i] = rand() % 100; 184 | cout << a[i] << " "; 185 | } 186 | break; 187 | case 2: 188 | num = 14; 189 | a[0] = 30; 190 | a[1] = 50; 191 | a[2] = 100; 192 | a[3] = 180; 193 | a[4] = 20; 194 | a[5] = 90; 195 | a[6] = 150; 196 | a[7] = 70; 197 | a[8] = 80; 198 | a[9] = 10; 199 | a[10] = 160; 200 | a[11] = 120; 201 | a[12] = 40; 202 | a[13] = 110; 203 | cout << "磁道序列为:" << endl; 204 | for (i = 0; i < num; i++) 205 | { 206 | cout << a[i] << " "; 207 | } 208 | break; 209 | case 3: 210 | cout << "请输入磁道数:" << endl; 211 | cin >> num; 212 | cout << "请依次输入磁道序列:" << endl; 213 | for (i = 0; i < num; i++) 214 | { 215 | cin >> a[i]; 216 | } 217 | cout << "磁道序列为:" << endl; 218 | for (i = 0; i < num; i++) 219 | { 220 | cout << a[i] << " "; 221 | } 222 | break; 223 | } 224 | } 225 | 226 | int main() 227 | { 228 | do 229 | { 230 | int a[MAX]; //存放要用到的磁道号 231 | int start; //开始的磁道 232 | int n, i, flag = 1; 233 | lazyDogInput(a, n); 234 | cout << endl 235 | << "开始的磁道:" << endl; 236 | cin >> start; 237 | //磁盘调度目录 238 | while (flag) 239 | { 240 | system("clear"); 241 | cout << "请选一种磁盘调度算法:" << endl; 242 | cout << "1.先来先服务寻道算法" << endl; 243 | cout << "2.最短寻道时间优先" << endl; 244 | cout << "3.扫描算法" << endl; 245 | cout << "4.循环扫描算法" << endl; 246 | cout << "0.返回" << endl; 247 | cin >> flag; 248 | if (flag) 249 | { 250 | cout << "磁道序列:\n"; 251 | for (i = 0; i < n; i++) 252 | { 253 | cout << a[i] << " "; 254 | } 255 | cout << "\n开始的磁道:" << start << endl; 256 | } 257 | switch (flag) 258 | { 259 | case 1: 260 | first_come_first_server(a, n, start); 261 | cin.get(); 262 | cin.get(); 263 | break; 264 | case 2: 265 | shortest_seek_time_first(a, n, start); 266 | cin.get(); 267 | cin.get(); 268 | break; 269 | case 3: 270 | scan(a, n, start); 271 | cin.get(); 272 | cin.get(); 273 | break; 274 | case 4: 275 | circle_scan(a, n, start); 276 | cin.get(); 277 | cin.get(); 278 | break; 279 | case 0: 280 | system("clear"); 281 | break; 282 | } 283 | } 284 | } while (true); 285 | return 0; 286 | } -------------------------------------------------------------------------------- /file-system-call/mzd.txt: -------------------------------------------------------------------------------- 1 | 我是从一个伟大的人物身上,学会自律的。 2 | 01 3 | 1945 年,重庆。 4 | 这座 70 年后在抖音上火得一塌糊涂的「网红」城市,一定没想到,自己在这一年的 9 月比半个世纪后还要红。 5 | 因为,一场举世瞩目的谈判正在这里举行。 6 | 国共两党的主要负责人,在美国的斡旋下,进行了马拉松式的一系列会谈。 7 | 马拉松要跑 42 公里多。 8 | 而重庆谈判也谈了 42 天多。 9 | 当蒋介石给毛泽东发出电报邀请其来重庆会谈时,估计也没有想到毛泽东真的会来。 10 | 他原本的想法大概是只要毛不来,就一把掀翻谈判桌,摊着双手对着所有人大喊:看,毛泽东对和平谈判没有诚意,都不敢来重庆,我也很无奈啊! 11 | 偏偏,毛泽东居然真的来了。 12 | 仅这一消息就已让全国都沸腾了。 13 | 毛泽东之所以敢赴「鸿门宴」,各方面其实考虑了很多因素,也做了最坏的准备。 14 | 但蒋介石认为,毛泽东之所以来主要是因为天命所归。 15 | 他在日记里写道:毛泽东果应召来渝,此虽威德所致,而实上帝所赐也。 16 | 这既是两个老对手十几年较量后的一场面对面交锋,更是一场关乎国运,关乎两党未来,并最终影响了历史走向的大事件。 17 | 在这场被后世称为「重庆谈判」的 40 多天里,有太多的明枪暗箭,风起云涌。 18 | 也就有了无数的唇枪舌战、针锋相对,甚至就连重庆谈判期间,围绕毛泽东创作的《沁园春·雪》,都有一箩筐的精彩故事。 19 | 但所有的这些故事,都没有一个非常不起眼的细节让我震撼。 20 | 02 21 | 据统计,重庆谈判期间,毛泽东与蒋介石的直接会谈差不多有 10 次左右。 22 | 在谈判桌上, 双方围绕政府、军队等重大原则问题,进行了激烈的辩论和斗争。 23 | 谈判之外,毛泽东还要参加各类宴会,出席各种公开场合,会见各个派系的代表人物,时不时和别有用心的记者们谈笑风生。 24 | 压力之大,精神之高度紧张,可以想象。 25 | 出人意料的是,虽然毛泽东每天都需要竭尽心力斗智斗勇,但在重庆的时间里,原本烟不离手的他,却像戒烟了一样,从来不靠香烟提神醒脑,,思考论战。 26 | 在和蒋介石进行的数次会谈中,更是一根都没有抽! 27 | 特别值得说明的是,这个细节并不是我发现的。 28 | 真正第一个注意到这个细节的人,是蒋介石。 29 | 重庆谈判后,蒋介石的亲信陈布雷问他对毛泽东的评价。 30 | 蒋介石回忆了一会儿,深有感触地说; 31 | 「毛泽东此人不可轻视。他嗜烟如命, 手执一缕, 绵绵不断, 据说一天要抽 50 支烟。但他知道我不吸烟, 在同我会谈期间, 竟然决不抽一支烟。对他的决心和精神, 不可少视啊! 」 32 | 从这段评价里,我们至少可以得出两个结论: 33 | 第一,蒋介石虽然一开始并不把毛泽东和红军放在眼里,动辄斥之以「共匪」,但对手多年,惺惺相惜,他依然尊重对手,并给予了公正客观的评价。这种心胸值得我们肯定。 34 | 第二,毛泽东居然能够对几十年的老烟瘾说停就停,这是何等惊人的意志力和自控能力!这样的自律更是值得我们去探究学习。 35 | 当然,除了毛泽东,客观来说,蒋介石年轻的时候也有过一段痛苦悔恨后,刻苦自律的经历。 36 | 而且两人都推崇的曾国藩,也是一个自律到极致的人。 37 | 曾国藩还经常引用一句名言来激励自己: 38 | 律己足以服人,量宽足以得人,身先足以率人。 39 | 而毛泽东拥有这样的自律能力,真的不是天生的。 40 | 1921 年 1 月 28 日,他在给彭璜写的一封信里吐露: 「弟有一最大缺点而不好意思向人公开者,即意弱是也。兄常谓我意志强,实则我有自知之明: 知最弱莫如我之意志! 41 | 但仅仅二十年后,他的意志力和自律能力就让蒋介石感到震惊。 42 | 这种意志力和自律能力一直保持到了他晚年。 43 | 1972 年 2 月,中美建交,毛泽东与尼克松、基辛格进行了一场历史性的会见。整个会见的过程是在幽默、轻松的气氛中展开的。 44 | 但从实质上看,并非一般说笑,毛泽东在会见的全过程中始终贯穿着自己坚定的原则和意志。他漫不经心、诙谐随意地驾驭着整个谈话。 45 | 以至使基辛格感到,除了戴高乐之外,从来没有遇到过一个人像毛泽东那样具有如此高度集中、不加掩饰的意志力。他成了凌驾整个房间的中心。 46 | 其实,毛泽东之所以能够有惊人的意志力和自律能力,正是因为他在年轻的时候,就意识到了自身意志的薄弱,更意识到了意志力对于人生的重要意义,经过刻苦修炼后的结果。 47 | 这段苦心修炼的经历值得每一个想要自律、想要升华自己人生的人学习。 48 | 我综合了大量史料,深入分析后,将这种修炼的过程,分为了四个层次。和大家一起分享。 49 | 03 50 | 第一个层次:学会从小事小节开始修炼自律 51 | 早在湖南第一师范求学的时候, 毛泽东就有意识地到喧闹的地方去练习闹中求静, 静中求学。 52 | 有一次, 他拿着书到长沙市最热闹的南门口去阅读, 任凭人来人往。声音嘈杂, 他只顾自己专心致志地看书。 53 | 有一位同学问他: 「你怎么到这种地方来看书啊?人来车往那么乱, 能看得下去吗? 」 54 | 毛泽东说:「就因为乱, 我才要来这里看。我要锻炼自己。」 55 | 同学又问「这是练的哪门子功?」 56 | 毛泽东答道: 「我们的国家不乱吗? 我要锻炼自己不为乱所动, 在乱中仍然集中全部精力去办成一件事, 朝着自己的目标走下去!」 57 | 在闹市中坚持读书,只是一件非常不起眼的小事。 58 | 却是修炼心性的一个好方法。 59 | 因为,成大事的人,首先就是要管得住小节。 60 | 要想修炼自律,从来都不是天天想着:现在自律不重要,等哪天要做大事了,需要了,我再来修炼。 61 | 因为真正要做一件大事的时候,需要的是你全身心的投入,已经没有精力和时间来给你练自律了。 62 | 不要一上来就给自己设计如何宏大的自律改变计划。 63 | 从一个小目标开始,形成一种习惯,让自律成为本能,又不带来很大的心理负担。 64 | 很多人就是因为调子定的太高,一尝试后发现根本做不到,而变得更加堕落的。 65 | 自律的关键,就是在私底下、无人时、细微处能否做到慎独慎微。 66 | 在这件事上,小的、连续不断的改变,比憋半天放个大招要有效的多。 67 | 这也是为什么很多人加强自律,都是从定期整理房间、每天去健身、早上背单词开始的。 68 | 因为这样坚持起来比较容易,而效果又非常明显。 69 | 每天自律一点点,就能一点点自律起来。 70 | 04 71 | 第二个层次:学会借助各种方式帮助强化自律 72 | 1912 年的时候毛泽东曾经有过一段时间的退学。 73 | 退学后的毛泽东寄居在湘乡会馆,每天都去湖南省立图书馆看书,他为自己制订了一个严格的自修计划,早上图书馆一开门就进去,中午只是买两块米糕充饥,算作午餐,直到图书馆关门才出来。 74 | 1936 年,毛泽东同斯诺谈话回顾这段经历时说:「每天到湖南省立图书馆去看书。我非常认真地执行,持之以恒 。我这样度过的半年时间,我认为对我极有价值 。」 75 | 在修炼自律的路上,一定要学着定下一些目标和计划。 76 | 漫无目的地去尝试自律,最是让人身心疲惫。 77 | 哪怕只是一个「每天晚上看 10 页书」的小目标,都能给你的自律修炼之旅带来成就感。 78 | 而这种成就感又会帮助你强化自律的状态。 79 | 除此外,在长沙求学的时候,毛泽东还热衷于体育锻炼,碰到下雨,他脱掉衬衫让雨淋,称之为雨浴;烈日当空,进行日光浴;春风吹来的时候,搞风浴;下霜的日子,搞露宿;甚至到 11 月份,他还在寒冷的河水里游泳。 80 | 无论春夏秋冬,从不间断。 81 | 这种刻意的体育锻炼,其实也是他锻炼自己自律能力的一种方式。 82 | 因为每一种类似「自虐」或者「苦行」的体育锻炼背后,都需要他和自己贪图舒服、懒惰的意识作心理的斗争。 83 | 毛泽东正是在跟桀骜不驯的大自然、头脑中的享乐观念进行不懈的斗争中,培养了勇猛无畏、坚韧不拔的意志力,成为实现其人生哲学的手段之一。 84 | 他曾经在自己的读书笔记中批判了懒惰,说「懒惰为万恶之渊薮。」 85 | 另一方面,通过这种方式也让身体习惯了自律。 86 | 身体的状态会影响意志力、控制情绪的能力,以及思考能力、判断能力等等。 87 | 一旦身体撑不住,精力跟不上,想要控制自己都不可能。 88 | 连续熬夜之后,人的意志力非常薄弱,很容易作出冲动之举,就是这个道理。 89 | 长期保持自律,不只是靠意志力、靠习惯,还要利用一切的内外部条件和力量。 90 | 包括身体的力量。 91 | 长征结束后,斯诺在延安第一次见到毛泽东,曾经给过他一个评价: 92 | 他精力过人,不知疲倦。 93 | 那时候的毛泽东每天工作十三四个小时,常常到深夜二三点钟才休息。 94 | 能保持如此高强度的工作状态,除了强大的自律精神,还离不开他年轻时锻炼出来的一副好身板。 95 | 05 96 | 第三个层次:学会控制欲望和情绪,远离诱惑 97 | 毛泽东的恩师杨昌济先生常教导学生说: 「意志之强者,对于己身,则能抑制情欲之横恣;对于杜会,则能抵抗权势之压迫。有不可夺之志,则事无不成矣。」 98 | 毛泽东深受其影响,成为这种理念的终身践行者。 99 | 在一师求学时,他以「 三不谈」 自律:不谈金钱, 不谈家庭琐事, 不谈男女之事。 100 | 金钱和欲望有关,家庭琐事和情绪有关,男女之事和诱惑有关。 101 | 要想真正做到自律,就一定要过这三关。 102 | 偏偏这又是最难的关口,很多人可以做到小事小节上自律,可以制定并严格完成计划,但在这三件事上,却很难做到坚持自己,不为所动。 103 | 毛泽东曾经多有钱,估计很多人都不知道。 104 | 我在《从小到大,他才是我们误解最大的历史人物》里,曾经写过,他在国民党手底下当高官的时候,一个月的工资有几百银元,是当时普通工人月工资的十倍不止。 105 | 但他从来没把这样的高收入放在心上,反而天天关心三农问题,跑去农村搞调研。 106 | 苏维埃曾经有一个国家银行,里面的钱大部分都是当年毛泽东带兵打下漳州后的战利品。 107 | 光大洋就有几百万,黄金 5 大担,还有 3 个担子的珠宝和 2 个担子的纸币。 108 | 由他的弟弟毛泽民保管着,封藏在一个山里。 109 | 藏的地点可能没几个人知道,说得夸张点,他和他的弟弟完全有可能把这笔巨款中的一部分变成私产。 110 | 但他却在长征开始前,无私的将这些钱分给了部队,在突围时发挥了很大的作用。 111 | 而他自己则从读中学开始,就经常是身无分文,心忧天下。 112 | 我看过一个资料,说他在一师读书期间,一共花了 160 元,这不是一笔小费用,但大部分都被他用来买书了。 113 | 他还参加过革命军,每个月军饷 7 元,也主要用来买报纸和书了。 114 | 其实,大多数人的失败,不是因为缺乏能力,而是缺乏控制自己欲望的能力。 115 | 一旦被欲望所吞噬,就可能急功近利,就可能走偏踏错,最终变得患得患失。 116 | 能够看淡人生欲望的人,才是真正能做到不服就干的人。 117 | 因为他的坚定行动里,除了理想,别无他物。 118 | 6 119 | 第四个层次:学会突破束缚,达到更高层次的自律 120 | 前面,提到了毛泽东在重庆期间短暂戒烟的经历。 121 | 但事实上,离开重庆后,他很快就恢复了吸烟的习惯,直到晚年才抽得少了。 122 | 从这点来看,似乎他还不够「高度自律」。 123 | 在我看来,小事小节是自律的基础,但那只是一种低层次的小自律;而毛泽东的自律,是更高层次上的自律。 124 | 是真正明白自己要什么、该做什么,有着强大内心驱动力的大自律。 125 | 我看很多宣传自律的文章里,第一条都是:不要晚睡。 126 | 坚持早睡是不是自律? 127 | 当然是。 128 | 但仅仅做到不晚睡就是真正的自律了吗? 129 | 不见得。 130 | 毛泽东长年累月习惯于半夜工作、白天睡觉,有时候为了写文章经常整夜整夜不睡。 131 | 但你能说他不自律吗? 132 | 自律要从小事小节中来,但当你进入更高层次的自律,建立大自律后,是可以忽略小自律的。 133 | 许多科研人才,经常不修边幅、胡子拉碴,却能够在自己钻研的领域里心无旁骛,保持高强度投入,做出惊人的成果来。 134 | 就是因为他们把所有的意志力都用到了更重要的事情上。 135 | 没有事的时候,不妨早睡。但当你为了更大的目标,有更重要的事情要做的时候,每天坚持晚睡反而成了一种自律。 136 | 而不是无所事事,沉浸在刷微博、刷抖音、刷朋友圈,看各种无聊综艺节目,耗到很晚。 137 | 康德说:所谓自由,不是随心所欲,而是自我主宰。 138 | 真正的自由,都是从一点一滴的自律中来。但当你修炼到了可以从心所欲的时候,反而不需要再去事事控制了。 139 | 就像达芬奇练基本功的时候,每天画鸡蛋。 140 | 当他已经能画出蒙娜丽莎的时候,还需要每天去画鸡蛋吗? 141 | 自律,就是一种不断修炼、层层精进的过程。 142 | 前面的所有基础,每个层次,都是为了让你有一天不需要再去专注于自己是否自律。 143 | 而是让自律成为自己的一种习惯,一种生活方式,身体的一部分。 144 | 甚至变成影响他人的一种能力,就像毛泽东成功地将他的自律带到了红军队伍中一样。 145 | 在历史里,我还读到过一个印象深刻的细节。 146 | 第二次反围剿前夕,红一方面军有大约 3 万人的总兵力。 147 | 这支军队在东固附近的山区埋伏了 20 多天以待敌军的到来,却始终没有人脱逃或者走漏风声。 148 | 这样的埋伏仗只有红军才能打,因为他们队伍的领袖,早已将自律的种子深深地扎根在了他们的心底。 149 | 07 150 | 最后,再多说一点,所有的自律都不是为了追求痛苦。 151 | 而是为了延迟满足。 152 | 真正痛苦的人,是不求上进的人,是为现状焦虑、又没有毅力和决心去改变自己的人。 153 | 王小波说:人的一切痛苦,都是对自己无能的愤怒。 154 | 这种无能为力的感觉,才是最痛苦的。 155 | 自律的第一步很艰辛,但真正有规律的生活,而不是失控之后,那种身心自由,掌控自己生活的状态其实非常美妙。 156 | 浮躁、焦虑、消沉、颓废等负面情绪,很少能够干扰到你的心境。 157 | 生活和时间变得有序,你的未来变得可预期、可控制。 158 | 你将会非常享受那种充满自信、欣喜常在心间的状态。 159 | 毛泽东在《讲堂录》中说,一般人喜躯壳之乐,「惟圣人不喜躯壳之乐利(即世俗之乐利),而喜精神之乐利」。 160 | 从这个角度讲,修炼自律其实就是帮助大家逐渐养成宁静、专一的心态,让人虽得意而不忘形、处困顿而不沉沦、临诱惑而不摇摆。 161 | 能够因自律而明志,因自律而生慧。能够少一些浮躁焦虑,多一些从容不迫;少一些进退失据,多一些挥洒有度。 162 | 我们从事一件大事情,下了一个大决定,如果最终能做成,大概都会经历这样一个阶段: 163 | 苦中作乐;以苦为乐;不以为苦反以为乐;不苦不乐一切平和。 164 | 再进一步,大概就是禅宗的境界了:什么是苦?什么是乐?心之所在,即是极乐。 165 | 当你下定决心开始自律,经过那段荒无人烟、披星戴月的艰苦修炼之后。 166 | 看到的日出,才是真正的美好。 167 | 享受到的,才是最高层次的满足感和成就感。 168 | 有些经验是从痛苦中得来的。 169 | 这些痛苦教育了我们。 170 | 我们不要对于这些痛苦生气。 171 | 相反,我们要感谢这些痛苦。 172 | 因为它使我们开动脑筋, 173 | 想一想,努力去避免那些痛苦。 174 | 果然,我们就避免了那些痛苦。 175 | 是不是呢?——毛泽东 176 | 177 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | ##Rules for linux 7 | *.out 8 | .vscode/* 9 | 10 | # User-specific files 11 | *.rsuser 12 | *.suo 13 | *.user 14 | *.userosscache 15 | *.sln.docstates 16 | 17 | # User-specific files (MonoDevelop/Xamarin Studio) 18 | *.userprefs 19 | 20 | # Mono auto generated files 21 | mono_crash.* 22 | 23 | # Build results 24 | [Dd]ebug/ 25 | [Dd]ebugPublic/ 26 | [Rr]elease/ 27 | [Rr]eleases/ 28 | x64/ 29 | x86/ 30 | [Ww][Ii][Nn]32/ 31 | [Aa][Rr][Mm]/ 32 | [Aa][Rr][Mm]64/ 33 | bld/ 34 | [Bb]in/ 35 | [Oo]bj/ 36 | [Oo]ut/ 37 | [Ll]og/ 38 | [Ll]ogs/ 39 | 40 | # Visual Studio 2015/2017 cache/options directory 41 | .vs/ 42 | # Uncomment if you have tasks that create the project's static files in wwwroot 43 | #wwwroot/ 44 | 45 | # Visual Studio 2017 auto generated files 46 | Generated\ Files/ 47 | 48 | # MSTest test Results 49 | [Tt]est[Rr]esult*/ 50 | [Bb]uild[Ll]og.* 51 | 52 | # NUnit 53 | *.VisualState.xml 54 | TestResult.xml 55 | nunit-*.xml 56 | 57 | # Build Results of an ATL Project 58 | [Dd]ebugPS/ 59 | [Rr]eleasePS/ 60 | dlldata.c 61 | 62 | # Benchmark Results 63 | BenchmarkDotNet.Artifacts/ 64 | 65 | # .NET Core 66 | project.lock.json 67 | project.fragment.lock.json 68 | artifacts/ 69 | 70 | # ASP.NET Scaffolding 71 | ScaffoldingReadMe.txt 72 | 73 | # StyleCop 74 | StyleCopReport.xml 75 | 76 | # Files built by Visual Studio 77 | *_i.c 78 | *_p.c 79 | *_h.h 80 | *.ilk 81 | *.meta 82 | *.obj 83 | *.iobj 84 | *.pch 85 | *.pdb 86 | *.ipdb 87 | *.pgc 88 | *.pgd 89 | *.rsp 90 | *.sbr 91 | *.tlb 92 | *.tli 93 | *.tlh 94 | *.tmp 95 | *.tmp_proj 96 | *_wpftmp.csproj 97 | *.log 98 | *.vspscc 99 | *.vssscc 100 | .builds 101 | *.pidb 102 | *.svclog 103 | *.scc 104 | 105 | # Chutzpah Test files 106 | _Chutzpah* 107 | 108 | # Visual C++ cache files 109 | ipch/ 110 | *.aps 111 | *.ncb 112 | *.opendb 113 | *.opensdf 114 | *.sdf 115 | *.cachefile 116 | *.VC.db 117 | *.VC.VC.opendb 118 | 119 | # Visual Studio profiler 120 | *.psess 121 | *.vsp 122 | *.vspx 123 | *.sap 124 | 125 | # Visual Studio Trace Files 126 | *.e2e 127 | 128 | # TFS 2012 Local Workspace 129 | $tf/ 130 | 131 | # Guidance Automation Toolkit 132 | *.gpState 133 | 134 | # ReSharper is a .NET coding add-in 135 | _ReSharper*/ 136 | *.[Rr]e[Ss]harper 137 | *.DotSettings.user 138 | 139 | # TeamCity is a build add-in 140 | _TeamCity* 141 | 142 | # DotCover is a Code Coverage Tool 143 | *.dotCover 144 | 145 | # AxoCover is a Code Coverage Tool 146 | .axoCover/* 147 | !.axoCover/settings.json 148 | 149 | # Coverlet is a free, cross platform Code Coverage Tool 150 | coverage*.json 151 | coverage*.xml 152 | coverage*.info 153 | 154 | # Visual Studio code coverage results 155 | *.coverage 156 | *.coveragexml 157 | 158 | # NCrunch 159 | _NCrunch_* 160 | .*crunch*.local.xml 161 | nCrunchTemp_* 162 | 163 | # MightyMoose 164 | *.mm.* 165 | AutoTest.Net/ 166 | 167 | # Web workbench (sass) 168 | .sass-cache/ 169 | 170 | # Installshield output folder 171 | [Ee]xpress/ 172 | 173 | # DocProject is a documentation generator add-in 174 | DocProject/buildhelp/ 175 | DocProject/Help/*.HxT 176 | DocProject/Help/*.HxC 177 | DocProject/Help/*.hhc 178 | DocProject/Help/*.hhk 179 | DocProject/Help/*.hhp 180 | DocProject/Help/Html2 181 | DocProject/Help/html 182 | 183 | # Click-Once directory 184 | publish/ 185 | 186 | # Publish Web Output 187 | *.[Pp]ublish.xml 188 | *.azurePubxml 189 | # Note: Comment the next line if you want to checkin your web deploy settings, 190 | # but database connection strings (with potential passwords) will be unencrypted 191 | *.pubxml 192 | *.publishproj 193 | 194 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 195 | # checkin your Azure Web App publish settings, but sensitive information contained 196 | # in these scripts will be unencrypted 197 | PublishScripts/ 198 | 199 | # NuGet Packages 200 | *.nupkg 201 | # NuGet Symbol Packages 202 | *.snupkg 203 | # The packages folder can be ignored because of Package Restore 204 | **/[Pp]ackages/* 205 | # except build/, which is used as an MSBuild target. 206 | !**/[Pp]ackages/build/ 207 | # Uncomment if necessary however generally it will be regenerated when needed 208 | #!**/[Pp]ackages/repositories.config 209 | # NuGet v3's project.json files produces more ignorable files 210 | *.nuget.props 211 | *.nuget.targets 212 | 213 | # Microsoft Azure Build Output 214 | csx/ 215 | *.build.csdef 216 | 217 | # Microsoft Azure Emulator 218 | ecf/ 219 | rcf/ 220 | 221 | # Windows Store app package directories and files 222 | AppPackages/ 223 | BundleArtifacts/ 224 | Package.StoreAssociation.xml 225 | _pkginfo.txt 226 | *.appx 227 | *.appxbundle 228 | *.appxupload 229 | 230 | # Visual Studio cache files 231 | # files ending in .cache can be ignored 232 | *.[Cc]ache 233 | # but keep track of directories ending in .cache 234 | !?*.[Cc]ache/ 235 | 236 | # Others 237 | ClientBin/ 238 | ~$* 239 | *~ 240 | *.dbmdl 241 | *.dbproj.schemaview 242 | *.jfm 243 | *.pfx 244 | *.publishsettings 245 | orleans.codegen.cs 246 | 247 | # Including strong name files can present a security risk 248 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 249 | #*.snk 250 | 251 | # Since there are multiple workflows, uncomment next line to ignore bower_components 252 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 253 | #bower_components/ 254 | 255 | # RIA/Silverlight projects 256 | Generated_Code/ 257 | 258 | # Backup & report files from converting an old project file 259 | # to a newer Visual Studio version. Backup files are not needed, 260 | # because we have git ;-) 261 | _UpgradeReport_Files/ 262 | Backup*/ 263 | UpgradeLog*.XML 264 | UpgradeLog*.htm 265 | ServiceFabricBackup/ 266 | *.rptproj.bak 267 | 268 | # SQL Server files 269 | *.mdf 270 | *.ldf 271 | *.ndf 272 | 273 | # Business Intelligence projects 274 | *.rdl.data 275 | *.bim.layout 276 | *.bim_*.settings 277 | *.rptproj.rsuser 278 | *- [Bb]ackup.rdl 279 | *- [Bb]ackup ([0-9]).rdl 280 | *- [Bb]ackup ([0-9][0-9]).rdl 281 | 282 | # Microsoft Fakes 283 | FakesAssemblies/ 284 | 285 | # GhostDoc plugin setting file 286 | *.GhostDoc.xml 287 | 288 | # Node.js Tools for Visual Studio 289 | .ntvs_analysis.dat 290 | node_modules/ 291 | 292 | # Visual Studio 6 build log 293 | *.plg 294 | 295 | # Visual Studio 6 workspace options file 296 | *.opt 297 | 298 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 299 | *.vbw 300 | 301 | # Visual Studio LightSwitch build output 302 | **/*.HTMLClient/GeneratedArtifacts 303 | **/*.DesktopClient/GeneratedArtifacts 304 | **/*.DesktopClient/ModelManifest.xml 305 | **/*.Server/GeneratedArtifacts 306 | **/*.Server/ModelManifest.xml 307 | _Pvt_Extensions 308 | 309 | # Paket dependency manager 310 | .paket/paket.exe 311 | paket-files/ 312 | 313 | # FAKE - F# Make 314 | .fake/ 315 | 316 | # CodeRush personal settings 317 | .cr/personal 318 | 319 | # Python Tools for Visual Studio (PTVS) 320 | __pycache__/ 321 | *.pyc 322 | 323 | # Cake - Uncomment if you are using it 324 | # tools/** 325 | # !tools/packages.config 326 | 327 | # Tabs Studio 328 | *.tss 329 | 330 | # Telerik's JustMock configuration file 331 | *.jmconfig 332 | 333 | # BizTalk build output 334 | *.btp.cs 335 | *.btm.cs 336 | *.odx.cs 337 | *.xsd.cs 338 | 339 | # OpenCover UI analysis results 340 | OpenCover/ 341 | 342 | # Azure Stream Analytics local run output 343 | ASALocalRun/ 344 | 345 | # MSBuild Binary and Structured Log 346 | *.binlog 347 | 348 | # NVidia Nsight GPU debugger configuration file 349 | *.nvuser 350 | 351 | # MFractors (Xamarin productivity tool) working folder 352 | .mfractor/ 353 | 354 | # Local History for Visual Studio 355 | .localhistory/ 356 | 357 | # BeatPulse healthcheck temp database 358 | healthchecksdb 359 | 360 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 361 | MigrationBackup/ 362 | 363 | # Ionide (cross platform F# VS Code tools) working folder 364 | .ionide/ 365 | 366 | # Fody - auto-generated XML schema 367 | FodyWeavers.xsd 368 | --------------------------------------------------------------------------------