From a5172579e3b67e04b2fcc5194c975673e9c49272 Mon Sep 17 00:00:00 2001 From: lzy Date: Sun, 23 Jun 2024 17:45:58 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=88=20style:?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- C01-绪论/C1-绪论.md | 58 ++------------- .../C2-数据类型,运算符和表达式.md | 5 +- C03-输入输出专题/C3-输入输出专题.md | 42 +++-------- C04-流程控制/C4-流程控制.md | 30 +------- C05-数组/C5-数组.md | 27 +------ C06-指针/C6-指针.md | 37 +--------- C07-函数/C7-函数.md | 45 +----------- C08-构造类型/C8-构造类型.md | 26 +------ C09-动态内存管理/C9-动态内存管理.md | 13 +--- C10-Makefile/C10-Makefile.md | 4 +- C11-数据结构/C11-数据结构.md | 56 +++++---------- C12-俄罗斯方块/C12-俄罗斯方块.md | 5 +- C13-IO/C13-IO.md | 38 ++-------- C14-文件系统/C14-文件系统.md | 47 +++--------- C15-进程/C15-进程.md | 27 ++----- C16-并发/C16-并发.md | 71 +++++++++++++++++++ 16 files changed, 138 insertions(+), 393 deletions(-) diff --git a/C01-绪论/C1-绪论.md b/C01-绪论/C1-绪论.md index 17a7f6c..f0532d9 100644 --- a/C01-绪论/C1-绪论.md +++ b/C01-绪论/C1-绪论.md @@ -1,4 +1,5 @@ # 目录 + - [目录](#目录) - [第一章 绪论](#第一章-绪论) - [第一节](#第一节) @@ -27,12 +28,6 @@ - [进程](#进程) - [防止写越界,防止内存泄漏,谁打开谁关闭,谁申请谁释放](#防止写越界防止内存泄漏谁打开谁关闭谁申请谁释放) - - - - - - # 第一章 绪论 课程地址,[史上最强最细腻的linux嵌入式C语言学习教程【李慧芹老师】_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV18p4y167Md/?spm_id_from=333.999.0.0&vd_source=4e03f52e94cfa281cde032856b1f93a7)。 @@ -49,8 +44,6 @@ | 1967 | B语言 | | 1973 | C语言 | - - ### C语言特点 1. 基础性语言 @@ -60,8 +53,6 @@ 5. 移植性好,执行效率高 6. 允许直接对硬件操作 - - ### C语言学习建议 1. 概念的正确性 @@ -69,8 +60,6 @@ 3. 阅读优秀的程序段 4. 大量练习,面试题 - - ### 课程思路 1. 基础概念 @@ -85,17 +74,13 @@ 10. 调试工具(gdb,make) 11. 常用库函数 - - ### 课程平台 -* 老师:64位的`redhat6`,`vim`,`gcc4.4.6(make)` -* 本人:`WSL-debian`,`vscode(remote ssh)`,`gcc12.2.0(make)`,`ohmyzsh(theme:eastwood)` +- 老师:64位的`redhat6`,`vim`,`gcc4.4.6(make)` +- 本人:`WSL-debian`,`vscode(remote ssh)`,`gcc12.2.0(make)`,`ohmyzsh(theme:eastwood)` 我的`gcc`版本比较新,所以很多提示比较完善,老师这个课程是很早的课,那个时候的gcc提示没有现在厉害,所以还是要结合老师的视频的思路,在当时提示不完善的时候是如何手撕代码分析出来的。 - - ## 第二节 ### 神一般的`Hello world!` @@ -122,8 +107,6 @@ int main(void) 用哪种`main`得看编译器环境,目前在`linux`的`gcc`下,`int main(void);`常用,需要传参用`int main(int argc, char **argv);`。 - - ### 源文件到可执行文件 #### gcc @@ -147,8 +130,6 @@ gcc hello.c # 得到a.out可执行文件 gcc hello.c -o myhello # 得到myhello可执行文件 ``` - - #### make ```bash @@ -159,14 +140,10 @@ $ ls hello hello.c ``` - - ### vim 老师对于常用的`.vimrc`做了一些介绍,笔者建议`vscode`的`remote-ssh`插件,可以在win的vscode编辑器享受linux的环境。 - - ## 第三节 ### 基本概念 @@ -192,7 +169,7 @@ int main(void) 这里我的gcc版本比较新,所以和老师的不一致,总之老师的意思就是 -> 不要忽略gcc的警告!!! +> 不要忽略gcc的警告!!! ```bash # 通过 -Wall 参数让gcc显示全部警告 @@ -216,9 +193,9 @@ hello.c:6:9: warning: unused variable ‘i’ [-Wunused-variable] ``` -* 例如说这个变量`i`定义了但是没用上,就是你清楚来龙去脉可以忽略的警告。 -* 而`malloc`那个警告就是在告诉你`malloc`所属的`stdlib.h`库未引入。 -* C语言程序往往如果能把警告都消除,错误也能解决。例如: +- 例如说这个变量`i`定义了但是没用上,就是你清楚来龙去脉可以忽略的警告。 +- 而`malloc`那个警告就是在告诉你`malloc`所属的`stdlib.h`库未引入。 +- C语言程序往往如果能把警告都消除,错误也能解决。例如: ```c #include @@ -270,20 +247,14 @@ cc a.c -o a fopen():No such file or directory ``` - - ##### 2. 以函数为单位来进行程序编写 `main`是特殊的定义,其实就是一个正在运行的线程。其实对于内核而言,是只有进程的概念,且与我们理解的进程、线程不一样。 - - ##### 3. 声明部分+实现部分 早期的编译器要求变量先定义后使用。 - - ##### 4. `return 0/exit(0)` 结束当前进程,是给父进程看的。 @@ -303,12 +274,8 @@ Hello world! 在我本地无法复现,新版本可能改了。 - - ##### 5. 多用空格空行 - - ##### 6. 添加注释 ```c @@ -328,25 +295,14 @@ func(){ #endif ``` - - #### 算法 解决问题的方法。(流程图,NS图,FSM有限状态机) - - #### 程序 用某种语言实现算法 - - #### 进程 - - #### 防止写越界,防止内存泄漏,谁打开谁关闭,谁申请谁释放 - - - diff --git a/C02-数据类型,运算符和表达式/C2-数据类型,运算符和表达式.md b/C02-数据类型,运算符和表达式/C2-数据类型,运算符和表达式.md index e3d41e3..ff0bc6c 100644 --- a/C02-数据类型,运算符和表达式/C2-数据类型,运算符和表达式.md +++ b/C02-数据类型,运算符和表达式/C2-数据类型,运算符和表达式.md @@ -1,4 +1,5 @@ # 目录 + - [目录](#目录) - [第二章 数据类型,运算符和表达式](#第二章-数据类型运算符和表达式) - [数据类型(基本数据类型)](#数据类型基本数据类型) @@ -13,10 +14,6 @@ - [表达式和语句的区别](#表达式和语句的区别) - [运算符相关代码](#运算符相关代码) - - - - # 第二章 数据类型,运算符和表达式 ## 数据类型(基本数据类型) diff --git a/C03-输入输出专题/C3-输入输出专题.md b/C03-输入输出专题/C3-输入输出专题.md index 75fa67e..82a15dd 100644 --- a/C03-输入输出专题/C3-输入输出专题.md +++ b/C03-输入输出专题/C3-输入输出专题.md @@ -1,4 +1,5 @@ # 目录 + - [目录](#目录) - [第三章 输入输出专题](#第三章-输入输出专题) - [内容](#内容) @@ -6,26 +7,22 @@ - [`printf`](#printf) - [`scanf`](#scanf) - [字符输入输出函数](#字符输入输出函数) - - - - - + - [字符串输入输出函数](#字符串输入输出函数) + - [练习专题](#练习专题) + - [夸脱水](#夸脱水) + - [三角形面积](#三角形面积) + - [求根公式](#求根公式) # 第三章 输入输出专题 input & output -> I/O(标准IO,文件IO) - - ## 内容 1. 格式化输入输出函数:`scanf`, `printf` 2. 字符输入输出函数:`getchar`, `putchar` 3. 字符串输入输出函数:`gets(!)`,`puts` - - ## 格式化输入输出函数 ![标准输出格式字符](https://s2.loli.net/2024/03/18/OMiu6CUDZy5RH3P.png) @@ -39,8 +36,6 @@ int printf(const char *format, ...); format: "%【修饰符】格式字符",参照图片标准输出修饰符和格式字符 ``` - - - 有关`l`修饰符的提醒 ```C @@ -63,16 +58,12 @@ int main() } ``` - - 传输一个5G的文件 ```c 5LL*1204LL*1204LL*1204LL ``` - - 定义一个宏,表示一年有多少秒 ```c @@ -80,16 +71,12 @@ int main() #define SEC_YEAR (60LL * 60LL * 24LL * 365LL) ``` - - - 函数 变参与定参重载的区别 - 变参:编译器只报警告,函数自己都不知道自己有多少个参数 - 定参重载:编译报错 - - - `\n`的作用 强制刷新缓冲区,以死循环调试举例。 @@ -105,8 +92,6 @@ while (1) printf("[%s:%d]after while().\n", __FUNCTION__, __LINE__); ``` - - - 完整代码 ```c @@ -200,8 +185,6 @@ int main() #define SEC_YEAR (60LL * 60LL * 24LL * 365LL) ``` - - ### `scanf` ```c @@ -211,8 +194,6 @@ format:抑制符* 放在循环结构中时要注意能否接收到正常内容 ``` - - - 完整代码 ```c @@ -301,8 +282,6 @@ int main() } ``` - - ## 字符输入输出函数 ```c @@ -357,8 +336,6 @@ char *fgets(char *s, int size, FILE *stream);// 最多读到'size-1'个 `getline`是`GNU libc`的方言,可以动态内存保证读取一整行。 - - ## 练习专题 ### 夸脱水 @@ -430,13 +407,13 @@ SRC=test.c OBJ=$(SRC:.c=.o) $(TARGET): $(OBJ) - $(CC) -o $@ $^ $(LDFLAGS) + $(CC) -o $@ $^ $(LDFLAGS) %.o: %.c - $(CC) $(CFLAGS) -c $< -o $@ + $(CC) $(CFLAGS) -c $< -o $@ clean: - rm -f $(TARGET) $(OBJ) + rm -f $(TARGET) $(OBJ) ``` ### 求根公式 @@ -474,4 +451,3 @@ void root(void) printf("x2 = %f\n", x2); } ``` - diff --git a/C04-流程控制/C4-流程控制.md b/C04-流程控制/C4-流程控制.md index dd3ba3b..da5ce9f 100644 --- a/C04-流程控制/C4-流程控制.md +++ b/C04-流程控制/C4-流程控制.md @@ -1,5 +1,6 @@ # 目录 +- [目录](#目录) - [流程控制](#流程控制) - [关键字](#关键字) - [详解选择](#详解选择) @@ -26,29 +27,22 @@ - [11](#11) - [12](#12) - # 流程控制 1. 顺序,选择,循环 2. NS图,流程图(工具:Visio,Dia) 3. 简单结构与复杂结构:自然流程 - - - 顺序:语句逐句执行 - 选择:出现了一种以上的情况 - 循环:在某个条件成立的情况下,重复执行某个动作 - - ## 关键字 - 选择:`if-else`,`switch-case` - 循环:`while`,`do-while`,`for`,`if-goto` - 辅助控制:`continue`,`break` - - ## 详解选择 ### `if-else` @@ -156,8 +150,6 @@ int main() } ``` - - ### `switch-case` ```c @@ -243,8 +235,6 @@ int main() } ``` - - ## 详解循环 ### `while` @@ -255,8 +245,6 @@ while(exp) loop; ``` - - ### `do-while` ```c @@ -268,8 +256,6 @@ do ``` - - ### `for` ```c @@ -278,15 +264,11 @@ for(exp1;exp2;exp3) loop; ``` - - ### `goto` - 慎重使用`if-goto` - `goto`实现的是 无条件的跳转,且不能跨函数跳转 - - ### 死循环 ```c @@ -296,16 +278,10 @@ for(;;); `ctrl + c`杀掉死循环。 - - ### 辅助控制 `break`,`continue` - - - - ## 练习专题 ### 1 @@ -364,8 +340,6 @@ for(;;); > > F - - ### 10 > 包括钻石型 @@ -384,4 +358,4 @@ for(;;); ### 12 -> 从半径为1开始,输出圆的面积,直到面积大于100为止 \ No newline at end of file +> 从半径为1开始,输出圆的面积,直到面积大于100为止 diff --git a/C05-数组/C5-数组.md b/C05-数组/C5-数组.md index 459384e..5d42740 100644 --- a/C05-数组/C5-数组.md +++ b/C05-数组/C5-数组.md @@ -1,4 +1,5 @@ # 目录 + - [目录](#目录) - [数组](#数组) - [一维数组](#一维数组) @@ -21,19 +22,14 @@ - [单词计数](#单词计数) - [多维数组](#多维数组) - # 数组 构造类型之一,连续存放。 - - > [!warning] > > 时间关系,大量的练习题,没有做笔记,只记录了题目。自己思考加看课程足矣。 - - ## 一维数组 1. 定义 @@ -57,8 +53,6 @@ 5. 数组越界 - - ### 练习部分 #### 斐波那契数列前10项 @@ -230,8 +224,6 @@ static void primer(void) } ``` - - ## 二维数组 1. 定义,初始化 @@ -285,10 +277,6 @@ static void primer(void) `a+1`跨越了行而不是单个元素。 - - - - ### 练习部分 #### 行列互换 @@ -299,10 +287,6 @@ static void primer(void) #### 矩阵乘积 - - - - ## 字符数组 1. 定义,初始化,存储特点 @@ -316,8 +300,6 @@ static void primer(void) 3. 常用函数 - - ### 常用函数 1. `strlen`和`sizeof` @@ -375,8 +357,6 @@ static void primer(void) // out:hello world ``` - - 4. `strcmp`与`strncmp` ```c @@ -387,17 +367,12 @@ static void primer(void) // 指定比较前5个字符 ``` - - ### 练习部分 #### 单词计数 - - ## 多维数组 ```c int a[2][3][4]; ``` - diff --git a/C06-指针/C6-指针.md b/C06-指针/C6-指针.md index a9a8c2d..6c329b7 100644 --- a/C06-指针/C6-指针.md +++ b/C06-指针/C6-指针.md @@ -1,4 +1,5 @@ # 目录 + - [目录](#目录) - [指针](#指针) - [变量与地址](#变量与地址) @@ -16,7 +17,6 @@ - [指针数组与数组指针](#指针数组与数组指针) - [多级指针](#多级指针) - # 指针 ## 变量与地址 @@ -27,8 +27,6 @@ `100`是存放在这个地址的变量的值。 - - ## 指针与指针变量 ```c @@ -39,14 +37,10 @@ int **q = &p; p是一个指针变量,他所存放的值是指针,指向另一个变量`i`的地址。 - - ## 直接访问与间接访问 同样对于上面那个存放值为`100`的变量,既可以通过`i`直接访问,也可以通过`*p, **q`来间接访问。 - - ```c #include #include @@ -122,8 +116,6 @@ int main() } ``` - - ## 空指针与野指针 - 野指针:`int *p = 0x14532534`,不确定这个地址的情况,盲目的指过去,那么读或者写都是非法的。 @@ -147,16 +139,12 @@ int main() } ``` - - ## 空类型 `void *q` 万能类型。 - - ## 定义与初始化的书写规则 ```c @@ -164,13 +152,9 @@ int *p; int* p; ``` - - ## 指针运算 -`&` ` *` 关系运算 `++` `--` - - +`&` `*` 关系运算 `++` `--` ## 指针与数组 @@ -269,8 +253,6 @@ int main() } ``` - - ### 指针与二维数组 ```c @@ -326,8 +308,6 @@ int main() } ``` - - ### 指针与字符数组 ```c @@ -387,8 +367,6 @@ int main() } ``` - - ## const 与指针 - 常量指针:**指向常量的指针** @@ -494,10 +472,6 @@ int main() ``` - - - - ## 指针数组与数组指针 - 数组指针:指向数组的**指针**。 @@ -512,8 +486,6 @@ int main() 如:`int *arr[3];` 看成 `int *[3] arr;` - - ```c #include #include @@ -552,9 +524,4 @@ int main() } ``` - - - - ## 多级指针 - diff --git a/C07-函数/C7-函数.md b/C07-函数/C7-函数.md index 45fdb39..c7b111b 100644 --- a/C07-函数/C7-函数.md +++ b/C07-函数/C7-函数.md @@ -1,4 +1,5 @@ # 目录 + - [目录](#目录) - [函数](#函数) - [函数的定义](#函数的定义) @@ -16,15 +17,12 @@ - [函数指针数组](#函数指针数组) - [指向指针函数的函数指针数组](#指向指针函数的函数指针数组) - # 函数 ## 函数的定义 数据类型 函数名 ( 【数据类型 形参名,数据类型 形参,...】 ) - - ```c #include #include @@ -45,8 +43,6 @@ int main(int argc, char *argv[]) } ``` - - ```c #include #include @@ -70,8 +66,6 @@ void print_hello(void) } ``` - - ## 函数的传参 值传递 @@ -127,10 +121,6 @@ int main() } ``` - - - - ## 函数的调用 ### 嵌套调用 @@ -170,8 +160,6 @@ int main() } ``` - - ### 递归调用 ```c @@ -229,10 +217,6 @@ int main() } ``` - - - - ## 函数与数组 ### 一维数组 @@ -253,8 +237,6 @@ int *p = a; | *p | int | | p+1 | int* | - - ```c #include #include @@ -310,8 +292,6 @@ int main() } ``` - - ### 二维数组 ```c @@ -326,8 +306,6 @@ int (*q)[N] = a; // 行指针 ``` - - | 传参 | 类型 | | -------------------------- | -------------------------------------- | | `a[i][j]` | int | @@ -336,9 +314,9 @@ int (*q)[N] = a; | `p[i]` | ~~int [N] *~~ 正确答案: int | | `*p` | ~~int [N] *~~ 正确答案: int | | `q[i][j]` | int | -| `*q` | ~~int [N] *~~ 正确答案: int * | +| `*q` | ~~int [N] *~~ 正确答案: int* | | `q` | int (*) [N] | -| `p+3` | ~~int [N] *~~ 正确答案: int * | +| `p+3` | ~~int [N] *~~ 正确答案: int* | | `q+2` | ~~int [N] *~~ 正确答案: int (*) [N] | ```c @@ -421,10 +399,6 @@ int main() } ``` - - - - ### 字符数组 ```c @@ -470,10 +444,6 @@ int main() } ``` - - - - ## 函数与指针 ### 指针函数 @@ -484,8 +454,6 @@ int main() 如:`int * fun(int);` - - ### 函数指针 是一个**指针**,指向**函数**。 @@ -494,8 +462,6 @@ int main() 如: `int (*p)(int);` - - ### 函数指针数组 由**函数指针**组成的数组。 @@ -504,14 +470,10 @@ int main() 如: `int (*arr[N])(int);` - - ### 指向指针函数的函数指针数组 `int *(*funcp[N])(int)` - - ```c #include #include @@ -553,4 +515,3 @@ int main() exit(0); } ``` - diff --git a/C08-构造类型/C8-构造类型.md b/C08-构造类型/C8-构造类型.md index 091a6c0..2ed0357 100644 --- a/C08-构造类型/C8-构造类型.md +++ b/C08-构造类型/C8-构造类型.md @@ -1,4 +1,5 @@ # 目录 + - [目录](#目录) - [构造类型](#构造类型) - [结构体](#结构体) @@ -19,7 +20,6 @@ - [枚举](#枚举) - [typedef](#typedef) - # 构造类型 ## 结构体 @@ -39,26 +39,16 @@ struct 结构体名 }; ``` - - ### 嵌套定义 ### 定义变量(变量,数组,指针),初始化及成员引用 - - 成员引用: 变量名. 成员名,指针->成员名,(*指针).成员名 - - ### 结构体占用的内存空间大小 - - ### 函数传参(值,地址) - - ```c #include #include @@ -175,10 +165,6 @@ int main() } ``` - - - - > 跳过 ## 共用体 @@ -196,8 +182,6 @@ union 共用体名 }; ``` - - ### 嵌套定义 ### 定义变量(变量,数组,指针),初始化及成员引用 @@ -208,12 +192,6 @@ union 共用体名 ### 位域 - - - - - - ## 枚举 ```c @@ -229,4 +207,4 @@ enum 标识符 为已有的数据类型改名。 -`typedef 已有的数据类型 新名字;` \ No newline at end of file +`typedef 已有的数据类型 新名字;` diff --git a/C09-动态内存管理/C9-动态内存管理.md b/C09-动态内存管理/C9-动态内存管理.md index 78fa849..2c9a280 100644 --- a/C09-动态内存管理/C9-动态内存管理.md +++ b/C09-动态内存管理/C9-动态内存管理.md @@ -1,10 +1,10 @@ # 目录 + - [目录](#目录) - [动态内存管理](#动态内存管理) - [函数传参相关问题](#函数传参相关问题) - [关于 free](#关于-free) - # 动态内存管理 ```` c @@ -14,12 +14,8 @@ void free(void *ptr); void *realloc(void *ptr, size_t size); // 重新分配空间 ```` - - 原则:谁申请谁释放。 - - ## 函数传参相关问题 1. 要么用二级指针 @@ -65,10 +61,6 @@ int main() ``` - - - - ## 关于 free `free`操作没有扣掉那块内存,没有改变那块内存的值,也没有改变指针的指向。 @@ -110,6 +102,3 @@ int main() } ``` - - - diff --git a/C10-Makefile/C10-Makefile.md b/C10-Makefile/C10-Makefile.md index b665909..68527ec 100644 --- a/C10-Makefile/C10-Makefile.md +++ b/C10-Makefile/C10-Makefile.md @@ -4,8 +4,6 @@ `make`会优先使用`makefile`,发布的项目一般是一个`Makefile`,方便用户写自己的`makefile`。 - - ## 参考资料 -[跟我一起写Makefile — 跟我一起写Makefile 1.0 文档 (seisman.github.io)](https://seisman.github.io/how-to-write-makefile/) \ No newline at end of file +[跟我一起写Makefile — 跟我一起写Makefile 1.0 文档 (seisman.github.io)](https://seisman.github.io/how-to-write-makefile/) diff --git a/C11-数据结构/C11-数据结构.md b/C11-数据结构/C11-数据结构.md index c1d782e..cff3ac5 100644 --- a/C11-数据结构/C11-数据结构.md +++ b/C11-数据结构/C11-数据结构.md @@ -1,14 +1,14 @@ # 目录 + - [目录](#目录) - [数据结构](#数据结构) - [架构梳理](#架构梳理) - [静态库与动态库](#静态库与动态库) - [静态库](#静态库) - - [以链式双向链表的`lib2`为例。](#以链式双向链表的lib2为例) + - [以链式双向链表的`lib2`为例](#以链式双向链表的lib2为例) - [动态库](#动态库) - - [还是以`lib2`为例。](#还是以lib2为例) - - [以链式存储栈为例,`libstack`依赖`libllist`。](#以链式存储栈为例libstack依赖libllist) - + - [还是以`lib2`为例](#还是以lib2为例) + - [以链式存储栈为例,`libstack`依赖`libllist`](#以链式存储栈为例libstack依赖libllist) # 数据结构 @@ -27,18 +27,18 @@ 会更加简单,无头的话,更改首部节点会麻烦。 头节点不仅可以作为起点,还可以作为存储信息的仓库,因为头节点只有*next是必须的。 - + - 单链表 - 循环 - 不循环 - + - 双向链表 - + `lib`四个版本,第一个最基础完善,第二个改成了变长结构体,第三个在第二个的基础上封装了函数指针,第四个在第二个的基础上隐藏了数据结构,只暴露接口。 - + - 循环 - 不循环 - + 学到这里可以去读一下内核有关**list**的实现,主要都是宏和内联函数。 - 栈 @@ -52,8 +52,6 @@ 2. 球钟算法 三个栈,1h,5min,1min。27个球,过了多久队列里又是1到27的顺序。 - - - 树状(1:N) **递归**。**递归**转**非递归**。 @@ -86,35 +84,25 @@ - 后序(左,右,根) 先加中,或者,中加后,都可以逆推出树。先加后不行。 - - - + - 平衡: 有很多种条件判定。 这棵树的左右子树个数差值为1。 - - - 广义表 - `( root ( left ) ( right) )`,进行嵌套。 - - - + `( root ( left ) ( right) )`,进行嵌套。 + - 搜索树 空间换时间,查找是**o(1)**。 **课后作业:词频统计** - - - 图(N:M) - - ## 静态库与动态库 - 静态库: @@ -124,8 +112,6 @@ - 公交车,只能在指定的路径。 - 运行时引入,占用运行时间。 - - ### 静态库 1. `libxx.a` @@ -140,9 +126,7 @@ 5. `ldd -print shared libirary dependencies` 打印所用到的动态库的内容 - - -#### 以链式双向链表的`lib2`为例。 +#### 以链式双向链表的`lib2`为例 ```bash *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ldd ./main @@ -180,10 +164,9 @@ 1 std1 77 15 0 std0 83 86 ``` + 这时`main.c`路径下都不需要`llist.c`和`llist.h`了,`#include`时也从`"llist.h"`变为``。 - - ### 动态库 1. `libxx.so` @@ -203,10 +186,7 @@ cp xx.co ~/lib export LD_LIBRARY_PATH= ~/lib ``` - - -#### 还是以`lib2`为例。 - +#### 还是以`lib2`为例 ```bash *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/list/linklist/double/lib2]$ ls @@ -246,9 +226,7 @@ export LD_LIBRARY_PATH= ~/lib > > 当动态库和静态库重名,会优先链接**静态库**。 - - -#### 以链式存储栈为例,`libstack`依赖`libllist`。 +#### 以链式存储栈为例,`libstack`依赖`libllist` ```bash *[main][~/workspace/Linux-C-Notes/Chapter11/ds/line/stack/list]$ ls @@ -291,4 +269,4 @@ collect2: error: ld returned 1 exit status 0 stu0 83 86 ``` -添加动态库记得重载配置文件`sudo /sbin/ldconfig`! \ No newline at end of file +添加动态库记得重载配置文件`sudo /sbin/ldconfig`! diff --git a/C12-俄罗斯方块/C12-俄罗斯方块.md b/C12-俄罗斯方块/C12-俄罗斯方块.md index 3dc676f..41bafab 100644 --- a/C12-俄罗斯方块/C12-俄罗斯方块.md +++ b/C12-俄罗斯方块/C12-俄罗斯方块.md @@ -2,13 +2,12 @@ 1. 图形 - ANSI_VT,framebuffer + ANSI_VT,framebuffer 前者以光标为单位,后者以像素为单位。 - 推荐后者。 + 推荐后者。 2. 输入设备 3. 并发 - diff --git a/C13-IO/C13-IO.md b/C13-IO/C13-IO.md index 5c96602..b07c1d5 100644 --- a/C13-IO/C13-IO.md +++ b/C13-IO/C13-IO.md @@ -1,10 +1,11 @@ # 目录 + - [目录](#目录) - [I/O操作](#io操作) - [标准IO](#标准io) - [文件IO/系统调用IO](#文件io系统调用io) - [文件描述符的概念](#文件描述符的概念) - - [文件IO操作相关函数:](#文件io操作相关函数) + - [文件IO操作相关函数](#文件io操作相关函数) - [例题:通过文件IO处理csv表格](#例题通过文件io处理csv表格) - [文件IO与标准IO的区别](#文件io与标准io的区别) - [IO的效率问题](#io的效率问题) @@ -17,7 +18,6 @@ - [同步](#同步) - [/dev/fd/目录](#devfd目录) - # I/O操作 输入输出是一切实现的基础。 @@ -28,8 +28,6 @@ 优先使用**标准IO**,兼容性更好,还有合并系统调用的优势。 - - ## 标准IO ```c @@ -205,23 +203,17 @@ FILE *tmpfile(void); ``` - - ## 文件IO/系统调用IO 文件描述符(`fd`)是在文件IO中贯穿始终的类型。 - - ### 文件描述符的概念 是一个整型数,是一个指针数组的下标。 优先使用当前可用范围内最小的。 - - -### 文件IO操作相关函数: +### 文件IO操作相关函数 - `open` - `close` @@ -305,8 +297,6 @@ off_t lseek(int fd, offt offset, int whence); ``` - - ### 例题:通过文件IO处理csv表格 ```csv @@ -320,8 +310,6 @@ off_t lseek(int fd, offt offset, int whence); 可以使用16进制查看工具 - - ### 文件IO与标准IO的区别 区别:响应速度&吞吐量 @@ -330,17 +318,11 @@ off_t lseek(int fd, offt offset, int whence); 响应速度快就文件IO,吞吐量大就标准IO。 - - > [!warning] > 二者不可混用 - - 转换方法:`fileno`, `fdopen` - - ### IO的效率问题 #### 习题 @@ -399,8 +381,6 @@ rm $dst ``` - - #### 结果 ```bash @@ -424,8 +404,6 @@ Max BUFSIZE before segfault: 8388608 在`ulimit -a`中,我的系统的`stack size`是`8192`,所以`BUFSIZE`不能超过`8192`,否则会段错误。与测试结果一致。 - - ### 文件共享 多个任务共同操作一个文件或者协同完成任务 @@ -465,8 +443,6 @@ p1->read -> p2->write ``` - - ### 原子操作 指不可分割的操作 @@ -475,8 +451,6 @@ p1->read -> p2->write 如`tmpnam`函数,产生文件名和创建文件是两步,会有并发问题。 - - ### 程序中的重定向:`dup`, `dup2` ```c @@ -489,8 +463,6 @@ int dup(int oldfd); int dup2(int oldfd, int newfd); ``` - - ### 同步 同步内核层面的buffer和cache @@ -508,8 +480,6 @@ int ioctl(int fd, unsigned long request, ... /* arg */); ``` - - ### /dev/fd/目录 -**虚目录**:显示当前进程的文件描述符信息 \ No newline at end of file +**虚目录**:显示当前进程的文件描述符信息 diff --git a/C14-文件系统/C14-文件系统.md b/C14-文件系统/C14-文件系统.md index 70b0f45..a38eb59 100644 --- a/C14-文件系统/C14-文件系统.md +++ b/C14-文件系统/C14-文件系统.md @@ -1,4 +1,5 @@ # 目录 + - [目录](#目录) - [文件系统](#文件系统) - [目录和文件](#目录和文件) @@ -13,15 +14,12 @@ - [函数之间正常的跳转](#函数之间正常的跳转) - [资源的获取及控制](#资源的获取及控制) - # 文件系统 类`ls`的实现,如`myls -l -a -i -n` `cmd --长格式 -短格式 非选项的传参` - - ## 目录和文件 1. 获取文件属性 @@ -90,17 +88,16 @@ int fchmod(int fd, mode_t mode); 文件或数据的存储格式。 1. `FAT`:静态存储的单链表 - ```c - struct node_st{ - int next[N]; - char data[N][SIZE]; - }; - ``` - - 2. `UFS`: - 缺点:不善于处理大量的小文件,因为每个文件都有一个`inode`,占用空间。 - - + ```c + struct node_st{ + int next[N]; + char data[N][SIZE]; + }; + ``` + + 2. `UFS`: + 缺点:不善于处理大量的小文件,因为每个文件都有一个`inode`,占用空间。 + > 面试题: > 不用比较,比较两个uint32_t的大小 > 使用位图 @@ -114,13 +111,11 @@ int fchmod(int fd, mode_t mode); 限制:不能给分区建立,不能给目录建立 - - 符号链接 `ln -s bigfile_link bigfile_s` 优点:可以跨分区,可以给目录建立 - ```c int link(const char *oldpath, const char *newpath); @@ -275,8 +270,6 @@ long telldir(DIR *dirp); 作业:用另一套函数实现`mydu` - - ## 系统数据文件和信息 > 不同环境可能有区别,以具体查询为准,这里以Linux为例 @@ -434,8 +427,6 @@ size_t strftime(char *s, size_t max, const char *format, strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm); ``` - - ## 进程环境 ### `main`函数 @@ -444,8 +435,6 @@ strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tm); int main(int argc, char *argv[]); ``` - - ### 进程的终止 1. 正常终止: @@ -470,7 +459,6 @@ int main(int argc, char *argv[]); - 接到一个信号并终止 - 最后一个线程对其取消请求作出响应 - ```c /** * 注册一个函数,当进程终止时调用 @@ -481,8 +469,6 @@ int main(int argc, char *argv[]); int atexit(void (*function)(void));// 钩子函数 ``` - - ### 命令行参数的分析 ```c @@ -498,8 +484,6 @@ int getopt_long(int argc, char *const argv[], const char *optstring, const struct option *longopts, int *longindex); ``` - - ### 环境变量 **KEY = VALVE** @@ -525,14 +509,10 @@ int unsetenv(const char *name); int putenv(char *string); ``` - - ### C程序的存储空间布局 `pmap`命令,查看进程空间布局 - - ### 库 - 动态库 @@ -549,8 +529,6 @@ int putenv(char *string); // Link with -ldl ``` - - ### 函数之间正常的跳转 `goto`无法跨函数跳转。 @@ -573,8 +551,6 @@ int setjmp(jmp_buf env); void longjmp(jmp_buf env, int val); ``` - - ### 资源的获取及控制 `ulimit -a` @@ -591,4 +567,3 @@ struct rlimit { rlim_t rlim_max; /* hard limit */ }; ``` - diff --git a/C15-进程/C15-进程.md b/C15-进程/C15-进程.md index bdb43b4..0ac405c 100644 --- a/C15-进程/C15-进程.md +++ b/C15-进程/C15-进程.md @@ -1,4 +1,5 @@ # 目录 + - [目录](#目录) - [进程基本知识](#进程基本知识) - [进程标识符`pid`](#进程标识符pid) @@ -13,7 +14,6 @@ - [守护进程](#守护进程) - [系统日志](#系统日志) - # 进程基本知识 已经进入**多进程**阶段 @@ -36,8 +36,6 @@ pid_t getpid(void); pid_t getppid(void); ``` - - ## 进程的产生 `pid_t fork();` @@ -68,8 +66,6 @@ pid_t getppid(void); pid_t vfork(void); ``` - - ## 进程的消亡及释放资源 ```c @@ -90,8 +86,6 @@ wait4(); 池类算法: 上游往池子里放任务,下游三个线程从池子里取任务。 - - ## `exec`函数族 eg. `bash`进程创建`primer`进程 @@ -172,8 +166,6 @@ int setregid(gid_t rgid, gid_t egid); ``` - - ## 观摩课:解释器文件 > unix讲究机制而非策略 @@ -188,8 +180,6 @@ int setregid(gid_t rgid, gid_t egid); `#!`是一种约定俗成的标记,告诉系统这个脚本应该用什么解释器来执行。 - - ## `system()`函数 ```c @@ -202,8 +192,6 @@ int system(const char *command); 相当于`fork+exec+wait`的封装 - - ## 进程会计 ```c @@ -211,8 +199,6 @@ int system(const char *command); int acct(const char *filename); ``` - - ## 进程时间 ```c @@ -229,8 +215,6 @@ struct tms{ ``` - - ## 守护进程 1. 守护进程`PPID`为1 @@ -248,19 +232,16 @@ pid_t getpgrp(psid_t pid); //! 方言 - 会话(session):一个或多个进程组的集合,以`sid`为标识 `pid_t setsid(void);` `setsid`必须由非`leader`进程调用,从而创建一个新的会话。 - - 前台进程组:正在与终端交互的进程组 - - 后台进程组:正在运行,但不与终端交互的进程组 + - 前台进程组:正在与终端交互的进程组 + - 后台进程组:正在运行,但不与终端交互的进程组 - 终端: 我们接触的都是虚拟终端 - **单实例守护进程**:锁文件`/var/run/name.pid` 启动脚本文件:`/etc/rc*...` - - ## 系统日志 `syslogd`服务 @@ -295,4 +276,4 @@ void closelog(void); ```bash sudo tail /var/log/messages # 老师 journalctl -r # 我的debian -``` \ No newline at end of file +``` diff --git a/C16-并发/C16-并发.md b/C16-并发/C16-并发.md index aa41a07..efe86ff 100644 --- a/C16-并发/C16-并发.md +++ b/C16-并发/C16-并发.md @@ -299,3 +299,74 @@ struct timeval { 此外都和标准信号一样 ## 线程(强烈异步) + +### 线程的概念 + +会话-->进程-->线程 + +一个正在运行的函数。 + +`main`函数可以叫做main线程,不应该说主线程,线程之间平等。 + +`posix`线程是一套标准,而不是实现。 +`openmp`线程。 + +例如,线程标识: `pthread_t`, 具体类型怎么实现是不知道的 +在linux环境,可以通过`ps axm`或者`ps -ax -L`查看线程信息。 +发现线程消耗了进程号。 + +```c +#include +//* Compile and link with -pthread + +/** + * 比较两个pthread_t是否相等 + * @param: t1: pthread_t + * @param: t2: pthread_t + * + * @return: 相等返回非0,不相等返回0 + */ +int pthread_equal(pthread_t t1, pthread_t t2); + +/** + * 获取当前线程的pthread_t + * @return: 当前线程的pthread_t + */ +pthread_t pthread_self(void); + +``` + +### 线程的操作 + +创建,终止,取消,栈的清理 + +线程的调度取决于调度器策略。 + +```c +#include +// Compile and link with -pthread + +/** + * 创建线程 + * @param: thread: 线程ID指针 + * @param: attr: 线程属性指针 + * NULL: 默认属性 + * @param: start_routine: 线程函数指针 + * void *(*)(void *) + * @param: arg: 线程函数参数 + * + * @return: 成功返回0,失败返回errCode + * 建议使用strerror而非perror + */ +int pthread_create(pthread_t * thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), + void *arg); + +``` + +### 线程的同步 + +### 线程属性,线程同步的属性 + +### 重入,线程与信号,线程与`fork`