├── 7.30诺瓦科技 ├── linux内核裁剪的方式.md ├── tcp物理层的具体内容.md ├── 关于时钟发生器的英文翻译.md └── 示波器采集数据的要求.md ├── 8.1Dji大疆 ├── C关键词的描述.md ├── C函数使用注意.md ├── C有符号的变量和无符号的变量相加.md ├── C语言编译执行的四个阶段.md ├── Linux多任务进程线程之间的关系.md ├── Linux查询进程和线程数量.md ├── OScache多任务调度描述.md ├── OScache缓存一致性描述.md ├── OS中断处理过程的描述.md ├── OS处理器读取内存的过程 (copy).md ├── OS处理器读取内存的过程.md ├── OS如何实现进程间的切换.md ├── OS实时和非实时性.md ├── OS嵌入式系统指定位反转.md ├── OS简述一个执行程序在运行时的内存布局.md ├── OS简述线程之间的同步互斥时占用空间的大小.md ├── OS系统设计.md ├── cpu对锁的支持.md ├── linux内核中常用的两个宏定义.md ├── linux目录结构.md ├── linux系统打开设备文件处于的状态.md ├── photo │ ├── Cobject_link.png │ ├── INTR.png │ ├── big-small-endian.png │ ├── emebeded_OS.png │ ├── pointer_judge.png │ └── thread_status.png ├── 大端小端存储问题.md └── 简述C函数中参数传递问题.md ├── 8.24HIK ├── C中全局变量和局部变量可以重名.md ├── C宏使用.md └── list相关操作.md ├── 8.3网易 ├── Dijkstra最短路径算法的描述.md ├── LInux系统权限.md ├── echo重定义和grep正则表达式匹配.md ├── linux_chmod.png └── 二叉树节点和度.md ├── C ├── C中常量的表示.md ├── C变量的生命周期.md ├── C实现一个数的四舍五入.md ├── C实现函数跳转到绝对地址0x100000处执行.md ├── C对于一个频繁使用的短小函数.md ├── C简述static关键字对于工程模块化的作用.md ├── C运算符的优先级.md ├── IGBT是什么控制性原件.md ├── PC寻址范围.md ├── Token划分.md ├── error的目的是什么.md ├── photo │ ├── memcpy.png │ ├── operator_priority.png │ ├── pointer.png │ └── watch_dog.png ├── 单片机应用程序架构.md ├── 如何写C嵌入式的死循环.md ├── 指针和引用的区别.md ├── 用变量a给出下面的定义.md └── 看门狗程序的应用.md ├── OS ├── ARM体系结构下的MMU如何实现映射.md ├── Bootloader.md ├── JTag用途.md ├── Linux中断之间区别.md ├── Linux中断分层的概念.md ├── Linux中的RCU.md ├── Linux内核启动流程.md ├── Linux内核和用户程序运行在物理地址还是虚拟地址.md ├── Linux内核的五个模块描述.md ├── Linux字符驱动和块驱动模型.md ├── Linux抽象出framebuffer这个设备的作用.md ├── Linux系统调用函数copy_from_user.md ├── Linux虚拟文件系统的关键数据结构有哪些.md ├── Linux进程上下文切换和中断上下文切换.md ├── Linux驱动模型platform.md ├── MIPScpu地址空间划分.md ├── OS信号量互斥体自旋锁的概念.md ├── OS同步机制的实现.md ├── Oops.md ├── Uboot如何给kernel传参数.md ├── cache的解析.md ├── ioctl和unlock_ioctl的区别.md ├── linux7种文件类型.md ├── linux中netfilter的实现机制.md ├── linux中系统调用过程.md ├── linux内存管理.md ├── linux内核中多级分页目录结构.md ├── linux内核中的锁和同步机制.md ├── linux计算页表项大小.md ├── photo │ ├── AIO_result.png │ ├── DMA.png │ ├── IO_model.png │ ├── MMU_cache.png │ ├── VFS_kernel.png │ ├── bootloader.png │ ├── cache.png │ ├── driver_enter.png │ ├── driver_enter.svg │ ├── interrupt_reason.png │ ├── linux_hook.png │ ├── linux_kernel_start.png │ ├── linux_memory.png │ ├── memory_malloc.png │ ├── mips_cpu.png │ ├── mips_kseg.png │ ├── mtd_struct.png │ ├── page_number.png │ ├── page_table.png │ ├── platform.png │ ├── process_status.png │ ├── ret_sys.png │ ├── sem_pv.png │ ├── spin_lock_sem.png │ └── sys_call.png ├── 主设备号和次设备号的用途.md ├── 内存泄漏的理解.md ├── 几组概念.md ├── 四大CPU体系结构.md ├── 嵌入式的volatile变量.md ├── 访问固定的内存位置.md └── 驱动中的一些查看命令.md ├── README.md ├── SVG_photo ├── ADC_sampling.svg ├── linux kernel 启动流程.svg └── process_status.svg ├── TCP ├── DNS服务器是如何工作的.md ├── IGMP组播中的MAC地址.md ├── OSI七层中的硬件设备.md ├── Socket建立连接过程.md ├── http和TCP之间的关联.md ├── photo │ ├── RIP.png │ ├── TCP_MSL.png │ ├── http_connect.png │ ├── http_ways.png │ ├── https_connect.png │ ├── port.png │ ├── ssl_connect.png │ ├── tcp_flow.png │ └── tcp_three.png ├── tcp和udp的区别.md └── 基于UDP实现可靠传输.md ├── code ├── .idea │ ├── .gitignore │ ├── code.iml │ ├── misc.xml │ ├── modules.xml │ └── vcs.xml ├── CMakeLists.txt ├── README.md ├── cmake-build-debug │ ├── CMakeCache.txt │ ├── CMakeFiles │ │ ├── 3.14.5 │ │ │ ├── CMakeCCompiler.cmake │ │ │ ├── CMakeDetermineCompilerABI_C.bin │ │ │ ├── CMakeSystem.cmake │ │ │ └── CompilerIdC │ │ │ │ ├── CMakeCCompilerId.c │ │ │ │ └── a.out │ │ ├── 3.15.3 │ │ │ ├── CMakeCCompiler.cmake │ │ │ ├── CMakeDetermineCompilerABI_C.bin │ │ │ ├── CMakeSystem.cmake │ │ │ └── CompilerIdC │ │ │ │ ├── CMakeCCompilerId.c │ │ │ │ └── a.out │ │ ├── CMakeDirectoryInformation.cmake │ │ ├── CMakeOutput.log │ │ ├── Makefile.cmake │ │ ├── Makefile2 │ │ ├── TargetDirectories.txt │ │ ├── array_transmit_paramter.dir │ │ │ ├── C.includecache │ │ │ ├── DependInfo.cmake │ │ │ ├── array_transmit_paramter.c.o │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── depend.internal │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ └── progress.make │ │ ├── clion-environment.txt │ │ ├── clion-log.txt │ │ ├── cmake.check_cache │ │ ├── code.dir │ │ │ ├── DependInfo.cmake │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ └── progress.make │ │ ├── double_array_tran_pram.dir │ │ │ ├── C.includecache │ │ │ ├── DependInfo.cmake │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── depend.internal │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ └── progress.make │ │ ├── feature_tests.bin │ │ ├── feature_tests.c │ │ ├── funcation_array.dir │ │ │ ├── C.includecache │ │ │ ├── DependInfo.cmake │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── depend.internal │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ └── progress.make │ │ ├── one_array_transmit_paramter.dir │ │ │ ├── DependInfo.cmake │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ └── progress.make │ │ ├── pointer_funcation.dir │ │ │ ├── C.includecache │ │ │ ├── DependInfo.cmake │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── depend.internal │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ └── progress.make │ │ ├── progress.marks │ │ └── sizeof_value.dir │ │ │ ├── C.includecache │ │ │ ├── DependInfo.cmake │ │ │ ├── build.make │ │ │ ├── cmake_clean.cmake │ │ │ ├── depend.internal │ │ │ ├── depend.make │ │ │ ├── flags.make │ │ │ ├── link.txt │ │ │ ├── progress.make │ │ │ └── sizeof_value.c.o │ ├── Makefile │ ├── array_transmit_paramter │ ├── cmake_install.cmake │ ├── code.cbp │ └── sizeof_value ├── double_array_tran_pram.c ├── funcation_array.c ├── main.c ├── memory_visit.c ├── one_array_transmit_paramter.c ├── pointer_funcation.c └── sizeof_value.c ├── dataStruct ├── n个元素的出栈顺序.md ├── photo │ ├── binary_tree.png │ └── dgree.png ├── 图的表示和存储.md ├── 数据结构中堆、栈和队列的理区别.md └── 树的联系与区别.md ├── design_model └── 常用的设计模式.md ├── neuralNet └── 神经网络中引入非线性能力的是.md ├── process ├── Linux进程调度的算法.md └── schedule()的触发和执行时机.md └── shell ├── Linux磁盘整体情况.md ├── Linux读取某个文件的某一行或者某几行.md ├── Makefile.md ├── linux内核版本号.md ├── linux文件操作的五个命令.md ├── photo └── file_operation.png └── 如何理解三个标准文件.md /7.30诺瓦科技/linux内核裁剪的方式.md: -------------------------------------------------------------------------------- 1 | 1. linux内核裁剪的方式? 2 | - 增加需要的,去除不需要的 3 | - make menuconfig / xconfig`是裁剪的其中一种手段 4 | 5 | -------------------------------------------------------------------------------- /7.30诺瓦科技/tcp物理层的具体内容.md: -------------------------------------------------------------------------------- 1 | ### TCP/IP物理层的具体内容是啥 2 | 3 | 1. 物理层的主要功能是:利用传输介质为数据链路层提供物理连接,实现**比特流的透明传输**。 4 | 2. 物理层的作用: 5 | + 是实现相邻计算机节点之间比特流的透明传送,尽可能**屏蔽**掉具体传输介质和物理设备的差异。 6 | + 使其上面的数据链路层不必考虑网络的具体传输介质是什么。 7 | + “透明传送比特流”表示经实际电路传送后的比特流没有发生变化,对传送的比特流来说,这个电路好像是看不见的。 8 | 9 | -------------------------------------------------------------------------------- /7.30诺瓦科技/关于时钟发生器的英文翻译.md: -------------------------------------------------------------------------------- 1 | ### 英文翻译: 关于时钟发生器的英文翻译? 2 | 3 | ``` 4 | A clock generator is a type of circuit that produces acontinuous, sychronized electrical signal for timing purposes in a widevarity of devices work together in an efficient manner, clock generators are often a necessary component in many devices in order toensuure that all other components work harmoniously. 5 | 6 | 时钟发生器是一种电路,其产生连续的,同步的电信号用于定时目的,在广泛的设备中以有效的方式协同工作,时钟发生器通常是许多设备中的必要组件,以便确保所有其他组件协调地工作。 7 | ``` 8 | 9 | -------------------------------------------------------------------------------- /7.30诺瓦科技/示波器采集数据的要求.md: -------------------------------------------------------------------------------- 1 | ## 硬件调试器 2 | 3 | ### 万用表 4 | 5 | 1. 万用表使用 6 | + 电平信号测量 7 | + 是否导通: 放在二极管 8 | 9 | ### 示波器 10 | 11 | 1. 示波器采集数据的要求? 12 | + 采样速率高于信号频率的2倍, 才不会失真; 13 | 14 | 2. 示波器调频和调宽度? 15 | + 基于不同的基准电压 16 | 3. 三种模式 17 | + 自动模式 18 | + 常规模式 19 | + 单词模式 20 | 21 | ### 逻辑分析仪 22 | 23 | 1. 逻辑分析仪使用方式? 24 | + 采用始终从测试设备上采集数字信号并进行现实的仪器, 用于时序的判断 25 | 2. 特性? 26 | + 只显示两个电压, 逻辑0和逻辑1; 27 | + 相对于设置的参考电压; -------------------------------------------------------------------------------- /8.1Dji大疆/C关键词的描述.md: -------------------------------------------------------------------------------- 1 | ## C关键词的描述 2 | 3 | | 关键字 | 特征 | 应用 | 4 | | -------- | -------------------------------------------------- | ---------------------------------------------------- | 5 | | const | 编译时分配,**只读** | 修饰常量,指针 | 6 | | static | 编译时分配空间,**静态**全局变量 | 修饰变量,函数 | 7 | | volatile | 编译时不优化:从内存中取值,不是寄存器中 | 多线程访问一个全局变量时 | 8 | | sizeof | 编译时:计算 | 计算**类型**占用的空间大小 | 9 | | strlen | 运行时:计算 | 计算字符串的**长度**,不是类型占内存的大小 | 10 | | assert | 运行时:断言--是**宏**,不是函数; | 如果条件错误,则终止程序执行; | 11 | | extern | 编译时:扩展声明 | 声明全局变量/函数; | 12 | | Union | **共享**内存空间,任意时刻只有一个数据成员可以有值 | 计算内存字节的空间时,以最大值为准 | 13 | | typedef | 运行时:类型重定义..可以重定义类型 | 定义函数指针 | 14 | | #define | **预编译**时:宏定义 | 定义频繁使用的短小函数,在预编译的时候直接**替换**; | 15 | 16 | 1. const 与 #define相比? 17 | + const 常量有**数据类型**,而宏常量没有数据类型 18 | + **编译器**可以对前者进行类型安全**检查**。而对后者只进行**字符替换**,没有类型安全检查,并且在字符替换可能会产生意料不到的错误 19 | + 集成化的**调试**工具可以对const 常量进行调试,但是不能对宏常量进行调试。 20 | 2. inline和#define对比 21 | + inline代码放入**预编译器**符号表中,高效;它是个真正的**函数**,调用时有严格的**参数检测**。 22 | 23 | ### const : 只读 24 | 25 | + 被const修饰的就只能读:**常**整形数,**常**指针; 26 | + const修饰的变量为只读变量,定义一个const类型的变量时必须完成**初始化** 27 | 28 | ``` 29 | Const int a; // a是一个常量整形,值不能修改 30 | int const a; // 同上 31 | const int *a; // a是一个**指向常整型数的指针**;整型数是不可修改的,但指针可以 32 | int const *a; //同上 33 | int * const a; // a **指向整型数的常指针**;指针指向的整型数是可以修改的,但指针是不可修改 34 | const int * const a; 35 | int const * const a //a是一个**指向常整型数的常指针**;指针指向的整型数是不可修改的,同时指针也是不可修改的 36 | ``` 37 | 38 | 1. const的作用? 39 | + 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。 40 | + 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。 41 | + 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。 42 | 43 | ### static 44 | 45 | 1. 在函数体,一个被声明为静态的变量在这一函数被调用过程中维持其值不变。 46 | 2. 在模块内(但在函数体外),一个被声明为静态的变量可以被模块内所用函数访问,但不能被模块外其它函数访问。它是一个本地的全局变量。 47 | 3. 在模块内,一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是,这个函数被限制在声明它的模块的本地范围内使用。 48 | 49 | 50 | ### volatile 51 | 52 | ``` 53 | volatile int i = 10; 54 | ``` 55 | 56 | - volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素(操作系统、硬件、其它线程等)更改。所以使用**volatile 告诉编译器不应对这样的对象进行优化** 57 | - volatile 关键字声明的变量,每次访问时都必须从**内存中取出值**(没有被 volatile 修饰的变量,可能由于编译器的优化,从 CPU 寄存器中取值) 58 | - const 可以是 volatile (volatile实在编译阶段,const是在使用的阶段) 59 | - 指针可以是 volatile() 60 | 61 | ### sizeof() 和 strlen()区别 62 | 63 | - sizeof 对数组,得到整个数组所占空间大小。 64 | - sizeof 对指针,得到指针本身所占空间大小。4bytes 65 | 66 | + sizeof()是运算符,由于在编译时计算,因此sizeof不能用来返回动态分配的内存空间的大小。 67 | + sizeof返回值:跟这些里面所存储的内容没有关系 68 | + strlen是函数,它的结果要在运行的时候才能计算出来,用来计算字符串的长度,不是类型占内存的大小。 69 | 70 | ### assert() 71 | 72 | + 断言,是宏,而非函数。assert 宏的原型定义在 ``(C)、``(C++)中,其作用是如果它的条件返回错误,则终止程序执行。可以通过定义 `NDEBUG` 来关闭 assert,但是需要在源代码的开头,`include ` 之前。 73 | 74 | ### extern "C" 75 | 76 | - 被 extern 限定的函数或变量是 extern 类型的 77 | - 被 `extern "C"` 修饰的变量和函数是按照 C 语言方式编译和链接的 78 | 79 | + `extern "C"` 的作用是让 C++ 编译器将 `extern "C"` 声明的代码当作 C 语言代码处理,可以避免 C++ 因符号修饰导致代码不能和C语言库中的符号进行链接的问题。 80 | 81 | ### union 联合 82 | 83 | 联合(union)是一种节省空间的特殊的类,一个 union 可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。当某个成员被赋值后其他成员变为未定义状态。联合有如下特点: 84 | 85 | - 默认访问控制符为 public 86 | - 可以含有构造函数、析构函数 87 | - 不能含有引用类型的成员 88 | - 不能继承自其他类,不能作为基类 89 | - 不能含有虚函数 90 | - 匿名 union 在定义所在作用域可直接访问 union 成员 91 | - 匿名 union 不能包含 protected 成员或 private 成员 92 | - 全局匿名联合必须是静态(static)的 93 | 94 | ### typedef and define 95 | 96 | 1. typedef 的优势 97 | 98 | ``` 99 | #define dPS struct s * // 宏定义 dPS 表示 struct s* 100 | typedef struct s * tPS; // typedef 表示,将struct *s 重命名为tPS 101 | ``` 102 | 103 | + 在定义指针变量的时候,哪种方式更好?使用typedef更好; 104 | 105 | ``` 106 | dPS p1,p2; --> 扩展为:struct s *p1, p2; // 此时只定义了一个指针类型的p1, 另外一个不是; 107 | tPS p3,p4; --> 两个都是指针 108 | ``` 109 | 110 | -------------------------------------------------------------------------------- /8.1Dji大疆/C函数使用注意.md: -------------------------------------------------------------------------------- 1 | ## C 函数strcpy,memcpy,memset 的区别 2 | 3 | ### 函数的区别 4 | 5 | 1. strcpy 6 | 7 | + strcpy的作用是**拷贝字符串**,当它遇到'\0'时结束拷贝。 8 | 9 | + **注意**:存在拷贝越界的问题; 10 | 11 | + ``` 12 | extern char *strcpy(char *dest,char *src); //就是把src的字符串复制到dest中 13 | ``` 14 | 15 | 2. **memcpy** 16 | 17 | + memcpy用来做**内存拷贝**,可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度。 18 | 19 | + **注意**:内存重叠的问题:目的地址的指针位置大于src,小于src+n; 20 | 21 | + ``` 22 | void *memcpy(void *dest, const void *src, size_t n) // 其中dest为返回的值 23 | ``` 24 | 25 | 3. sprintf 26 | 27 | - 操作源可以是多种数据类型,最终目的对象是**字符串** 28 | 29 | - 作用:将其他数据类型格式转化为字符串; 30 | 31 | - ``` 32 | sprintf(char *str, "%d", size_t num); //直接将数字n转化为字符串 33 | ``` 34 | 35 | 36 | 37 | 4. memset 38 | 39 | + memset的作用是对一段内存空间全部**设置为某个字符**,常用在内存空间的初始化。 40 | + 其原型为 void *memset(void *s,int c,size_t n); 就是把已开辟内存空间s的首n个字节设置为c。 41 | 42 | 43 | 44 | ### C库函数中,size_t类型定义的变量值 45 | 46 | 1. C中使用memcpy()系列函数时要足够小心? 47 | 48 | ``` 49 | void * memcpy ( void * destination, const void * source, size_t num ); 50 | ``` 51 | 52 | - 注意最后一个参数是 **字节**数 == **sizeof(size_t)** 53 | 54 | ``` 55 | int main() { 56 | int a[10] = { 0,1,2,3,4,5,6,7,8,9 }; 57 | memcpy(a + 3, a, 5); // 想实现5个int类型的数复制 ; 修改 为 memcpy(a + 3, a, 5*sizeof(int)); 58 | for (int i = 0; i<10; i++){ 59 | printf("%d ", a[i]); 60 | } 61 | return 0; 62 | } 63 | ``` 64 | 65 | - 解答:0 1 2 0 1 5 6 7 8 9 66 | 67 | ### memcpy内存重叠的问题 68 | 69 | 1. dst的起始位置,和src指向的内存空间位置存在一定的关系 70 | 71 | ![memcpy.png](https://github.com/quronghui/Embedded-written-reference/blob/master/C/photo/memcpy.png) 72 | 73 | 2. 内存复制的时候:内存空间的增长情况 74 | 75 | + 属于栈空间的增长,从高地址到低地址; 76 | 77 | 3. 内存重叠的现象 78 | 79 | ``` 80 | src < dst < src + num; // 当其地址的情况是这样的时候,就出现地址重叠 81 | ``` 82 | 83 | 4. 如何解决地址重叠的问题 84 | 85 | ``` 86 | const char *q = (const char *)src ; //将其转化为char,一个字节一个字节的进行复制 87 | char *p = (char *)dst; 88 | p = p + num - 1 // 将两个指针都移动到低地址 89 | q = q + num - 1; 90 | // 实现从低地址 -- > 到高地址的移动复制 91 | ``` 92 | 93 | + [实现memcpy函数和优化](https://github.com/quronghui/DataStructAndAlogrithmCode/blob/master/CompanyWrite/1_Dji/strncmp.c) 94 | 95 | ### strcpy 96 | 97 | 1. 考虑内存溢出的情况; 98 | + 注意给目的地址加上'\0'; 99 | 2. 实现[strcpy and strcnpy](https://github.com/quronghui/DataStructAndAlogrithmCode/blob/master/c_library/my_strcpy.cpp) -------------------------------------------------------------------------------- /8.1Dji大疆/C有符号的变量和无符号的变量相加.md: -------------------------------------------------------------------------------- 1 | ## 有符号变数与无符号数相加 2 | 3 | 1. 遵循的原则: 4 | + 将有符号数转化为无符号数;想当于取两个数的补码 5 | 2. [代码实例](https://github.com/quronghui/DataStructAndAlogrithmCode/blob/master/CompanyWrite/1_Dji/charConvertint.c) 6 | 7 | ### 理解原码, 反码, 补码 8 | 9 | | 类型 | 特征 | 10 | | ---------- | -------------------------- | 11 | | 机器数 | 带符号的二进制数 | 12 | | 真值 | 去掉符号位的值 | 13 | | 原码 | 符号位+真值 | 14 | | 反码和补码 | 正数的反码和补码是其本身; | 15 | 16 | 1. 机器数和真值概念: 17 | 18 | + 机器数: 19 | 20 | + 一种**带符号**的**二进制**表示形式 21 | + 为了方便: 我们用一个byte来计算 22 | 23 | ``` 24 | +3 : 0000 0011; 25 | -3 : 1000 0011; 26 | ``` 27 | 28 | + 真值: 29 | 30 | + **去掉符号位**后表示的值, 就是真值; 31 | 32 | + ``` 33 | 0000 0001 真值 = +000 0001 = +1; 34 | 1000 0001 真值 = -000 0001 = -1; 35 | ``` 36 | 37 | 2. 理解原码的概念 38 | 39 | + 原码: 是**符号位**加上**真值的绝对值** 40 | 41 | ``` 42 | [+1]原 = 0000 0001 43 | [-1]原 = 1000 0001 44 | ``` 45 | 46 | + 带符号的8位二进制数的取值范围就是 47 | 48 | ``` 49 | [1111 1111 , 0111 1111] == [-128 , 127] 50 | ``` 51 | 52 | 3. 理解反码的概念 53 | 54 | + 负数反码: 在原码的基础上**符号位不变**, 其余位取反(0/1); 55 | 56 | + 正数的反码: 是其本身; 57 | 58 | ``` 59 | [+1] = [00000001]原 = [00000001]反 60 | [-1] = [10000001]原 = [11111110]反 61 | ``` 62 | 63 | 4. 理解补码的概念 64 | 65 | + 负数的补码: 在反码的基础上, 最后位进行加1 66 | 67 | + 正数的补码: 是其本身 68 | 69 | ``` 70 | [+1] = [00000001]原 = [00000001]反 = [00000001]补 71 | [-1] = [10000001]原 = [11111110]反 = [11111111]补 72 | ``` 73 | 74 | 5. 关于负数 75 | 76 | + 其反码和补码都不能直接看出其数值; 77 | + 通常转化为原码才能看出; 78 | 79 | ### 为何要使用原码, 反码, 补码 80 | 81 | 1. 为了让机器的计算只有加法没有减法? 82 | 83 | 1. 如果使用原码相加 : **结果不正确** 84 | 85 | ``` 86 | 1 - 1 = 1 + (-1) = [00000001]原 + [10000001]原 = [10000010]原 = -2 87 | ``` 88 | 89 | 2. 如果使用反码相加 90 | 91 | ``` 92 | 1 - 1 = 1 + (-1) = [0000 0001]反 + [1111 1110]反 = [1111 1111]反 = [1000 0000]原 = -0 93 | ``` 94 | 95 | + **"0"的特殊**: 存在+0 和 -0 96 | 97 | ``` 98 | [0000 0000]原和[1000 0000]原 --> 都表示0 99 | ``` 100 | 101 | 3. 如果使用补码相加 102 | 103 | ``` 104 | 1-1 = 1 + (-1) = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原 105 | ``` 106 | 107 | 2. **问题一: 如果使用补码进行计算有什么问题呢?** 108 | 109 | ``` 110 | (-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补 111 | ``` 112 | 113 | + **0只有一种表示情况** [0000 0000]; 114 | 115 | + **多表示一个最低数** : [1000 0000] = -128 116 | 117 | + 有符号的char型表示的数值 118 | 119 | ``` 120 | [-128, 127] = [ -2^7 -- (2^7 -1) ] 121 | ``` 122 | 123 | ### [减法变成加法的数学原理解析?](https://www.cnblogs.com/zhangziqiu/archive/2011/03/30/ComputerCode.html) 124 | 125 | 1. 数学问题的定义? 126 | 127 | + 钟表想象成是一个1位的12进制数. 如果当前时间是6点, 我希望将时间设置成4点, 需要怎么做呢? 128 | 129 | ``` 130 | 1. 往回拨2个小时: 6 - 2 = 4 131 | 2. 往前拨10个小时: (6 + 10) mod 12 = 4 132 | 3. 往前拨10+12=22个小时: (6+22) mod 12 =4 133 | ``` 134 | 135 | 2. **问题二: 如何通过一个正数, 代替一个负数?** 136 | 137 | 1. 同余的概念: 两个整数a,b,若它们除以整数m所得的**余数相等** 138 | 139 | ``` 140 | 记做: a = b( mod m) 141 | ``` 142 | 143 | 2. 负数如何取模? 144 | 145 | + **取下界 b / m** : L(-1.5) = (-2); L( 1.5 ) = 1 146 | 147 | ``` 148 | b mod m = b - m * L( b / m ) 149 | ``` 150 | 151 | + 例子 152 | 153 | ``` 154 | -3 mod 2 = -3 - 2 * L(-3/2) = -3 - 2 * L(-1.5) = -3 - 2*(-2) = 1 155 | ``` 156 | 157 | 3. 如何通过一个正数, 代替一个负数? 158 | 159 | + **找到这个负数的同余数** 160 | 161 | ``` 162 | 7 ≡ 7 (mod 12) 163 | (-2) ≡ 10 (mod 12) ; -2 mod 12 = 10 ; 10 mod 12 = 10 164 | 所以此时就能替换: 7 + ( -2 ) ≡ 7 + 10 (mod 12) 165 | ``` 166 | 167 | 3. 将同余的概念应用到二进制: 168 | 169 | + **负数的二进制同余: 就是其补码;** -------------------------------------------------------------------------------- /8.1Dji大疆/C语言编译执行的四个阶段.md: -------------------------------------------------------------------------------- 1 | ### C函数使用注意 2 | 3 | 1. C语言**编译链接**的四个阶段? 4 | 5 | ![Cobject_link.png](/8.1Dji大疆/photo/Cobject_link.png) 6 | 7 | 1. 预编译: 8 | - "#" 相关的语句: 进行展开; 9 | - 例如: #define : 宏定义展开 10 | 2. 编译: 翻译 11 | - 分析代码的语法和语义, 将**变量和关键字** **翻译**成中间代码或者汇编代码; 12 | 3. 汇编: 翻译 13 | - 将汇编语言**翻译**为机器可识别的二进制代码 14 | - .o 是二进制文件 15 | 4. 链接: 16 | - 将目标文件所需的**库, 文件**进行链接 17 | 18 | 2. [程序编译成可执行文件的代码](https://luckywater.top/2019/03/18/ComplationAndC/) 19 | 20 | + ``` 21 | $ gcc -S main.c -o main.s //生成汇编代码 22 | $ gcc -c main.s -o main.o //生成目标文件 23 | $ gcc main.o -o main //生成可执行文件 24 | ``` 25 | 26 | 3. volatile应该是在**编译阶段**,extern在**链接阶段**。 27 | 28 | + volatile:告诉编译器,修饰的变量不能优化,每次读取需要从内存中读取; 29 | 30 | ### 链接库 31 | 32 | | 区别 | 静态库(.a、.lib) | 动态库(.so、.dll) | 33 | | -------- | -------------------------------------------- | ---------------------------- | 34 | | 链接阶段 | 编译时期:与目标文件.o一起打包生成可执行文件 | 运行时被载入 | 35 | | 优点 | 运行与函数库无关,移植方便 | 不同的应用程序可以**共享库** | 36 | | 缺点 | 浪费资源空间 | 运行时需要提供相关库 | 37 | | | 小的改动,全量更新 | | 38 | 39 | 1. **库的本质** 40 | + 库是一种可执行代码的二进制形式,可以被操作系统载入内存执行 41 | + windows上对应的是.lib .dll; 42 | + linux上对应的是.a .so 43 | 2. 动态库共享? 44 | + 共享的是数据段(全局的变量) -------------------------------------------------------------------------------- /8.1Dji大疆/Linux多任务进程线程之间的关系.md: -------------------------------------------------------------------------------- 1 | ## Linux的多任务, 多进程, 多线程 2 | 3 | ### [进程和程序的区别](https://blog.csdn.net/weixin_36194037/article/details/82390068) 4 | 5 | | 区别 | 程序 | 进程 | 6 | | --------- | ------------ | -------------------- | 7 | | 组成 | 代码+数据; | 代码+数据+堆栈+pcb; | 8 | | 存储方式 | 永久存储 | 占时存储与内存 | 9 | | 静态/动态 | 静态的概念 | 动态的概念 | 10 | | 并发 | 无并发概念 | 有并发的概念 | 11 | | 关系 | 对应多个进程 | 可以执行多个程序 | 12 | 13 | 1. 什么是程序? 14 | - 是完成特定任务的一系列**指令的集合** 15 | - 是指编译好的**二进制文件**,在磁盘上;不占用系统资源(cpu,内存,设备,锁) 16 | 2. 什么是进程? 17 | - **用户**角度:进程是程序的一次**动态**执行过程; 18 | - **内核角度**:进程是分配cpu,内存等系统资源的**基本单位**; 19 | - 都有自己的**状态**;都有自己的虚拟地址空间; 20 | - 在内存中执行且占用系统资源; 21 | 22 | ### 进行,线程,协程:执行任务的方法 23 | 24 | | 区别 | 进程 | 线程 | 协程 | 25 | | ------------ | -------------------------- | ----------------------------------------- | ------------------------------ | 26 | | 主要区别 | 资源分配的最小单位 | 程序执行的最小单位
CPU的最小调度单位 | 完全是由程序所控制 | 27 | | 组成 | 拥有多个线程 | 共享地址空间, 访问相同的数据 | 多个函数,子程序组成 | 28 | | 可执行 | 程序执行时的一个实例(大) | 线程是进程的一个执行流(小) | **极高的执行效率** | 29 | | 保存状态信息 | PCB | TCB Thread control block | 通过栈进行切换,无需上下文切换 | 30 | | 页表 | 地址空间改变, 切换当前页表 | 共享地址空间, 不用切换页表 | | 31 | | 内存空间 | 独立的内存空间 | **独立栈**空间(局部变量) | | 32 | | 影响 | 进程间不影响 | 一个线程死掉就等于**整个**进程死掉 | | 33 | 34 | ### 进程和线程 35 | 36 | 2. 进程的创建和执行 37 | + 必须分配给它独立的地址空间, 38 | + 建立众多的数据表来维护它的代码段、堆栈段和数据段 39 | 3. 线程的描述 40 | + 线程是进程的一个**执行流**,是CPU调度和分派的基本单位, 41 | + 它是比进程更小的能独立运行的基本单位; 42 | 43 | ![thread_status.png](/8.1Dji大疆/photo/thread_status.png) 44 | 45 | ### 线程 VS 协程 46 | 47 | 1. 协程的特点: 48 | + 比线程更加轻量级的存在,协程不是被操作系统内核所管理,而完全是**由程序所控制**(也就是在用户态执行) 49 | + 类似于程序里面的函数; 50 | + 协程在子程序内部是可中断的,然后转而执行别的子程序,在适当的时候再返回来接着执行 51 | 2. 协程的特点在于是一个线程执行,那和多线程比,协程有何优势? 52 | + **极高的执行效率**: 53 | + 因为**子程序切换不是线程切换,而是由程序自身控制**, 54 | + **没有线程切换的开销**,和多线程比,线程数量越多,协程的性能优势就越明显; 55 | + **不需要多线程的锁机制**: 56 | + 因为只有一个线程,也不存在同时写变量冲突, 57 | + **在协程中控制共享资源不加锁**,只需要**判断状态**就好了,所以执行效率比多线程高很多。 58 | 59 | ### 使用多线程原因 60 | 61 | 1. 多任务并发的优势 62 | + 进程创建 : 花费较多的时间维护其内存空间 63 | + 线程创建: 只需要在执行的时候, 分配栈空间和局部变量空间就行; 64 | 2. 通信实现 65 | + 进程间: 数据的传递只能通过**通信**的方式进行; 66 | + 线程间: 同步和互斥机制就能实现; 67 | 3. 多内核 68 | + 多线程程序作为一种多任务、并发的工作方式 69 | + 多线程技术: 将耗时长的操作(time consuming)单独置于一个新的线程; 70 | + OS **使得线程数不大于CPU数目时,不同的线程运行于不同的CPU上**。 71 | 72 | ### 线程共享的资源有哪些? 73 | 74 | 1. 一个进程中的所有线程:共享该进程的地址空间 75 | 2. **堆:**是大家共有的空间,分全局堆和局部堆。 76 | 3. -------------------------------------------------------------------------------- /8.1Dji大疆/Linux查询进程和线程数量.md: -------------------------------------------------------------------------------- 1 | ## 查询进程和线程的方法 2 | 3 | ### 查询线程方式 4 | 5 | ``` 6 | $ pstree -p pid | wc -l // 通过wc将数量统计 7 | $ cat /proc/pid/status // 通过proc虚拟文件系统 8 | 9 | $ ulimit -s // 查询线程的最大值 10 | ``` 11 | 12 | ### 查询进程数量 13 | 14 | ``` 15 | $ ps -m // 查询进程的数量 16 | $ top -H // 动态显示进程状态; 17 | ``` 18 | 19 | 1. 查询进程的最大值 20 | 21 | ``` 22 | $ ulimit -a // 查询进程的相关限制信息 23 | $ cat /proc/sys/kernel/pid_max; // PID的最大值默认设置位32768(short int 短整型的最大值)。 24 | $ ulimit -u 65535; // ulimit 修改Linux的限制, 将进程扩大为int 25 | ``` 26 | 27 | ### 进程的创建 28 | 29 | 1. 进程的创建: fork() 30 | - fork() 创建成功 31 | - 子进程的pid, 返回给父进程; 32 | - 0 返回个子进程 33 | - fork() 创建失败 34 | - -1 返回给父进程; 子进程没哟返回值 35 | 2. 进程的执行和等待 36 | - exec() and wait() 37 | 38 | ## Linux把名称中含有test内容的进程找出来杀死 39 | 40 | ``` 41 | $ ps | grep test // 先找出含有"test"的进程的pid 42 | $ kill pid // 杀死线程 43 | ``` 44 | 45 | ## 僵尸进程查询 46 | 47 | ``` 48 | $ ps u // 查看进程状态 49 | STAT 为z时 -- 僵尸进程的状态 50 | ``` 51 | 52 | -------------------------------------------------------------------------------- /8.1Dji大疆/OScache多任务调度描述.md: -------------------------------------------------------------------------------- 1 | ## Cache多任务调度 2 | 3 | 1. 为什么会发生页面替换问题? 4 | + Cache 本质是一个物理内存, 为了保证快速性所以空间有限; 淘汰掉一个不常用的页面,以便腾出主存空间来存放 新调入的页面 5 | + **提高TLB命中率** 6 | 2. 页面替换算法 7 | + 随机算法,即RAND算法(Random algorithm) 8 | + FIFO算法(First-In First-Out algorithm) 9 | + 没有反映程序的局部性, 经常要使用的页面可能就在队头; 10 | + LFU算法(Least Frequently Used algorithm) 11 | + 因为到目前为止最少使用的页面,很可能也是将来最少访问的页面。 12 | + 实现: 为每个页面设置一个很长的定时计数器, 替换时找出**计数器最大**使用的页面; 13 | + **LRU算法**(Least Recently Used algorithm) 14 | + 近期最久没有被访问过的页面作为被替换的页面 15 | + 它把LFU算法中要记录数量上的"多"与"少"简化成判断"有"与"无" 16 | + OPT算法(OPTimal replacement algorithm) 17 | + 好的算法应该是选择将来最久不被访问的页面作为被替换的页面; 18 | + 不容易实现 19 | 3. **LRU调度算法** 20 | + 核心思想是“如果数据最近被访问过,那么将来被访问的几率也更高” 21 | + 最常见的实现是使用一个**链表保存缓存数据**,详细算法实现如下 22 | + 新数据插入到链表头部; 23 | + 每当缓存命中(即缓存数据被访问),则将数据移到链表头部; 24 | + 当链表满的时候,将链表尾部的数据丢弃。 25 | 4. [考题:计算一个CPU调度过程中的缺页次数?](https://blog.csdn.net/ENSHADOWER/article/details/89057007) 26 | 27 | -------------------------------------------------------------------------------- /8.1Dji大疆/OScache缓存一致性描述.md: -------------------------------------------------------------------------------- 1 | ## [Cache 缓存一致性的问题](https://www.infoq.cn/article/cache-coherency-primer) 2 | 3 | 1. 缓存一致性出现的原因? 4 | + (1)DMA直接与主存的数据交互,导致CPU中的cache内容与主存内容不一致; 5 | + (2)多组缓存中,直写和回写造成的不一致; 6 | 2. 如何解决缓存一致性问题? 7 | + 多组缓存, 通过共享总线的机制, 使用MESI协议, 实现缓存一致性; 8 | + 写操作: 只有缓存段处于某一个处理器独占E的时, 才允许写; 9 | 10 | ### 缓存 11 | 12 | 1. 缓存的作用? 13 | 14 | + 加快虚拟地址与物理地址的转换; 15 | + 能见的地址空间: 程序运行时OS为其分配的虚拟存储位置; 16 | 17 | 2. 缓存的存储空间? 18 | 19 | + 缓存是分“段”(line)的,一个段对应一块存储空间 20 | + 大小: 32 byte / 64 byte / 128 byte 21 | + 每个CPU缓存 : 有多个缓存; 22 | 23 | 3. 所有级别的缓存遵循基本定律: 24 | 25 | ``` 26 | 在任意时刻,**任意级别**缓存中的缓存段的内容,等同于它对应的内存中的内容。 27 | ``` 28 | 29 | 4. **问题一: ** 允许写操作有几种方式? 30 | 31 | + **直写**: 透过本级缓存,直接把数据写到下一级缓存(或直接到内存)中,如果对应的段被缓存了,我们同时更新缓存中的内容(甚至直接丢弃) 32 | + **回写: ** 33 | + 仅修改本级缓存中的数据,并且把对应的缓存段标记为“脏”段 34 | + 脏段会触发回写: 把里面的内容写到对应的内存或下一级缓存中; 35 | 36 | 5. 回写的优势的定律? 37 | 38 | + 回写模式:它能过滤掉对同一地址的反复写操作 39 | 40 | ``` 41 | 回写定律:当所有的脏段被回写后,**任意级别**缓存中的缓存段的内容,等同于它对应的内存中的内容。 42 | ``` 43 | 44 | ### 一致性问题 45 | 46 | + 针对: 内存中的内容 47 | 48 | 1. 一致性问题的产生? 49 | + 如果某个 **CPU 缓存段中对应的内存内容**被另外一个 CPU 偷偷修改. 50 | + 使多组缓存的**内容**保持一致。 51 | 2. **问题一:** 如何解决缓存之间的一致性问题? 52 | + 总体方法: 如果一个 CPU 缓存了某块内存,那么在其他 CPU 修改这块内存的时候,希望得到通知 53 | + 具体方法: 通过一个**共享总线**连接多个缓存; 54 | 55 | ### **直写共享总线使用的协议** : “窥探(snooping)协议” 56 | 57 | + 具体思想: *所有内存传输* 都发生在一条共享的总线上,而*所有的处理器*都能看到这条总线; 58 | + 缓存本身是独立的,但是内存是共享资源 59 | + 内存访问的仲裁: 60 | + 同一个指令周期中,只有一个缓存可以读写内存; 61 | + 缓存失效 62 | + 某个处理器一写内存,其他处理器马上就知道这块内存在它们自己的缓存中对应的段已经失效。 63 | 64 | + 直写模式下, 写操作一旦发生, 效果就会马上"公布"; 65 | 66 | ### 回写模式: 共享总线使用的协议 MESI 67 | 68 | 1. MESI 协议: 69 | + MESI 是**四种缓存段**状态的首字母缩写 70 | + 失效(Invalid)缓存段 71 | + 要么已经不在缓存中,要么它的内容已经过时(被更新) 72 | + 一旦缓存段被**标记为失效**,那效果就等同于它从来没被加载到缓存中。 73 | + 共享(Shared)缓存段 74 | + 和主内存内容保持一致的**一份拷贝**,在这种状态下的缓存段**只能被读取,不能被写入** 75 | + **多组缓存**可以同时拥有针对同一内存地址的共享缓存段 76 | + 独占(Exclusive)缓存段 77 | + 和主内存内容保持一致的**一份拷贝**; 78 | + **独占**: 同一时间只能有一个处理器持有E 状态的缓存段 79 | + 已修改(Modified)缓存段 80 | + 属于脏段: 缓存内存被修改; 81 | + 已修改状态: 那么它在其他处理器缓存中的拷贝马上会变成**失效状态** 82 | 2. **MESI 协议如何实现一致性呢?** 83 | + 处理器是**独占**这个缓存段: 84 | + 只有当缓存段处于 E 或 M 状态时,处理器才能去**写**它; 85 | + 写操作: 申请独占权: 86 | + 在总线上发送"我要独占权"的请求; 87 | + 这会通知其他处理器,把它们拥有的同一缓存段的拷贝失效 88 | + 读操作: 缓存段必须先回到“共享”状态 89 | + 通过回写 90 | 3. MESI定律 91 | + 在所有的脏缓存段(M 状态)被回写后,任意缓存级别的所有缓存段中的内容,和它们对应的内存中的内容一致。 92 | + 在任意时刻,当某个位置的内存被一个处理器加载入独占缓存段时(E 状态),那它就不会再出现在其他任何处理器的缓存中。 -------------------------------------------------------------------------------- /8.1Dji大疆/OS中断处理过程的描述.md: -------------------------------------------------------------------------------- 1 | ## 简述处理器中断处理的过程 2 | 3 | ![INTR.png](/8.1Dji大疆/photo/INTR.png) 4 | 5 | ### 中断的定义 6 | 7 | 1. CPU在正常执行程序的时候, 由于外部/内部事件的**触发**, 或者程序预先设定的**系统调用**; 8 | 2. 引起CPU暂时**中止**当前正在执行的程序, **保存**被中断程序相关信息到栈中, **转而去处理**外部/内部事件, 或者程序预先设定的中断服务子程序; 9 | 3. 待执行完ISR后, CPU**获取**保存在栈中被中断的程序信息, **继续执行**被中断的程序, 这一过程就叫做中断; 10 | 11 | ### 中断的几个概念 12 | 13 | 1. 中断向量: 中断服务程序ISR的**入口地址**; 14 | 2. 中断向量表: 把系统中所有的**中断类型码**及其对应的**中断向量**按一定的**规律存放**在一个区域内,这个存储区域就叫做中断向量表; 15 | 3. 中断源: 软中断/内中断(软件中断)、外中断/硬件中断、异常等。 16 | 17 | ### 中断处理过程 18 | 19 | + 中断请求→中断响应→保护现场(入栈)→中断服务→恢复现场(出栈)→中断返回 20 | + cpu接受终端->保存中断上下文跳转到中断处理历程->执行中断上半部->执行中断下半部->恢复中断上下文。 21 | 22 | 1. 中断请求 23 | + 当某一中断源需要CPU为其进行中断服务时,就输出中断请求信号,使中断控制系统的中断请求触发器置位,向CPU请求中断。 24 | + 系统要求中断请求信号一直保持到CPU对其进行中断响应为止; 25 | 2. 中断响应 26 | + 内部中断源: CPU必须响应,而且**自动取得**中断服务子程序的入口地址,执行中断服务子程序。 27 | + 外部中断源: CPU在执行当前指令的最后一个时钟周期去**查询INTR引脚**; 28 | + 若查询到中断请求信号有效,同时在系统开中断(即IF=1)的情况下 29 | + CPU向发出中断请求的外设回送一个**低电平**有效的**中断应答信号**,作为对中断请求INTR的应答,系统自动进入中断响应周期; 30 | 3. 保护现场 31 | + 主程序和中断服务子程序都要使用CPU内部寄存器等资源,为使中断处理程序不破坏主程序中寄存器的内容,应**先将断点处各寄存器的内容压入堆栈保护起来** 32 | + **当前IP**: 保存将要执行的下一条地址 33 | + **CS值**: 代码段地址,再进入的中断处理。 34 | + 现场保护是由**用户**使用**PUSH**指令来实现的; 35 | 4. 中断服务ISR 36 | + **ISR的几个特点** 37 | + ISR 与中断号是一一对应;不同的中断请求,有各自不同的中断服务内容; 38 | + ISR:事先编写相应的中断服务子程序存入内存,等待中断请求响应后调用执行; 39 | 5. 恢复现场 40 | + 当中断处理完毕后,用户通过**POP指令**将保存在堆栈中的各个寄存器的内容弹出,即恢复主程序断点处寄存器的原值。 41 | 6. 中断返回 42 | + 在中断服务子程序的最后要安排一条**中断返回指令IRET**(interrupt return), 43 | + 执行该指令,系统自动将堆栈内保存的 IP和CS值**弹出**,从而恢复主程序断点处的地址值, 44 | + 同时还自动恢复**标志寄存器FR或EFR**的内容,使CPU转到被中断的程序中**继续执行**。 45 | 46 | 47 | ### 中断响应中的寄存器 48 | 49 | + IP两个寄存器, 指示了 CPU 当前将要读取的指令的地址 50 | + 其中CS为**代码段**寄存器, 51 | + 而IP为**指令指针**寄存器。 52 | + 可以简单地认为,CS段地址,IP是偏移地址。 53 | + RET:也可以叫做**近返回**,即段内返回。 54 | + 处理器从堆栈中弹出IP或者EIP,然后根据当前的CS:IP跳转到新的执行地址。 55 | + 如果之前压栈的还有其余的参数,则这些参数也会被弹出; 56 | + RETF:也叫**远返回**,从一个段返回到另一个段。 57 | + 先弹出堆栈中的IP/EIP,然后弹出CS,有之前压栈的参数也会弹出。(近跳转与远跳转的区别就在于CS是否压栈); 58 | + IRET:用于从中断返回,会弹出IP/EIP,然后CS,以及一些标志。然后从CS:IP执行。 59 | 60 | 61 | ### 中断服务程序需要满足如下要求: 62 | 63 | - (1)不能返回值; 64 | - (2)不能向ISR传递参数; 65 | - (3) ISR应该尽可能的短小精悍; --- 不进行浮点类型的计算 66 | - (4) printf(char * lpFormatString,…)函数会带来重入和性能问题,不能在ISR中采用。 67 | 68 | ``` 69 | // 新的关键字__interrupt, 让标准C支持中断; 70 | // 定义了一个ISR中断服务程序,查找其中的错误; 71 | __interrupt double compute_area (double radius) (1)不能进行传参 72 | { 73 | double area = PI * radius * radius; (2) 在许多的处理器/编译器中,浮点一般都是不可重入的。 74 | printf(” Area = %f”, area); (3)printf()经常有重入和性能上的问题 75 | return area; (4) 中断不允许返回值的 76 | } 77 | ``` -------------------------------------------------------------------------------- /8.1Dji大疆/OS处理器读取内存的过程 (copy).md: -------------------------------------------------------------------------------- 1 | ### [简述处理器在读内存的过程中,CPU核、cache、MMU如何协同工作?画出CPU核、cache、MMU、内存之间的关系示意图加以说明(可以以你熟悉的处理器为例)](https://blog.csdn.net/qq_38410730/article/details/80905551) 2 | 3 | -------------------------------------------------------------------------------- /8.1Dji大疆/OS处理器读取内存的过程.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/8.1Dji大疆/OS处理器读取内存的过程.md -------------------------------------------------------------------------------- /8.1Dji大疆/OS如何实现进程间的切换.md: -------------------------------------------------------------------------------- 1 | ## OS 如何实现进程的切换 2 | 3 | ### 进程切换的三部分 4 | 5 | ​ ![process_status.png](/OS/photo/process_status.png) 6 | 7 | ### OS如何实现进程间的切换 8 | 9 | - a) 首先: OS 获取CPU的控制权 10 | - 协作方式: 当进程在进行系统调用是, 将CPU的控制权转交给OS 11 | - 非协作方式: 设置**定时器**中断,OS在控制中得到安全感 12 | - b) 保存和恢复上下文切换 13 | - OS 为正在执行的进程**保存**一些寄存器的值; 14 | - 并为即将执行的进程**恢复**一些寄存器的值; 15 | - c) 完成进程三部分内容的切换 16 | - 用户级上下文 17 | - 正文、数据、用户堆栈以及共享存储区; 18 | - 寄存器上下文 19 | - 通用寄存器、程序寄存器(IP)、处理器状态寄存器(EFLAGS)、栈指针(ESP) 20 | - 系统级上下文: 21 | - 进程控制块task_struct、 22 | - 内存管理信息(mm_struct、vm_area_struct、pgd、pte) 23 | - 内核栈 24 | -------------------------------------------------------------------------------- /8.1Dji大疆/OS实时和非实时性.md: -------------------------------------------------------------------------------- 1 | ### 简述实时操作系统和非实时操作系统特点和区别。 2 | 3 | 1. **实时性**最主要的含义是:任务的最迟完成时间是可确认预知的。 4 | 5 | 2. **实时操作系统**是保证在**一定时间限制内完成**特定功能的操作系统。 6 | 7 | 3. 实时操作系统有**硬实时和软实时**之分: 8 | 9 | + 硬实时: 要求在规定的**时间内必须完成**操作,这是在操作系统设计时保证的; 10 | + 软实时: 则只要按照**任务的优先级**,**尽可能快**地完成操作即可。 11 | 12 | ![emebeded_OS.png](/8.1Dji大疆/photo/emebeded_OS.png) 13 | 14 | 15 | ### 实时操作系统的分类 16 | 17 | + Linux是现在用得最多的软实时嵌入式操作系统 18 | + uCOS-II是一用得较多的硬实时嵌入式操作系统, -------------------------------------------------------------------------------- /8.1Dji大疆/OS嵌入式系统指定位反转.md: -------------------------------------------------------------------------------- 1 | ## 嵌入式OS位运算 2 | 3 | 1. 写两段代码,第一个设置a的bit 3,第二个清除a 的bit 3;保持其让的位不变 4 | 5 | ``` 6 | #define BIT3 (0x1<<3) 7 | static int a; 8 | void set_bit3(void) 9 | { 10 | a |= BIT3; 11 | } 12 | void clear_bit3(void) 13 | { 14 | a &= ~BIT3; 15 | } 16 | ``` 17 | 18 | 19 | 20 | ### OS系统中的位运算 21 | 22 | 1. OS多任务嵌入式系统中,有一个CPU可直接寻址的32位寄存器REGn,地址为0x1F000010,编写一个安全的函数,将寄存器REGn的指定位反转(要求保持其他bit的值不变) 23 | 24 | ``` 25 | void bit_reverse(uint32_t nbit) 26 | { 27 | *((volatile unsigned int *)0x1F000010) ^= (0x01 << nbit); // (volatile unsigned int *)0x1F000010 相当于强制转换; 28 | } 29 | ``` 30 | 31 | 2. OS系统中的位运算 32 | 33 | + 特定位清零用 & 34 | + 特定位置1用 | 35 | + 特定位取反用 ^ 36 | 37 | ## 位运算 38 | 39 | 1. 按位与运算符(&) 40 | 41 | - 只有两个数的二进制**同时为1,结果才为1**,否则为0。(负数按补码形式参加按位与运算) 42 | 43 | - ``` 44 | 0 & 0= 0 ,0 & 1= 0,1 & 0= 0, 1 & 1= 1 45 | ``` 46 | 47 | 2. 按位或运算符( | ) 48 | 49 | - 参加运算的两个数,只要其中一个为1,结果就为1 50 | 51 | - ``` 52 | 0 | 0= 0 , 1 | 0= 1 , 0 | 1= 1 , 1 | 1= 1 53 | ``` 54 | 55 | 3. 异或运算符( ^ ) 56 | 57 | - 参加运算的两个数,如果两个相应位为“异”(值不同),则该位结果为1,否则为0 58 | 59 | - ``` 60 | 0 ^ 0=0 , 0 ^ 1= 1 , 1 ^ 0= 1 , 1 ^ 1= 0 61 | ``` 62 | 63 | ### 异或运算符的特殊作用: 64 | 65 | 1. 与1异或:特点位反转 66 | 67 | ``` 68 | X=10101110,使X低4位翻转,用X ^0000 1111 = 1010 0001即可得到 69 | 0 ^1 = 1; 1^1 = 0; 70 | ``` 71 | 72 | 2. 与0异或:保留原值 73 | 74 | ``` 75 | X ^ 00000000 = 1010 1110。 76 | 0 ^ 0 = 0; 1 ^ 0 = 1; 77 | ``` 78 | 79 | 3. 异或运算的性质 80 | 81 | - 异或其实就是**不进位加法** 82 | - 如:1+1=0,0+0=0,1+0=1 83 | - 自反性: 84 | - a^b^b=a^0=a; 85 | 86 | ### 左移运算符(<<) 和 右移运算符(>>) 87 | 88 | 1. 左移运算符 89 | + 将一个运算对象的各二进制位全部左移若干位 90 | + 左边的二进制位丢弃,右边补0 91 | + 则每左移一位,相当于该数乘以2 92 | 2. 右移运算符 93 | + 各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃 94 | + 每右移一位,相当于该数除以2 95 | 3. 正数和负数 96 | + 正数:位不足时,左边补0; 97 | + 负数:位不足时,左边补1; 98 | 99 | ### [位运算的题目](https://blog.csdn.net/sinat_35121480/article/details/53510793) -------------------------------------------------------------------------------- /8.1Dji大疆/OS简述一个执行程序在运行时的内存布局.md: -------------------------------------------------------------------------------- 1 | ## OS简述一个执行程序在运行时的内存布局 2 | 3 | 1. C程序中内存空间的组成? 4 | 5 | + 由五个部分组成代码段(.text)、数据段(.data)、BSS段(.bss),堆和栈 6 | 7 | + 编译的时候由**编译器分配**: 代码段(.text)、数据段(.data)、BSS段(.bss) 8 | 9 | + 程序运行的时候由**系统分配**: 堆和栈 10 | 11 | | 分配 | 空间分布 | 功能 | 空间大小 | | 12 | | ---------- | -------- | ------------------------------------------------------------ | ----------- | ------ | 13 | | 编译时分配 | BSS段 | 存放**未初始化**或者初始为0的全局变量和静态变量
只在**运行**时占用内存; | | 可读写 | 14 | | | data | 存放**已初始化非零**的全局变量和static,**常量**;
既占**运行**时的内存空间,也占程序文件的**储存**空间 | 空间很大4GB | 只读 | 15 | | | text | 存放程序**执行代码**的一块内存区域;
text段是可以执行的,而且被不同的**进程共享**。 | | 只读 | 16 | | 运行是分配 | 堆heap | 存放 : 进程运行中被**动态分配的内存段** | 很大 | 可读写 | 17 | | | 栈stack | 存放: 程序**临时创建**的局部变量 | 空间较小2M | 可读写 | 18 | 19 | 20 | 21 | 2. BSS段(bss segment)“Block Started bySymbol”“以符号开始的块” 22 | 23 | + 存放 : 程序中**未初始化**的全局变量和静态变量; 24 | + 未初始化: 没有显示赋值; 25 | + BSS段属于**静态内存分配**。 26 | + BSS节不包含任何数据,只是简单的维护开始和结束的地址,即总大小 27 | + 以便内存区能在运行时分配并被有效地清零 28 | + 运行是占空内存: 29 | + **不占用磁盘**空间而只在运行的时候占用内存空间, 30 | + 所以如果全局变量和静态变量未初始化那么其可执行文件要小很多。 31 | 32 | 3. 数据段(.data) 33 | 34 | + 存放: 程序中**已初始化**的全局变量和静态变量的一块内存区域 35 | + 数据段属于静态内存分配 36 | + 只读数据段 : 字符串常量等 37 | + 读写数据段 38 | + 内存大小 39 | + 全局变量和静态变量的存储区域是在一起的,程序结束后由系统释放。 40 | + 数据区的大小由系统限定,一般很大。 41 | 42 | 4. 代码段(.text) 43 | 44 | + 存放: 程序**执行代码**的一块内存区域; 45 | + 这部分区域的大小在程序运行前就已经确定 46 | + 并且内存区域通常属于**只读** 47 | 48 | 5. 堆(heap) 49 | 50 | + 存放 : 进程运行中被**动态分配的内存段**,它的大小并不固定,可动态扩张或缩减 51 | + 堆内存的变化: 52 | + 调用malloc等函数分配内存时: 新分配的内存就被动态添加到堆上(堆被扩张) 53 | + free等函数释放内存时: 被释放的内存从堆中被剔除(堆被缩减) 54 | + 内存空间大小 55 | + 堆是向高地址扩展的数据结构,是不连续的内存区域。 56 | + 堆的大小受限于计算机系统中有效的虚拟内存。由此可见,堆获得的空间比较灵活,也比较大。 57 | 58 | 6. 栈(stack) 59 | 60 | + 存放: 程序**临时创建**的局部变量,也就是说我们函数括弧“{}”中定义的变量 61 | + 但不包括static声明的变量: static意味着在**数据段**中存放变量 62 | + 作用 63 | + **函数被调用**: 其参数也会被压入发起调用的进程栈中; 并且待到调用结束后,函数的返回值也会被存放回栈中 64 | + 栈特别方便用来保存/恢复调用现场; 65 | + 栈的空间大小: 66 | + 栈:由高地址向低地址扩展的数据结构,是一块连续的内存的区域。 67 | + 这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,能从栈获得的空间较小 68 | + 在linux上默认的大小是8M,可以用ulimit查看和修改; -------------------------------------------------------------------------------- /8.1Dji大疆/OS简述线程之间的同步互斥时占用空间的大小.md: -------------------------------------------------------------------------------- 1 | ## 问题: OS 嵌入式系统中共享资源的访问限制, 需要描述其占用空间的大小? 2 | 3 | 1. 具体问题的描述? 4 | + 嵌入式系统中, 为了保证资源的独立访问, 通常会设计锁保证互斥. 假定系统中有N(<256)个任务要访问同一个共享资源,任务要获取锁之后才能进行访问. 由于每个人物的优先级一样. 目前系统已经实现了一种锁可以保证互斥访问, 但是没有办法保证顺序, 即容易造成线程饿死的情况? 5 | + 需要设计一种机制, 能保证锁按照先到先得的任务方式被任务获取, 并且占用的内存空间最小; 请描述这种机制使用的数据结构和使用过程中占用的空间大小, 以及每个字节的存储空间的使用方法? 6 | 2. 这种机制: 同步互斥的机制; 7 | + 采用条件变量和锁进行实现; 8 | + 锁: 是一个二值信号, 保证了任务之间的互斥, 任何时候只有一个任务获得锁, 其余任务只能处于等待状态; 9 | + 条件变量中的cond_wait(): 会将任务放到一个队列中; 10 | + 同时cond_signal(): 会从队头唤醒一个任务去执行; 11 | 3. 机制中使用的数据结构: 12 | + 占用一个N大小的队列空间, 队列可以通过链表进行创建实现, 有任务等待时才创建; 13 | + 数组实现: array[256] 14 | + 链表实现: 两个 int 型变量; 15 | + 每个字节的存储方法? -------------------------------------------------------------------------------- /8.1Dji大疆/OS系统设计.md: -------------------------------------------------------------------------------- 1 | ### [OS系统设计](https://blog.csdn.net/qq_38410730/article/details/80905551) -------------------------------------------------------------------------------- /8.1Dji大疆/cpu对锁的支持.md: -------------------------------------------------------------------------------- 1 | ### 无锁可以提高整个程序的性能,但是CPU需要对此提供支持,请以x86/ARM为例简述。 2 | 3 | 1. 无锁编程技术方法包括? 4 | - 原子操作(atomic operations), 内存栅栏(memory barriers; 5 | - 内存顺序冲突(memory order), 指令序列一致性(sequential consistency)和顺ABA现象 6 | 2. 最基础和最重要的操作是原子操作? 7 | - 定义: 原子操作在**执行完毕之前**不会被任何其它任务或事件**中断**的一系列操作。 8 | - 非阻塞编程最核心基本的部分 9 | - 如果不存在原子操作: 操作会因为中断异常等各种原因引起**数据状态的不一致**从而影响到程序的正确 10 | 3. 原子操作的实现机制: 需要CPU的支持 11 | - 在硬件层面上: **CPU处理器**会默认保证基本的内存操作的原子性; 12 | - 复杂的内存操作: 需要**CPU指令集**中设计的原子操作指令; 13 | 4. 无锁编程中经常用到的原子操作? 14 | - 全部基于硬件原语实现锁, 不适用线程库 15 | - 常用的原子操作又是**比较交换CAS**COMPARE AND SWAP,几乎所有的CPU指令集都支持CAS的原子操作; 16 | - **X86平台**下中的是 CMPXCHG(Compare Are Exchange) 17 | 5. CAS操作具体的实现原理主要是两种方式:总线锁定和缓存锁定 18 | 6. 解决ABA的问题的一种方法是? 19 | - 一次用CAS检查双倍长度的值,前半部是指针,后半部分是一个计数器; 20 | - 或者对CAS的数值加上版本号。 21 | 22 | 23 | -------------------------------------------------------------------------------- /8.1Dji大疆/linux内核中常用的两个宏定义.md: -------------------------------------------------------------------------------- 1 | ## [Linux内核中常用的两个宏定义](https://blog.csdn.net/feiyanaffection/article/details/79282562) 2 | 3 | 1. 内存中如何求一个变量的地址? 4 | 5 | + physical adress = virtual adress + base (基质/界限) 6 | 7 | 2. 描述**Linux内核结构体**container_of的宏定义 8 | 9 | ``` 10 | #define offsetof(TYPE,MEMBER) ((size_t)&((TYPE*)0)->MEMBER) 11 | #define XXX(ptr,type,member)({\ 12 |     const typeof(((type*)0)->member) *__mptr=(ptr);\ 13 |     (type*)((char*) __mptr – offsetof(type,member));}) 14 | ``` 15 | 16 | ### 第一个宏:offsetof 17 | 18 | 1. offsetof: 用于计算 TYPE 结构体中 MEMBER 成员的**偏移位置** 19 | 20 | ``` 21 | #ifndef offsetof 22 | #define offsetof(TYPE, MEMBER) ((size_t)&((TYPE*)0)->MEMBER) 23 | #endif 24 | ``` 25 | 26 | 2. 编译器到底做了什么? 27 | 28 | + `size_t`类型就是`long unsigned int`类型,这句代码的意思不就是C语言里面的强制类型转换形式 29 | + (TYPE*)0:将0强转为TYPE类型的指针,且指向了0地址空间; 30 | + (TYPE*)0->MEMEBER:指向结构体中的成员; 31 | + &((TYPE*)0->MEMBER):获取成员在结构体的位置,因为起始为0,所以获取的地址即为实际的**偏移地址**。 32 | 33 | 3. 直接使用**0**地址处的值不会导致程序崩溃吗? 34 | 35 | + 其实上面的宏,并没有使用**0**地址处的值,而是和将 **结构体地址 和 成员变量的偏移量地址 做了加法运算**,得到成员变量的偏移位置,具体转换在代码中已经注释了。 36 | 37 | ### 第二个宏:typeof 38 | 39 | 1. typeof: 用于得到结构体的**首地址** 40 | 41 | ``` 42 | #define XXX(ptr,type,member)({\ 43 |     const typeof(((type*)0)->member) *__mptr=(ptr);\ 44 |     (type*)((char*)__mptr – offsetof(type,member));}) 45 | ``` 46 | 47 | 2. 实现思路 48 | 49 | + typeof构造的主要应用是用在宏定义中。可以使用typeof关键字来引用宏参数的类型。也就是说,typeof(((type*)0)->member)是引用与type结构体的member成员的数据类型; 50 | + 获得了数据类型之后,定义一个与type结构体的member成员相同的类型的指针变量__mptr,且将ptr值赋给它; 51 | + 用宏offsetof(type,member),获取member成员在type结构中的偏移量; 52 | 53 | + 最后将__mptr值减去这个偏移量,就得到这个结构变量的地址了(亦指针)。 54 | 55 | 3. 具体的功能就是: 56 | 57 | + ptr是指向正被使用的某类型变量指针; 58 | + type是包含ptr指向的变量类型的结构类型; 59 | + member是type结构体中的成员,类型与ptr指向的变量类型一样。 60 | + **功能** : 计算返回包含ptr指向的变量所在的type类型结构变量的指针。 -------------------------------------------------------------------------------- /8.1Dji大疆/linux目录结构.md: -------------------------------------------------------------------------------- 1 | ### linux目录结构 2 | 3 | 1. linux**目录结构**,选项是/usr、/tmp、/etc目录的作用? 4 | 5 | 6 | 7 | | 目录结构 | 功能 | 8 | | ----------------------------- | ------------------------------------------------------------ | 9 | | /usr (Unix Software Resource) | Unix操作系统**软件资源**放置的目录(而**不是用户的数据**) | 10 | | /tmp | **一般使用者**或者是正在**执行的程序**: 暂时放置档案的地方; FHS甚至建议在开机时,应该要将/tmp下的资料都**删除** | 11 | | /etc | 系统**主要的设定档**几乎都放置在这个目录内; 帐号**密码档**、各种服务的**启始档** | 12 | | /mnt | **mount 挂载**某些额外的装置 | 13 | | /opt | 第三方协力软体放置的目录 | 14 | | /sbin | **设定系统环境**,这些指令只有**root**才能够利用来设定系统 | 15 | | /bin | 重要执行档 | 16 | 17 | -------------------------------------------------------------------------------- /8.1Dji大疆/linux系统打开设备文件处于的状态.md: -------------------------------------------------------------------------------- 1 | ### linux系统打开设备文件,进程可能处于三种基本状态? 如果多次打开设备文件,驱动程序应该实现什么? 2 | 3 | 1. linux系统打开设备文件,进程可能处于三种基本状态 4 | - 运行 , 就绪, 阻塞 5 | 2. 如果多次打开设备文件,驱动程序应该实现什么? 6 | - 实现设备共享区域数据的同步和互斥访问; 7 | 8 | -------------------------------------------------------------------------------- /8.1Dji大疆/photo/Cobject_link.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/8.1Dji大疆/photo/Cobject_link.png -------------------------------------------------------------------------------- /8.1Dji大疆/photo/INTR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/8.1Dji大疆/photo/INTR.png -------------------------------------------------------------------------------- /8.1Dji大疆/photo/big-small-endian.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/8.1Dji大疆/photo/big-small-endian.png -------------------------------------------------------------------------------- /8.1Dji大疆/photo/emebeded_OS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/8.1Dji大疆/photo/emebeded_OS.png -------------------------------------------------------------------------------- /8.1Dji大疆/photo/pointer_judge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/8.1Dji大疆/photo/pointer_judge.png -------------------------------------------------------------------------------- /8.1Dji大疆/photo/thread_status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/8.1Dji大疆/photo/thread_status.png -------------------------------------------------------------------------------- /8.1Dji大疆/大端小端存储问题.md: -------------------------------------------------------------------------------- 1 | ### 大端小端存储问题 2 | 3 | 1. 大端和小端定义 4 | 5 | - 大端模式(BE big-endian),是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中(**低地址 对 高位,高地址 对 低位**); 6 | - 小端模式(LE little-endian),是指数据的低位保存在内存的低地址中,而数据的高位保存在内存的高地址中(**低地址对低位,高地址对高位**)。 7 | 8 | 2. 为什么会存在大端和小端区分? 9 | 10 | + **地址单元:** 按照Byte进行划分, 也就是8bit; 11 | + 如果一个值含有多个字节, 如何对其进行安排就是一个问题? 12 | 13 | ``` 14 | value : 0x1122; // 0x11 -- 高位; 0x22 -- 低位; 15 | adress: 16bit -- 0x0010; 16 | (1) big-endian: 0x0010 -- 0x11; 0x0011 -- 0x22; 17 | (2) little-endian: 0x0010 -- 0x22; 0x0011 -- 0x11; 18 | ``` 19 | 20 | 3. 题目: 四个整数在内存中的存储情况,请选择其中最大的一个。 21 | 22 | ![big-small-endian.png](/8.1Dji大疆/photo/big-small-endian.png) 23 | 24 | ``` 25 | A:12345678、B:56781234、C:12785634、D:56341278。 26 | // 每个字节内部的顺序不变; 27 | ``` 28 | 29 | 30 | ### [如何判断处理器是大端存储还是小端存储](https://blog.csdn.net/bitboss/article/details/51247869) 31 | 32 | 1. 通过指针区分大小端; 33 | 34 | ``` 35 | void Judge_duan() 36 | { 37 | int a = 1; //定义为1是为了方便 如果你喜欢你可以随意, 38 | //只要你能搞清楚 例如:0x11223344; 39 | 40 | char *p = (char *)&a;//在这里将整形a的地址转化为char*; 41 | //方便后面取一个字节内容 42 | 43 | if(*p == 1)//在这里解引用了p的一个字节的内容与1进行比较; 44 | printf("小端\n"); 45 | else 46 | printf("大端\n"); 47 | } 48 | ``` 49 | 50 | ![pointer_judge.png](/8.1Dji大疆/photo/pointer_judge.png) 51 | 52 | 2. 通过联合体进行判断 53 | 54 | + **联合体的概念**: 联合体的各个成员**共用内存**,并应该同时只能有一个成员得到这块**内存的使用权**(即对内存的读写),而结构体各个成员各自拥有内存,各自使用互不干涉。 55 | 56 | ``` 57 | static union { 58 |     char c[4]; 59 |     unsigned long mylong; 60 | } endian_test = {{ 'l', '?', '?', 'b' } }; 61 | #define ENDIANNESS ((char)endian_test.mylong) 62 | ``` 63 | 64 | + 如果是“l”(小端)、“b”(大端) 65 | 66 | 3. 常见的大端和小端判断 67 | 68 | 69 | 70 | | 类型 | 处理器 | 71 | | ---- | ------------- | 72 | | 大端 | C51 | 73 | | 小端 | ARM, DSP, x86 | 74 | 75 | 76 | 77 | ### 小端转化 为大端8bit 78 | 79 | 1. 小端转化为大端? 80 | 81 | + 将小端低地址存储的低位, 放在高地址上 82 | + 按照8bit进行移位 83 | 84 | ``` 85 | int Lendmian_convertB(int t) 86 | { 87 | int result = 0; 88 | int i; 89 | for( i =0; i>= 8; 93 | } 94 | return result; 95 | } 96 | ``` 97 | 98 | 99 | ### 大端转化为小端 100 | 101 | 1. 32bit 的大端转化为小端 :该方法亦可用于小端模式转成大端模式 102 | 103 | ``` 104 | // 大端存储:低地址存储高位,高地址存储低位 105 | /* 106 | * (1) 将低8位(0~8位)左移24位,变成了高8位(24~32位) 107 | * (2) 将低8~16位左移8位变成了(16~24位) 108 | * (3) 将原高8位和高16位右移,变成了新的低8位和低16位; 109 | */ 110 | 111 | uint32_t reversebytes_uint32t(uint32_t value) 112 | { 113 | return (value & 0x000000FFU) << 24 | (value & 0x0000FF00U) << 8 | 114 | (value & 0x00FF0000U) >> 8 | (value & 0xFF000000U) >> 24; 115 | } 116 | ``` 117 | 118 | 2. 64bit的转换方法 119 | 120 | ``` 121 | /* 122 | * 64位的转换方法:转化为两个32bit进行转换 123 | */ 124 | 125 | uint64_t reversebytes_uint64t(uint64_t value) 126 | { 127 | uint32_t high_uint64 = (uint64_t) (reversebytes_uint32t(uint32_t(value))); // 低32位转成小端 128 | uint64_t low_uint64 = (uint64_t)reversebytes_uint32t(uint32_t(value >> 32)); // 高32位转成小端 129 | return (high_uint64 << 32) + low_uint64; 130 | 131 | ``` 132 | 133 | 3. 具体的例子 134 | 135 | ``` 136 | // 比如0x12345678,小端模式下可认为是12*(2^32) + 34*(2^16) + 56*(2^8) + 78*(2^0)。 137 | // 在大端模式下,排列顺序发生了变化。 138 | 139 | uint32_t changeEndian_uint32t(uint32_t value){ 140 | char* ptr = (char*)(&value); // uint32_t的变量强制转换成字符类型数组,以便一个字节一个字节的处理。 141 | 142 | uint64_t base[4]; // 设置基 143 | base[0] = 1; 144 | for(int i = 1; i < 4; ++i){ 145 | base[i] = base[i-1] * 256; 146 | } 147 | 148 | uint32_t res = 0; 149 | for(int i = 0; i < sizeof(value); ++ i){ 150 | res += uint8_t(ptr[i]) * base[4-i-1]; 151 | } 152 | 153 | return res; 154 | } 155 | ``` 156 | 157 | -------------------------------------------------------------------------------- /8.1Dji大疆/简述C函数中参数传递问题.md: -------------------------------------------------------------------------------- 1 | ## 简述C函数中参数传递问题? 2 | 3 | ### 问题一: C函数中参数如何传递(__cdecl调用方式) 4 | 5 | 1. 什么是函数调用约定? 6 | 7 | + 函数的调用: 会发生参数的传递和值的返回; 函数调用完后, 会释放的分配的内存空间; 8 | + **函数调用约定作用**: 描述**参数的传递**过程,决定由调用者(被调用者)**平衡堆栈**; 9 | + (1) 决定了发生函数调用时函数**参数的入栈顺序** 10 | + (2)决定由**调用者函数**(被调用函数)负责**清除栈**中的参数,还原堆栈; 11 | 12 | 2. 常见的函数调用约定有哪些? 13 | 14 | + 按参数的**传递顺序**对这些约定可划分: (栈: 从上到下入栈?) 15 | + 从右到左依次入栈:__ stdcall (C++),__ cdecl (C),__thiscall; 16 | + 从左到右依次入栈:__ pascal,__fastcall。 17 | 18 | 3. * __cdecl**函数调用约定? 19 | 20 | + **__cdecl**:C Declaration的缩写(declaration,声明)表示C语言默认的函数调用方法; 21 | + **入栈顺序:** 所有参数从右到左依次入栈, 22 | + **调用者函数:** 由调用者负责把参数压入栈,最后也是由调用者负责清除栈的内容 ; 23 | + __stdcall:是StandardCall的缩写,是C++的标准调用方式 24 | + 特征类似; 25 | 26 | 4. **可变参数**的函数调用约定如何选择? 27 | 28 | + 要求: **带有可变参数的函数必须是__cdecl调用约定** 29 | + 例如: printf 30 | 31 | ### [问题二: C语言返回值如何传递?](https://blog.csdn.net/qq_33921804/article/details/52663212) 32 | 33 | 1. 函数返回值为什么一般放在**寄存器**中? 34 | 35 | + 如果放在堆栈中: 有可能因为中断而被覆盖。 36 | + esp 寄存器总是指向栈顶(低地址),ebp指向栈底(高地址) 37 | + 栈的增长方向:由高地址--向低地址 38 | 39 | 2. C语言返回值通过哪个寄存器传递? 40 | 41 | + 一般情况: 通过**eax**进行传递的,但是eax只能存储**4个字节**的信息; (返回值不会太大) 42 | + 返回值大小为**M字节** 43 | + M <= 4字节,将返回值存储在eax返回; 44 | + 4 < M <=8,把eax,edx联合起来。其中,edx存储高位,eax存储**低位**; 45 | + [M > 8,如何传递呢?用一下代码测试:](https://blog.csdn.net/qq_38410730/article/details/80895986) 46 | + 通过指针进行传递, 指针大小也是4字节, 所以最后还是通过eax进行 47 | 48 | 3. 寄存器的说明 49 | 50 | + eax是"累加器"(accumulator), 它是很多加法乘法指令的缺省寄存器; 51 | 52 | + ebx 是"基地址"(base)寄存器, 在内存寻址时存放基地址; 53 | + ecx是计数器(counter), 是重复(REP)前缀指令和LOOP指令的内定计数器; 54 | + edx则总是被用来放整数除法产生的余数。 55 | 56 | ### [问题三: C语言调用后如何返回到调用前的下一条指令执行?](https://www.cnblogs.com/findumars/p/7545818.html) 57 | 58 | 1. 类似于进行的切换: 有东西保存切换前的所有状态变量. 59 | 2. C函数中用于保存的是?**函数的堆栈帧** 60 | + 函数的**堆栈帧**(Stack Frame) : 栈保存了一个函数调用所需要的维护信息; 61 | 3. **堆栈帧**保存了那几部分内容? 62 | + 函数的参数;函数的局部变量;寄存器的值(用以恢复寄存器) 63 | + 函数的返回地址以及用于结构化异常处理的数据(当函数中有try…catch语句时才有)等等 64 | 4. C语言调用后如何返回到调用前的下一条指令执行? 65 | + 函数的堆栈帧: 存放了**函数的返回地址**,即调用方调用此函数的下一条指令的地址。 66 | + 故而,在函数调用后,由函数调用方执行,直接返回调用前的下一条指令。 -------------------------------------------------------------------------------- /8.24HIK/C中全局变量和局部变量可以重名.md: -------------------------------------------------------------------------------- 1 | ## C中全局变量和局部变量可以重名 2 | 3 | 1. 全局变量和局部变量是可以重名的 4 | 5 | + 变量名相同时, 使用就近原则处理; 6 | 7 | ``` 8 | int num = 123; 9 | 10 | void num_value() 11 | { 12 | int num = 789; 13 | printf("The num value is %d.\n", num); 14 | } 15 | 16 | int main() 17 | { 18 | int num = 456; 19 | printf("The num value is %d.\n", num); 20 | return 0; 21 | } 22 | 23 | // The num value is 789. 24 | // The num value is 456. 25 | ``` 26 | 27 | 2. static修饰的全局变量和局部变量值的计算 28 | 29 | ``` 30 | // 31 | // Created by quronghui on 2019/9/16. 32 | // 33 | // 题目:static修饰的全局变量和局部变量值的计算 34 | // (1)全局变量和局部变量重名时,按照就近原则取; 35 | // (2)static 修饰的变量,分为模块内和模块外 36 | // (3)a++自加运算时,先返回a做运算,然后a才自加 37 | #include 38 | 39 | static int a = 1; 40 | 41 | int f(int c) 42 | { 43 | static int a = 2; // 考虑这个静态变量会存储值吗? 会进行存储,知道整个程序运行完才释放;所以第二次调用时a=3; 44 | c = c + 1; 45 | return a++ + c; // 此时先取a的值计算后,才进行a++; 46 | } 47 | 48 | int main() 49 | { 50 | int i, k=0; 51 | for (i = 0; i < 2; ++i) { 52 | int a = 3; //定义了局部变量a 53 | k += f(a); 54 | } 55 | k += a; // 这时候的a用的是全局变量a的值 56 | printf("%d\n", k); 57 | return 0; 58 | } 59 | // 输出值为14; 60 | ``` 61 | -------------------------------------------------------------------------------- /8.24HIK/C宏使用.md: -------------------------------------------------------------------------------- 1 | ## #define 的作用 2 | 3 | ### 实现一个变量的置位操作 4 | 5 | 1. 实现对一个变量的bit2置位操作 6 | 7 | ``` 8 | // bit2, 就是变量的第二位 9 | #define SEETING(a) (a&( ~(0x01<<2)) 10 | or 11 | #define SEETING(a) (a&( ~2) 12 | ``` 13 | 14 | ### 求一个数组元素的个数 15 | 16 | ``` 17 | // 给一个数组名table, 求其数组中元素的个数 18 | #define SIZEOF(table) sizeof(table)/(sizeof(table[0])) 19 | ``` 20 | 21 | + 先求出数组table的总长度, 除以每一个元素占有的大小 22 | 23 | ### 用以表明1年中有多少秒(忽略闰年问题) 24 | 25 | ``` 26 | #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL // UL 表示的是长整形的变量 27 | ``` 28 | 29 | + 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉编译器这个常数是的长整型数。 30 | + 如果你在你的表达式中用到**UL**(表示无符号长整型) 31 | 32 | ### 输入两个参数并返回较小的一个 33 | 34 | ``` 35 | #define MIN(a,b) ( (a) <= (b) ? (a) : (b) ) //学会打括号 36 | ``` 37 | 38 | 1. define 定义最小值的使用中要注意一个问题 39 | 40 | ``` 41 | MIN(*p++, b) 42 | ((*p++) <= (b) ? (*p++) : (b)) // 产生一个副作用,使得p自加两次 43 | ``` 44 | 45 | 46 | ### **不用中间变量,实现两变量的交换** 47 | 48 | ``` 49 | #define swap(x, y) x = x + y; y = x - y; x = x - y // 注意结尾是没有分号的,因为在程序里面是有分号的 50 | ``` 51 | 52 | 53 | 54 | ## typedef 的作用 55 | 56 | 1. typedef的作用 57 | 58 | + 用来声明一个别名,typedef后面的语法,是一个声明 59 | + 后面的是一个整体,而不是分开的? 60 | 61 | ``` 62 | typedef int PARA ; // 这种形式跟#define int PARA几乎一样,造成了一种误解,误以为两者是分开的; 63 | ``` 64 | 65 | 2. 真正的理解typedef 66 | 67 | ``` 68 | typedef int PARA ; // 将 int PARA看成一个整体,类似于 int i; 69 | ``` 70 | 71 | + 声明一样是一个**整体声明**,只不过int i定义了一个变量; 72 | + 而typedef定义了一个**别名** 73 | 74 | 3. typedef的两个例子 75 | 76 | + ``` 77 | typedef int a[10]; // 把a声明为具有10个int元素的数组的类型别名 78 | typedef void (*p)(void); // p是一种函数指针的类型别名 79 | ``` 80 | 81 | 4. typedef 函数指针的声明和调用 82 | 83 | ``` 84 | typedef void (*convert)() ; // typedef定义了一个函数指针; 85 | 86 | void func(void) 87 | { 88 | printf("hello.\n"); 89 | } 90 | 91 | int main() 92 | { 93 | puts("By typedef: "); 94 | convert func_pp = func; // 函数指针的指向 95 | (func_pp)(); // 函数指针的调用; 96 | } 97 | ``` 98 | 99 | -------------------------------------------------------------------------------- /8.24HIK/list相关操作.md: -------------------------------------------------------------------------------- 1 | ## list的相关操作 2 | 3 | ### 问题一: 文件的物理结构,哪一个只能采用顺序存取方式? 4 | 5 | 1. 链式文件 6 | + 链接文件只能根据链去找下一个,依次访问 7 | + 就是和数据一样, 当时被迷惑了; 8 | 2. 文件中的数据可以随机访问 9 | + 顺序文件 10 | + 索引文件 11 | + Hash文件 12 | 13 | ### 问题二: 为一个链表设置一个head和tail, 链表的操作哪一个和长度相关? 14 | 15 | 1. 删除单链表的最后一个元素 16 | + 你必须去找删掉的节点的前一个节点, 由于是单链表, 你要找这个节点就要遍历一次链表 17 | + 当链表只有一个节点时, 需要重新将head 和 tail 指向同一个位置; 18 | + 类似于队列中出队操作, 遇到队里只有一个元素时的处理; -------------------------------------------------------------------------------- /8.3网易/Dijkstra最短路径算法的描述.md: -------------------------------------------------------------------------------- 1 | ### Dijkstra最短路径算法的描述正确的是? 2 | 3 | 1. Dijkstra最短路径算法的描述正确的是? 4 | 5 | 6 | 7 | | 算法 | 功能 | 8 | | -------------- | ------------------------------------------------------------ | 9 | | Floyd | 求多源、无负权边的最短路。用矩阵记录图。时效性较差 | 10 | | Floyd-Warshall | 解决**任意两点间**的**最短路径**的一种算法,可以正确处理**有向图**或**负权**的最短路径问题 | 11 | | Dijkstra | 求单源、无负权的最短路。时效性较好 | 12 | 13 | -------------------------------------------------------------------------------- /8.3网易/LInux系统权限.md: -------------------------------------------------------------------------------- 1 | ## Linux 目录和文件的权限 2 | 3 | | 权限 | 文件 | 目录 | 4 | | ---- | ---------------------------------- | ------------------------------------------ | 5 | | r | 读取**文件内容**的权限 | **浏览目录**的权限 | 6 | | w | 新增、修改和删除**文件内容**的权限 | 新建、删除、修改和移动**目录内文件**的权限 | 7 | | x | 执行文件的权限 | 该用户具有**进入目录**的权限 | 8 | 9 | 1. 查询文件或者目录的权限 10 | 11 | ``` 12 | $ umask //查询文件的umask权限 13 | 0024 14 | $ umask -S // 查询其具体的rwx 15 | u=rwx,g=rx,o=wx 16 | $ umask 027 /修改当前的umask 17 | ``` 18 | 19 | 2. **目录下**的权限条件? 20 | 21 | + 只有获得**x**权限:才能**cd**进入目录; 22 | + 只有获得 **x + r**:才能cd进入目录,并且**浏览**目录下的文件名和目录名; 23 | + 只有获得**w**权限:目录下的文件才能被**删除**;除非是文件所有者; 24 | 25 | 3. 如果没有目录下的w权限,即使拥有文件的w权限,某文件也不能写; 26 | 27 | 4. 如果目录下有文件,但是目录的权限不是rwx,则无法使用rm -rf 删除该目录; 28 | 29 | ### Linux 文件权限的计算 30 | 31 | + umask 、权限:默认是三位的8进制数; 32 | 33 | 1. Linux 系统权限755 777 644 ? 34 | 35 | + r -- 读 ; w -- 写 ; x -- 执行 36 | 37 | ![linux_chmod.png](/8.3网易/linux_chmod.png) 38 | 39 | 2. 3位的八进制数字 40 | 41 | - :7 (rwx),6 (rw-),5 (r-x),4 (r–),and 0 (-–) 42 | - “600”,我们能够设置文件所有者的权限为读写权限, 而删除用户组和其他人的所有权限。 43 | 44 | ### umask和文件目录的权限 45 | 46 | | 区别 | umask | 文件 | 目录 | 47 | | ----------- | ------------------- | ------------------------------------- | --------------------------- | 48 | | 创建时默认 | root-022 / user-002 | 666 / rw-rw-rw | 777 / rwx-rwx-rwx | 49 | | x权限的区分 | | 文件默认没有x执行权限的,除非更改权限 | 默认含有x权限,才能进入目录 | 50 | | 权限改变 | 当umask = 022 | 666 - 022 = 644 / rw - r - r | 777 - 022 = 755 / rwx-rx-rx | 51 | 52 | + 当设置umask值 53 | 54 | ``` 55 | 文件和目录的权限 = 原来文件和目录的权限 - umask 56 | ``` 57 | 58 | -------------------------------------------------------------------------------- /8.3网易/echo重定义和grep正则表达式匹配.md: -------------------------------------------------------------------------------- 1 | ### echo 重定义 和 grep 正则表达式匹配 2 | 3 | 1. 重定向标准输出和标准错误 到同一文件 4 | 5 | ``` 6 | $ echo hello 1>&2 | grep aaa // 通过stderr直接输出hello,buffer里面此时为空,没有其他的值 7 | $ echo hello 2>&1 |grep aaa // 无输出;buffer里面的内容hello和aaa不匹配,所以没有输出 8 | ``` 9 | 10 | + echo hello :将hello输出到屏幕; 11 | + 1>&2:将stdout重定向到stderr通道,也就是将stdout的内容通过stderr显示出来; 12 | + stdout :先放在缓冲区中 13 | + stderr:直接输出到屏幕; 14 | + grep aaa:匹配这个buffer里面是否存在aaa; 15 | 16 | 2. grep 正则表达式 17 | 18 | - 一个连行符 : 由一个斜杠字符其后紧跟一个回车符组成。它们之间不允许有空白字符。 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /8.3网易/linux_chmod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/8.3网易/linux_chmod.png -------------------------------------------------------------------------------- /8.3网易/二叉树节点和度.md: -------------------------------------------------------------------------------- 1 | ## 树的考题 2 | 3 | ### 树和二叉树的叙的区别? 4 | 5 | | 区别 | 树 | 二叉树 | 6 | | ------------ | ---------------------------------------------- | ------------------------------------------------------------ | 7 | | 集合 | 节点的**有限**集合,集合**不能为空集** | 是节点的一个有限集合,可以为空集 | 8 | | 子数个数 | 树中每个节点可有**若干子树** | 每个元素都恰好有**两棵子树**
其中一个或者两种**可能为空** | 9 | | **根本区别** | | 子树可以用左、右子数来区别
其子树的次序不能颠倒 | 10 | | 节点的度 | 节点所拥有**子树的个数**称为节点的度 | 最大为2 | 11 | | 树的度 | 树中所有节点的**度的最大值**成为该树的度。 | 同左 | 12 | | 根节点的层次 | 1,其余结点的层次等于该结点的双亲结点的层次加1 | | 13 | | **树的高度** | 树中结点的最大层次 | | 14 | | **存储结构** | 双亲、孩子、双亲孩子、孩子兄弟 | 顺序、链式 | 15 | 16 | 1. **森林**: 17 | + 0个或多个不相交的树组成。 18 | + 对森林加上一个根,森林即成为树;删去根,树即成为森林。 19 | 20 | ### 二叉树节点的度 21 | 22 | 1. 二叉树8个度为2节点, 5个度为1节点 , 度为0有多少个节点? 23 | - 度和节点之间的关系: 在树中,结点有几个分叉,度就是几; 24 | - 度为0的节点: 9个 25 | 2. 度为0的节点数 = 度为2的节点数 + 1 26 | 27 | ### 二叉树 28 | 29 | 1. 二叉树定义:二叉树是每个结点最多有两个子树的树结构 30 | 31 | 2. 二叉树的五中状态: 32 | 33 | ![binary_tree.png](/dataStruct/photo/binary_tree.png) 34 | 35 | 3. 二叉树的性质 36 | 37 | ![dgree.png](/dataStruct/photo/dgree.png) 38 | 39 | 4. 二叉树中的满二叉树和完全二叉树? 40 | 41 | - 在**满二叉树**的基础上,我在最底层从右往左删去若干节点,得到的都是完全二叉树。 42 | - 满二叉树一定是完全二叉树,但是完全二叉树不一定是满二叉树 43 | 44 | 5. 每一棵二叉树都能唯一地转换到它所对应的树(林) 45 | 46 | 6. 二叉树错误的描述? 47 | 48 | + 二叉树是树的特殊情况,即每个结点的子树个数都不超过2 49 | + 正确描述:每个元素都恰好有**两棵子树**,其中一个或者两种**可能为空** -------------------------------------------------------------------------------- /C/C中常量的表示.md: -------------------------------------------------------------------------------- 1 | ## C中常量的表示 2 | 3 | 1. 指数形式的科学计数法 e 4 | 5 | + 字母e或E**之前**:必须要有数字 6 | 7 | + e或E**后面**的指数:必须为整数 8 | 9 | + 字母e或E的前后以及数字之间:不得插入空格 10 | 11 | + ``` 12 | e3 ; 2e3.6; // 不合法的科学计数法 13 | 2.3e6; //2.3*10^6; 合法的科学计数法 14 | ``` 15 | 16 | 2. 进制数常量 17 | 18 | + 十进制数的常量 : 10;300 19 | 20 | + 八进制数的常量:以0开头,不能超过8 21 | 22 | + ``` 23 | 0276;(只有三位); 0128;// 这个是错的 24 | ``` 25 | 26 | + 十进制数的常量:以0x开头,不超过f 27 | 28 | + ``` 29 | 0x7F; 0xcd; 30 | ``` 31 | 32 | 3. 字符型常量 33 | 34 | ``` 35 | 普通字符,如‘a’,‘b’,‘c’ 36 | 转义字符,如‘\n’,‘\t’,‘\b’ 37 | ``` 38 | 39 | 4. 标识符 40 | 41 | + 标识符只能是英文字母(A-Z,a-z)和数字(0-9)或者下划线(_)组成,并且**第一个字母必须是字母或者下划线开头**,这点与变量的要求是一样的 42 | + 同样的标识符区分**大小写** 43 | + 不能使用**关键字**来命名标识符 -------------------------------------------------------------------------------- /C/C变量的生命周期.md: -------------------------------------------------------------------------------- 1 | ## C变量的生命周期 2 | 3 | | 变量类型 | 作用域 | 空间分配 | 未初始化 | 生命周期 | 4 | | ---------- | -------------- | ------------ | -------- | -------------- | 5 | | 普通局部 | 属于某个 "{ }" | 执行到该语句 | 随机数 | "{ }" 结束释放 | 6 | | static局部 | 属于某个 "{ }" | 编译阶段 | 0 | 程序结束 | 7 | | 普通全局 | 整个程序 | 编译阶段 | 0 | 程序结束 | 8 | | static全局 | 整个程序 | 编译阶段 | 0 | 程序结束 | 9 | | | | | | | 10 | 11 | 1. 普通全局变量 和 static全局变量 的区别? 12 | + 可以作用到外部文件; 13 | 2. extern函数和static函数的区别 14 | + extern声明的函数, 所有文件都是调用,所有文件中只能定义一次extern函数。 15 | + static函数只能在定义所在的文件中调用此函数; -------------------------------------------------------------------------------- /C/C实现一个数的四舍五入.md: -------------------------------------------------------------------------------- 1 | ## C实现一个数的四舍五入 2 | 3 | 1. 实现一个数的四舍五入 4 | 5 | + 负数和正数的上限值不一样; 6 | 7 | + ``` 8 | (int)(x*10的n次方+0.5)*10的负n次方; 9 | ``` 10 | 11 | 2. 代码实现 12 | 13 | ``` 14 | // 题目:实现一个小数的四舍五入 15 | #include 16 | int main() 17 | { 18 | double d1,d2,d3; 19 | // d1=-3.1415926; 20 | d1 = 3.1415926; 21 | d2=(int)(d1*10+0.5)*0.1; 22 | printf("d1=%f,保留一位小数的结果为:%.1f\n",d1,d2); 23 | d3=(int)(d1*1000+0.5)*0.001; 24 | printf("d1=%f,保留三位小数的结果为:%.3f",d1,d3); 25 | /* 26 | 27 | 总结四舍五入保留n为小数 28 | (int)(x*10的n次方+0.5)*10的负n次方; 29 | 其次这个方法对负数无效;如果非要用可以先取正数部分算,最后加上负号 30 | */ 31 | 32 | } 33 | ``` 34 | 35 | -------------------------------------------------------------------------------- /C/C实现函数跳转到绝对地址0x100000处执行.md: -------------------------------------------------------------------------------- 1 | ## [C语言实现程序跳转到绝对地址0x100000处执行](https://blog.csdn.net/weixin_33779515/article/details/86337160) 2 | 3 | + 将0x100000看做某一个函数的首地址,也就是函数名; 4 | 5 | ### 函数名代表首地址 6 | 7 | 1. 通过程序:打印函数的地址 8 | 9 | ``` 10 | #include 11 | void func(void) 12 | { 13 | printf("hello.\n"); 14 | } 15 | int main() 16 | { 17 | // (1) 他们的结果是一样的 18 | printf("func = %d\n",func); 19 | printf("&func = %d\n",&func); 20 | } 21 | ``` 22 | 23 | 2. &运算符本来的意义 24 | 25 | + 它要求其操作数是一个**对象**,但**函数名不是对象**(函数是一个对象) 26 | + c/c++标准的制定者出于对象的概念已经有所发展的缘故,也承认了&func的合法性 27 | 28 | 3. 对于函数名:取址不取址都可以 29 | 30 | + // func是函数的首地址,它的类型是void (); 31 | 32 | + // &func表示一个指向函数void func(void)这个对象的**地址**(也就是指针),它的类型是void (*)() 33 | 34 | ### 函数指针的调用方法? 35 | 36 | ``` 37 | #include 38 | void func(void) 39 | { 40 | printf("hello.\n"); 41 | } 42 | int main() 43 | { 44 | // (2)在调用一个函数的时候,也有两种方法 45 | // 定义一个函数指针,这个指针无返回值,无参数,指向fun函数 46 | void (*func_p)(void) = func; 47 | (*func_p)(); //调用函数时,加一个括号 48 | (func_p)(); // 49 | func_p(); //后面两者也是对的,只是不那么用 50 | func(); 51 | 52 | 53 | } 54 | ``` 55 | 56 | 1. void * :参数无返回值; 57 | 58 | 2. void (*)(void) : 定义一个函数指针,这个指针无返回值,无参数,指向fun函数 59 | 60 | 3. 可以通过**typedef**定义函数指针,简化代码表示 61 | 62 | ``` 63 | typedef void (*convert)() ; // typedef定义了一个函数指针; 64 | // (4) 能不能通过typedef来简化表达式 65 | { 66 | puts("By typedef: "); 67 | convert func_pp = func; 68 | (func_pp)(); 69 | } 70 | ``` 71 | 72 | ### 使用函数调用,实现绝对地址的跳转 73 | 74 | ``` 75 | //(3)实现程序跳转到绝对地址0x100000处执行 76 | /* void (*)(void); --> int * ; //void *:是一个数据类型,返回值为空,参数为空; 77 | * ( void (*)(void) ); --> ( int * ); //加了一个括号之后,代表强制类型转换 78 | * ( void (*)(void) )0x100000; //把0x100000强制转化为一个函数指针 79 | * ( *( void (*)(void) )0x100000 )(); // 第一种方式实现 80 | * ( ( void (*)(void) )0x100000 )(); // 第二种方式:就是调用这个函数,外层再加个括号,后面在加一对括号 81 | */ 82 | ``` 83 | 84 | 1. 当数据类型加上一个**括号**之后:类似于类型的**强制转换**; 85 | 86 | 2. 实现函数的调用:采用第二种方式,在调用这个函数,外层再加个括号,后面在加一对括号 87 | 88 | ``` 89 | ( void (*)(void) )0x100000; //把0x100000强制转化为一个函数指针; 整体就是一个函数指针; 90 | ( ( void (*)(void) )0x100000 )(); //函数指针的调用,外层再加个括号,后面在加一对括号; 91 | ``` 92 | 93 | ### 几个误区 94 | 95 | 1. 两种错误的调用方式 96 | 97 | ``` 98 | ( void(*) (void) )0x100000 (); // 没有加外层括号 99 | *( (void(*) (void)0x100000) ) (); // *号在整体之外;没见过*func(); 这么用的…… 100 | ``` 101 | 102 | 2. **总结:最外层不能是* ,必须是括号** 103 | 104 | ### [all code](/code/memory_visit.c) -------------------------------------------------------------------------------- /C/C对于一个频繁使用的短小函数.md: -------------------------------------------------------------------------------- 1 | ## C/C++对于一个频繁使用的短小函数 2 | 3 | | 区别 | C | C++ | 4 | | -------- | -------------------- | ------------------------------ | 5 | | 实现 | 宏定义 | 用inline关键字,内联函数 | 6 | | 参数检查 | 不进行参数类型检查 | 内联函数进行类型检查,更加安全 | 7 | | 处理时期 | 预处理器对宏进行替代 | 内联函数通过编译器控制 | 8 | 9 | ### 函数调用 和 内联函数的区别 10 | 11 | 1. 函数调用? 12 | + 优势:函数的引入,可以**减少**程序的目标代码,实现程序代码和数据的**共享**。 13 | + 缺点:函数调用也会带来降低**时间效率**(不断地参数压栈)的问题;这种转移操作要求在转去前要保护现场并记忆执行的地址,转回后先要恢复现场,并按原来保存地址继续执行。 14 | 2. 内联函数inline 15 | + 引入内联函数的目的是为了解决程序中函数调用的效率问题。 16 | + 程序编译时:编译器将程序中出现的内联函数的调用**表达式**,用内联函数的**函数体**来进行**替换**; 17 | + 缺点:通过**空间**代价替换**时间**效率; 18 | 19 | ### **使用内联函数注意事项** 20 | 21 | 1. 在内联函数中如果有**复杂操作**将不被内联,如:循环和递归调用。 22 | 2. 所有在类的声明中定义的函数将被自动认为是内联函数,但是第1种情况时编译器可能会放弃内联方式。 23 | 3. 内联函数的定义必须出现在内联函数第一次被调用之前。 24 | 25 | -------------------------------------------------------------------------------- /C/C简述static关键字对于工程模块化的作用.md: -------------------------------------------------------------------------------- 1 | ## static修饰 2 | 3 | | 区别 | 全局变量 | static全局变量 | 4 | | ------------ | ------------------------------------------------------------ | -------------------------- | 5 | | 存储 | 静态存储:bss / data | 静态存储:bss / data | 6 | | **作用域** | **整个**源程序: 非静态的全局变量在**各个源**文件中都是有效的 | 只在**定义**的源文件中有效 | 7 | | 生存周期 | **整个**源程序结束 | **定义**的源文件结束 | 8 | | | | | 9 | | **区别** | **局部变量** | **static局部变量** | 10 | | **存储** | 栈空间 | 静态存储:bss / data | 11 | | 作用域 | 定义的函数中 | 定义的函数中 | 12 | | **生存周期** | 定义的函数结束后就结束 | **整个**源程序结束 | 13 | | | | | 14 | | **区别** | **普通函数** | **static函数** | 15 | | 作用域 | 只要包含该头文件,就能使用这个函数 | **仅在**本文件中使用 | 16 | 17 | 1. ​ static全局变量与普通的全局变量有什么区别: 18 | - static全局变量只初始化一次,防止在其他文件单元中被引用; 19 | 2. static局部变量和普通局部变量有什么区别? 20 | - static局部变量只被初始化一次,下一次依据上一次结果值; 21 | 3. static函数与普通函数有什么区别? 22 | - static函数在内存中只有一份,普通函数在每个被调用中维持一份拷贝; 23 | 24 | ### C简述static关键字对于工程模块化的作用? 25 | 26 | 1. static 作用对相关的划分? 27 | 28 | - 函数体内**static变量**: 作用范围为该**函数体**,不同于auto变量, 该变量的**内存只被分配一次**,以为其值在下次调用时仍**维持上次**的值(该变量存放在静态变量区) 29 | - 模块内**static全局变量** : 被模块内所有函数访问,但不能被模块外其他函数访问。(先定义后使用) 30 | - 模块内的**static函数** : 只可被这一模块内的其他函数调用,这个函数的使用范围被限制在声明它的模块内。 31 | 32 | 2. 嵌入式系统中, 移植的重要性? 33 | 34 | - 在定义变量及函数的过程,可能会重名,这给系统的集成带来麻烦, **因此保证不冲突的办法是显示的表示此变量或者函数是本地的,static即可** 35 | 36 | 3. Linux模块化编程中, 一条很明显的规定? 37 | 38 | - 所有的函数和全局变量: 都要用static关键字声明,将其作用域限制在**本模块内部** 39 | - 与其他模块共享的函数或者变量 : 要**EXPORT到内核中**; 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /C/C运算符的优先级.md: -------------------------------------------------------------------------------- 1 | ## C中运算符的优先级 2 | 3 | ![operator_priority.png](https://github.com/quronghui/Embedded-written-reference/blob/master/C/photo/operator_priority.png) 4 | 5 | + 赋值运算符: 优先级最低的; 6 | 7 | ### 单目运算符和双目运算符 8 | 9 | 1. 单目运算符: 只需要一个操作数就可以运行 10 | 11 | ``` 12 | &a; !(i<0); 13 | ``` 14 | 15 | 2. 双目运算符: 需要两个操作数才能完成 16 | 17 | ``` 18 | a = 3; // 赋值运算符 19 | ``` 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /C/IGBT是什么控制性原件.md: -------------------------------------------------------------------------------- 1 | ## IGBT是什么控制性原件 2 | 3 | 1. IGBT是什么控制性原件? 4 | + 是**电压型**控制元件 5 | 2. IGBT是英文单词Insulated Gate Bipolar Transistor,它的中文意思是绝缘栅双极型晶体管 6 | + 从功能上来说,IGBT就是一个电路开关,优点就是用电压控制,饱和压降小,耐压高。 7 | 8 | -------------------------------------------------------------------------------- /C/PC寻址范围.md: -------------------------------------------------------------------------------- 1 | ## PC机的寻址范围 2 | 3 | 1. 单片机中的程序计数器PC是16位的寻址范围是64KB怎么来的呀? 4 | 5 | ``` 6 | 16 bits 7 | 2^16 = 2^10 * 2^6 = 1KB * 64 = 64KB 8 | ``` 9 | 10 | -------------------------------------------------------------------------------- /C/Token划分.md: -------------------------------------------------------------------------------- 1 | ## Token划分 2 | 3 | 1. 左值的运算符,都是左结合 4 | 5 | ``` 6 | int a=5, b=7, c1, c2, c3; 7 | // c1 = a+++b; // c1 = 12 8 | // c2 = a+ ++b; // c2 = 13 9 | // c3 = a++ +b; // c3 = 12 10 | a++ ++; // error:a++之后是一个常量,不是左值了,不能在++ 11 | ``` 12 | 13 | ### 左值概念 14 | 15 | 1. 16 | 17 | 1. 左值和右值的概念 18 | + 左值:能取地址,或者具名对象,表达式结束后依然存在的持久对象; 19 | + 右值:不能取地址,匿名对象,表达式结束后就不再存在的临时对象; 20 | 2. 左值和右值的区别 21 | 22 | + 左值能寻址,右值不能; 23 | + 左值能赋值,右值不能; 24 | + 左值可变,右值不能(仅对基础类型适用,用户自定义类型右值引用可以通过成员函数改变); -------------------------------------------------------------------------------- /C/error的目的是什么.md: -------------------------------------------------------------------------------- 1 | ## 预处理器的标识符error的目的是什么 2 | 3 | ``` 4 | #if __STDC_VERSION__ != 199901L 5 | #error Not C99 6 | #endif 7 | ``` 8 | 9 | + **编译程序时**:只要遇到 #error 就会跳出一个编译错误, 10 | + 既然是编译错误,要它干嘛呢?其目的就是保证程序是按照你所设想的那样进行编译的。 11 | + 用于判断#error所在的宏定义:**是否在使用** -------------------------------------------------------------------------------- /C/photo/memcpy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/C/photo/memcpy.png -------------------------------------------------------------------------------- /C/photo/operator_priority.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/C/photo/operator_priority.png -------------------------------------------------------------------------------- /C/photo/pointer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/C/photo/pointer.png -------------------------------------------------------------------------------- /C/photo/watch_dog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/C/photo/watch_dog.png -------------------------------------------------------------------------------- /C/单片机应用程序架构.md: -------------------------------------------------------------------------------- 1 | ## 单片机的架构 2 | 3 | ### 单片机的应用程序存放的位置? 4 | 5 | 1. 应用程序的机器码烧录在FLASH的ROM中; 6 | 2. 上电的时候,再将程序移到RAM中,加快运行速度; 7 | 8 | ### [单片机应用程序的三种架构](https://blog.csdn.net/DP29syM41zyGndVF/article/details/79864647) 9 | 10 | 1. 简单的前后台顺序执行程序 11 | + 前台:中断程序 12 | + 后台:顺序执行程序 13 | 2. 时间片轮询法 14 | + 此方法是介于顺序执行与操作系统之间的一种方法 15 | + 对一个程序加一个定时器; 16 | 3. 操作系统 17 | + 此法应该是应用程序编写的最高境界 -------------------------------------------------------------------------------- /C/如何写C嵌入式的死循环.md: -------------------------------------------------------------------------------- 1 | ## 如何写C嵌入式的死循环 2 | 3 | + 下面的三种代码:从汇编的角度来说,都是一样的代码。 4 | 5 | 1. for循环 6 | 7 | ``` 8 | for ( ; ; ) {} // 一般for(;;)性能更优; 这两个;; 空语句,编译器一般会优掉的,直接进入死循环 9 | ``` 10 | 11 | 2. while循环 12 | 13 | ``` 14 | while(1){} // 每循环一次都要判断常量1是不是等于零,在这里while比for多做了这点事 15 | ``` 16 | 17 | 3. goto 18 | 19 | ``` 20 | Loop: 21 | ... 22 | goto Loop; 23 | ``` 24 | 25 | -------------------------------------------------------------------------------- /C/指针和引用的区别.md: -------------------------------------------------------------------------------- 1 | ## C函数参数传递的三种方式 2 | 3 | | 区别 | 传值 | 传址 | 传引用 | 4 | | ---------------------- | ---- | -------------------------- | -------------------------- | 5 | | 本质 | | 参数的地址,想当于指针 | 参数的别名 | 6 | | 指针初始化后是否能改变 | | 指针地址可以改变 | 不能改变,不能改变的指针 | 7 | | 内存分配 | | 为指针分配内存区 | 不分配,**引用不能为空值** | 8 | | 级数限制 | | 指针无限制(指向指针的指针) | 只有一级 | 9 | | 是够可以改变原值 | 不能 | 可以 | 可以 | 10 | 11 | 12 | 13 | ### 三种传参方式 14 | 15 | 1. 方法一: 传值方式,不能实现交换 16 | 17 | + 形参是实参的**拷贝**,改变形参的值并不会影响外部实参的值 18 | + 参数只能传入, 不能传出; 19 | + 在传参过程中,首先将变量的值复制,然后在myswap函数中修改的即是函数的值,然后函数返回时,系统自动释放变量; 因此对原函数没有影响 20 | 21 | ``` 22 | // 方法一: 传值方式: 不能实现交换 23 | #include 24 | void myswap(int x, int y) 25 | { 26 | int t; 27 | t=x; 28 | x=y; 29 | y=t; 30 | } 31 | int main() 32 | { 33 | int a, b; 34 | printf("请输入待交换的两个整数:"); 35 | scanf("%d %d", &a, &b); 36 | myswap(a,b); //作为对比,直接交换两个整数,显然不行 37 | printf("调用交换函数后的结果是:%d 和 %d\n", a, b); 38 | return 0; 39 | } 40 | ``` 41 | 42 | 2. 方法二: 传址, 相当于传递指针的方式, 可以实现交换 43 | 44 | ``` 45 | // 方法二: 传址, 相当于传递指针的方式, 可以实现交换 46 | #include 47 | void myswap(int *p1, int *p2) 48 | { 49 | int t; 50 | t=*p1; 51 | *p1=*p2; 52 | *p2=t; 53 | } 54 | int main() 55 | { 56 | int a, b; 57 | printf("请输入待交换的两个整数:"); 58 | scanf("%d %d", &a, &b); 59 | myswap(&a,&b); //交换两个整数的地址 60 | printf("调用交换函数后的结果是:%d 和 %d\n", a, b); 61 | return 0; 62 | } 63 | ``` 64 | 65 | 3. 方法三: 传引用, **引用即别名**, 因此可以实现交换 66 | 67 | ``` 68 | // 方法三: 传引用, 引用即别名, 因此可以实现交换 69 | #include 70 | void myswap(int &x, int &y) //这里的形参为引用类型,引用与实参进行绑定,作为实参的别名 71 | { //所以,使用引用类型,传入实参后,函数对引用的操作, 72 | int t; //就是对实参的操作,所以实参会发生变化 73 | t=x; 74 | x=y; 75 | y=t; 76 | } 77 | 78 | int main() 79 | { 80 | int a, b; 81 | printf("请输入待交换的两个整数:"); 82 | scanf("%d %d", &a, &b); 83 | myswap(a,b); //直接以变量a和b作为实参交换 84 | printf("调用交换函数后的结果是:%d 和 %d\n", a, b); 85 | return 0; 86 | } 87 | ``` 88 | 89 | ### 指针和引用的区别 90 | 91 | 1. 指针和引用的区别? 92 | 93 | + 引用是别名,指针是地址 94 | + 指针在运行时可以改变所指向的值,而引用一旦与某个对象绑定后就不再改变。 95 | + **引用可以被认为是不能改变的指针** 96 | + 内存分配: 97 | + 程序为指针变量分配区域,而不为引用分配内存区域 98 | + **引用不能为空值** 99 | + 指针没有级数限制,但是引用只有一级 100 | + 有指向指针的指针 101 | 102 | ![pointer.png](https://github.com/quronghui/Embedded-written-reference/blob/master/C/photo/pointer.png) 103 | 104 | 105 | ### 为什么要使用指针呢? 106 | 107 | + 通过指针进行传参, 避免了数据变量的重复复制; 108 | + 能动态分配内存,实现内存的自由管理 109 | + 能方便的访问字符串 110 | 111 | -------------------------------------------------------------------------------- /C/看门狗程序的应用.md: -------------------------------------------------------------------------------- 1 | ## 看门狗定时器作用 2 | 3 | 1. 看门狗定时器防止溢出复位程序 4 | + 用来防止程序因供电电源、空间电磁干扰或其它原因引起的强烈干扰噪声而跑飞的事故。 5 | 2. 程序中设置看TL= WDTPW + WDTCNTCL 6 | + 当程序跑飞不能及时清零看门狗,导致看门狗溢出复位,这样程序可以恢复正常运行状态。 7 | 8 | ![watch_dog.png](https://github.com/quronghui/Embedded-written-reference/blob/master/C/photo/watch_dog.png) 9 | 10 | -------------------------------------------------------------------------------- /OS/ARM体系结构下的MMU如何实现映射.md: -------------------------------------------------------------------------------- 1 | ## ARM体系结构下的MMU如何实现映射 2 | 3 | 1. 创建内核页表,映射所有物理内存和IO空间,对于不同的处理器,该函数差别比较大。 4 | 5 | ``` 6 | paging_init(&meminfo, mdesc) 7 | ``` 8 | 9 | ### ARM下的MMU 10 | 11 | 1. 在ARM存储系统中,使用内存管理单元(MMU)实现虚拟地址到实际物理地址的映射。 12 | 2. 利用MMU 13 | + 可把**SDRAM**(动态RAM中的一种)的地址,完全映射到**0x0**起始的一片**连续地址**空间, 14 | + 而把原来占据这片空间的FLASH或者ROM映射到其他**不相冲突**的存储空间位置。 15 | 3. **通过MMU的映射,则可实现程序完全运行在SDRAM之中** 16 | + 在实际的应用中,可能会把两片不连续的物理地址空间分配给SDRAM。 17 | + 而在**操作系统**中,习惯于把SDRAM的空间连续起来,方便内存管理,且应用程序申请大块的内存时,操作系统内核也可方便地分配。 18 | + 通过MMU可实现不连续的物理地址空间映射为连续的虚拟地址空间。 19 | + 操作系统内核或者一些比较关键的代码,一般是不希望被用户应用程序访问。通过MMU可以控制地址空间的访问权限,从而保护这些代码不被破坏。 20 | 4. **MMU的实现过程,实际上就是一个查表映射的过程**。 21 | + 建立页表是实现MMU功能不可缺少的一步。 22 | + 页表位于系统的内存中,页表的每一项对应于一个虚拟地址到物理地址的映射。 23 | + 每一项的长度即是一个字的长度(在ARM中,一个字的长度被定义为4Bytes)。 24 | + 页表项除完成虚拟地址到物理地址的映射功能之外,还定义了访问权限和缓冲特性等。 25 | 5. **MMU的映射分为两种,一级页表的变换和二级页表变换** 26 | + 两者的不同之处就是实现的变换地址空间大小不同。 27 | + 一级页表变换支持1 M大小的存储空间的映射,而二级可以支持64 kB,4 kB和1 kB大小地址空间的映射。 28 | 29 | ### ARM通过几级页表实现存储空间映射 30 | 31 | 1. 采用的两级页表进行地址映射 32 | - 一级页表中:包含段为单位的地址变换条目或者指向二级页表的指针,一级页表实现地址的映射颗粒度较大; 33 | - 二级页表中:分为大页,小页,和极小页为单位的地址变换条目; -------------------------------------------------------------------------------- /OS/Bootloader.md: -------------------------------------------------------------------------------- 1 | # Bootloader和BIOS、uboot和grub和bootmgr的区别 2 | 3 | | 区别 | BIOS | Bootloader | U-boot | Grub | Bootmgr | 4 | | -------- | ------------------------------------ | ----------------------------------- | ------------------ | ------------------ | --------- | 5 | | 作用 | 初始化硬件,
不能引导OS内核 | 引导内核程序运行 | **通用Bootloader** | 引导不同的内核启动 | 同grub | 6 | | 程序位置 | ROM芯片上的程序 | RAM空间 | | RAM空间 | RAM空间 | 7 | | 程序运行 | 计算机的开启时
运行的第一个程序 | **内核运行前的程序** | | **选择**不同的内核 | **选择** | 8 | | | | Bootloader =
BIOS+Grub/Bootmgr | | 支持多操作系统 | windows下 | 9 | 10 | + BIOS :初始化硬件 11 | + Bootloader:引导内核程序的运行; 12 | + Grub / Bootmgr 在不同的平台下选择不同的内核运行 13 | 14 | ## BIOS 15 | 16 | 1. BIOS(Basic Input Output System):基本输入输出系统; 17 | + 它是一组固化到计算机内主板上一个**ROM芯片上的程序** ,**保存着计算机最重要的基本输入输出的程序、开机后自检程序和系统自启动程序**,它可从CMOS中读写系统设置的具体信息。 18 | + BIOS是连接软件与硬件的一座“桥梁”,是**计算机的开启时运行的第一个程序**,主要功能是为计算机提供最底层的、最直接的**硬件设置和控制**。 19 | 20 | ### BIOS 的三个功能 21 | 22 | 1. **自检及初始化程序**,分为三个部分。 23 | + 加电自检(POST):功能是检查计算机**硬件是否良好**,自检中如发现有错误,将按两种情况处理:对于严重故障(致命性故障)则**停机**,此时由于各种初始化操作还没完成,不能给出任何提示或信号;对于非严重故障则给出提示或声音**报警信号**,等待用户处理。 24 | + 初始化:创建中断向量、设置寄存器、对一些外部设备进行初始化和检测等,其中很重要的一部分是BIOS设置,主要是对**硬件设置的一些参数**,当计算机启动时会读取这些参数,并和实际硬件设置进行比较,如果不符合,会影响系统的启动。 25 | + 加载引导程序:功能是引导Dos或其他操作系统,此时会在硬盘读取引导记录,然后把计算机的控制权转交给引导记录,由**引导记录**(IPL与SPL)把操作系统装入电脑,在电脑启动成功后,BIOS的这部分任务就完成了。**也就是说BIOS本身不能引导OS内核。** 26 | 2. **程序服务处理** 27 | + BIOS直接与计算机的I/O设备(Input/Output,即输入/输出设备)打交道, 28 | + 通过特定的数据端口发出命令,传送或者接受各种外部设备的数据,实现**软件程序对硬件的直接操作**。 29 | 3. **硬件中断处理**;开机时BIOS会告诉CPU各硬件设备的中断号,当用户发出使用某个设备的指令后,CPU就根据中断号使用相对应的硬件完成工作,再根据中断号跳回原来的工作。 30 | 31 | ### 两种BIOS 32 | 33 | ``` 34 | BIOS分为:Legacy BIOS 和 UEFI BIOS 35 | ``` 36 | 37 | ## Bootloader 38 | 39 | 1. Bootloader:引导加载程序(bootloader)完成比BIOS更多的功能 40 | + 嵌入式系统中:**Bootloader运行之后,操作系统内核才运行**; 41 | + 可以分为单阶段的BootLoader和多阶段的BootLoader,一般从从**固态存储**设备上启动的Bootloader大多都是 2 阶段的启动过程 42 | + 如uboot是2阶段的,grub就是单阶段的; 43 | 44 | ### Bootloader两个阶段功能 45 | 46 | 1. Bootloader第一阶段的功能 47 | 48 | + 硬件设备初始化。 49 | + 为加载Bootloader的第二阶段代码准备RAM空间。 50 | + 拷贝Bootloader的第二阶段代码到 RAM 空间中。 51 | + 设置好栈。 52 | + **跳转**到第二阶段代码的C入口点。 53 | + 在第一阶段进行的硬件初始化一般包括:关闭WATCHDOG、关中断、设置CPU的速度和时钟频率、RAM初始化等。 54 | 55 | 2. Bootloader第二阶段的功能 56 | 57 | + 初始化本阶段要使用到的硬件设备 58 | + 检测系统内存映射(memory map) 59 | + 将内核映像和根文件系统映像从Flash上读到RAM空间中。 60 | 61 | + **为内核设置启动参数**。 62 | + **调用内核**。 63 | 64 | ## 不同平台的引导加载程序 65 | 66 | ### PC平台的Grub与 bootmgr 67 | 68 | 1. GNU GRUB(GRand Unified Bootloader简称“GRUB”) 69 | + 是一个来自GNU项目的多操作系统启动程序。 70 | + GRUB是多启动规范的实现:它允许用户可以在计算机内同时**拥有多个操作系统**,并在计算机启动时**选择运行的操作系统** 71 | + GRUB可用于选择操作系统分区上的不同内核,也可用于向这些内核传递启动参数 72 | + 可用来用来引导不同系统,如windows,linux,通常用于linux,毕竟是GNU的嘛 73 | 2. Windows也有类似的工具NTLOADER、Bootmgr 74 | 75 | ### 嵌入式平台 76 | 77 | 1. U-Boot,全称为Universal Boot Loader,即通用Bootloader 78 | 2. 改名为U-Boot。 79 | - 支持多种嵌入式操作系统内核,如Linux、NetBSD、VxWorks、QNX、RTEMS、ARTOS、LynxOS; 80 | - 支持多个处理器系列,如PowerPC、ARM、x86、MIPS、XScale; -------------------------------------------------------------------------------- /OS/JTag用途.md: -------------------------------------------------------------------------------- 1 | ## JTag用途 2 | 3 | 1. JTag用途 4 | + 用于调试和下载程序 5 | + JTAG来实现调试/仿真功能, 6 | + 所有的FPGA和CPLD都利用JTAG来实现下载程序功能 7 | 2. JTag用途另外的用途 8 | + JTAG / 边界扫描是如何用于测试一个板的 9 | 10 | -------------------------------------------------------------------------------- /OS/Linux中断之间区别.md: -------------------------------------------------------------------------------- 1 | ## Linux中断信号源 2 | 3 | ### 硬件中断和软件中断 4 | 5 | | 中断区别 | 硬件中断 | 软件中断 | 6 | | ----------- | ------------------------- | ---------------------------------------------------- | 7 | | 中断源产生 | 硬件外设 | 执行中断指令 | 8 | | 中断号提供 | 中断控制器 | 由指令直接指出 | 9 | | 可屏蔽 | 可屏蔽 | 不可屏蔽 | 10 | | ISR中断分层 | 上半部分ISR: 需要快速完成 | 下半部ISR, 通过软中断完成 | 11 | | | | 软中断: 处理硬中断未完成的工作, 是一种推后执行的机制 | 12 | 13 | 1. 硬件中断 14 | + 硬件外设: 由与系统相连的外设(比如网卡 硬盘 键盘等)自动产生 15 | + 每个设备或设备集都有他自己的IRQ(中断请求), 基于IRQ 16 | + CPU可以将相应的**请求**分发到相应的**硬件驱动**上 17 | + 硬件驱动通常是内核中的一个子程序, 而不是一个独立的进程 18 | + **处理中断的驱动**: 是需要运行在CPU上的, 当中断产生时, CPU会暂时停止当前程序的程序转而执行中断请求; 19 | 2. 软件中断 20 | + 不会直接中断CPU, 当前正在运行的代码(或进程)才会产生软中断; 21 | + 软中断: 是一种需要内核为正在运行的进程去做一些事情(通常为I/O)的请求; 22 | 23 | ### 软中断和硬中断 24 | 25 | | 区别 | 软中断 | 硬中断 | 信号 | 26 | | -------- | ------------------------------------------ | ----------------------- | ------------------------------------------ | 27 | | 中断类型 | **硬中断服务程序**(下半部)对**内核**中断 | 外部设备对**CPU**的中断 | 是由**内核**(或进程)对某个**进程**的中断 | 28 | | 抢占 | 软中断之间**不抢占**,保证严格的时间要求 | 发生**抢占** | | 29 | | | 软中断的服务程序:执行上下文为软中断daemon | | | 30 | 31 | 1. 软中断(ISR下半部分的中断) 32 | + 概念: 用软件方式模拟硬件中断的概念,实现宏观上的**异步**执行效果, 类似于信号; 33 | + 软中断的一种典型应用就是所谓的"**下半部**"(bottom half): 它的得名来自于将硬件中断处理分离成"上半部"和"下半部"两个阶段的机制: 34 | 2. 软中断和函数调用区别? 35 | + 函数调用时将返回地址和CPU状态寄存器内容压栈,函数执行完毕后出栈返回断点继续执行。 36 | + 软中断调用时将返回地址和CPU状态寄存器内容压栈,**修改特权级**,根据**中断号查找中断向量表**,找到ISR中断服务例程地址,跳转执行。 37 | + **函数调用和软中断调用的区别**: 软中断多了修改特权级和查找中断向量表的功能,其他部分完全一样。 38 | -------------------------------------------------------------------------------- /OS/Linux中断分层的概念.md: -------------------------------------------------------------------------------- 1 | ## Linux 中断分层的概念 2 | 3 | ### Linux中断嵌套处理 4 | 5 | 1. Linux中断嵌套概念 6 | + 当一种类型的中断发生时, 又产生另外一种中断; 7 | 2. 慢速中断: 处理ISR函数时, **中断总开关不关闭**, 允许其他中断发生 8 | + 不同中断设备: 发生另外中断,**执行新的中断**,执行完成; 返回之前的中断处理函数继续执行 9 | + 相同类型设备: 发生另外中断,**忽略**发生的中断,继续执行之前的中断函数,造成中断丢失; 10 | 3. 快速中断: 处理ISR函数时, **中断总开关关闭**,不接受外部中断 11 | + 不同中断设备 : **忽略**发生的中断 12 | + 相同类型设备: **忽略**发生的中断 13 | 14 | ### Linux 中断分层的原因 15 | 16 | 1. Linux 中断分层 17 | + 概念 : 将中断ISR分为前后两部分, 第一部分在中断函数中执行,第二部使用中断分层技术隔离出来。 18 | 19 | + 原因:ISR的执行并不存在于进程的上下文切换中, 要求ISR要尽可能短; 20 | 21 | ![interrupt_reason.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/interrupt_reason.png) 22 | 23 | + 作用: 减少中断处理函数执行时间,减少中断丢失的概率 24 | 25 | ### 实现中断下半部 26 | 27 | | 机制 | 软中断 | tasklet | 工作队列 | 28 | | -------- | --------------------------------------------- | -------------------------------------- | -------------------------------------- | 29 | | 运行状态 | 不允许睡眠,阻塞 | 运行于**中断上下文**,不允许阻塞和休眠 | 运行与**进程上下文**,可以休眠和阻塞。 | 30 | | 多核执行 | 支持多核,同一软中断可以在不同CPU**并发执行** | 同一个tasklet只能在一个CPU执行 | | 31 | | 分配方式 | 静态分配(不能改变) | 运行时改变 | | 32 | | 调度函数 | | tasklet_schedule(); | schedule_work(); | 33 | 34 | + tasklet是在软中断类型的基础上实现,因此如果不需要软中断的并行特性,tasklet就是最好的选择。 35 | + 也就是说tasklet是软中断的一种特殊用法,即**延迟情况下的串行执行** 36 | 37 | 3. 软中断 38 | + 不同于软件中断 39 | + 软中断发生: 是从中断、调用或者异常返回用户空间之前; 40 | + 执行顺序: 按照软中断在结构数组中定义的**顺序**依次执行; 41 | + 同一个软中断可以在不同CPU上**并发执行**, 软中断执行过程中**不允许睡眠和进程切换;** 42 | 2. tasklet 43 | + 基于软中断实现,在软中断结构数组中占用两项 44 | + 当中断执行到这两项时, 就会跳转到tasklet函数入口处,依次执行队列中的tasklet函数 45 | + 同一个tasklet**不能**在不同CPU上并发执行,但是不同tasklet可以在不同CPU上执行 46 | 3. 工作队列 47 | + 是一种将任务推后执行的形式,他把推后的任务交由一个**内核线程**去执行 48 | + 中断函数的第二部分会在进程上下文执行,它允许**重新调度甚至睡眠**。 49 | + 每个被推后的任务叫做“工作”,由这些工作组成的队列称为工作队列; 50 | 51 | ### Linux 软中断实现的原理 52 | 53 | 1. 构成软中断机制的核心元素包括: 54 | 55 | - 软中断状态寄存器soft interrupt state(irq_stat) 56 | - 软中断向量表(softirq_vec): 不同的中断号有不同的终端入口地址; 57 | - 软中断守护daemon 58 | 59 | 2. **软中断如何模拟:硬件中断?** 60 | 61 | - 当某一软中断事件发生:首先需要**设置**对应的**中断标记位**,触发中断事务(raise_softirq():设置软中断状态bitmap,触发软中断事务) 62 | 63 | - 然后唤醒**守护线程**:去检测中断状态寄存器; 64 | 65 | ``` 66 | do_softirq(); //在Linux中 软中断daemon线程函数 67 | ``` 68 | 69 | - 如果查询:发现某一软中断事务发生之后,那么通过软**中断向量表**调用软中断服务程序action() 70 | 71 | 3. 软中断模拟硬件中断的区别在哪里? 72 | 73 | - 区别:从**中断标记** ----> 中断服务程序 的映射过程 74 | - 硬件中断:CPU从硬件中断发生后,将中断请求通过向量表映射成具体的服务程序,过程是硬件自动完成,硬件主动提供ISR入口地址; 75 | - 软中断:需要**守护线程**去实现这一过程 76 | 77 | -------------------------------------------------------------------------------- /OS/Linux中的RCU.md: -------------------------------------------------------------------------------- 1 | ## Linux中的RCU原理 2 | 3 | 1. RCU(Read-Copy Update) 4 | + 数据同步的一种方式 5 | + RCU适用于需要频繁的**读**取数据,而相应**写**数据并不多的情景 6 | + 例如在文件系统中:经常需要查找定位目录,而对目录的修改相对来说并不多 7 | 2. RCU实现**链表**中数据的读取 8 | + 目的:提高链表遍历**读取数据**的效率; 9 | + 方法:在读取数据时,不加锁,内存屏障,原子指令类开销,几乎是直接读; 10 | 3. RCU实现**链表**中数据的写操作 11 | + **允许一个线程对链表进行修改(修改的时候,需要加锁)** 12 | 13 | ### RCU实现过程中,需要解决的问题 14 | 15 | 1. 在读取过程中,另外一个线程**删除**了一个节点 16 | + 删除线程可以把这个节点从链表中移除,但它不能直接销毁这个节点; 17 | + 必须等到**所有的读取线程**读取完成以后,才进行销毁操作。 18 | + RCU中把这个过程称为宽限期(Grace period)。 19 | 2. 在读取过程中,另外一个线程**插入**了一个新节点 20 | + 而读线程读到了这个节点,那么需要**保证**读到的这个节点是**完整**的。 21 | + 这里涉及到了发布-订阅机制(Publish-Subscribe Mechanism) 22 | 3. 保证读取链表的**完整性** 23 | + 新增或者删除一个节点,不至于导致遍历一个链表从中间断开。 24 | + 但是RCU并**不保证**一定能读到新增的节点或者不读到要被删除的节点。 -------------------------------------------------------------------------------- /OS/Linux内核启动流程.md: -------------------------------------------------------------------------------- 1 | ## Linux内核启动流程 2 | 3 | ### Bootloader 启动 4 | 5 | ![bootloader.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/bootloader.png) 6 | 7 | ### Linux Kernel 启动 8 | 9 | ![linux_kernel_start.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/linux_kernel_start.png) 10 | 11 | ### kernel 启动分为三步 12 | 13 | 1. 内核先执行一个文件head-armv.S 14 | 15 | + 作用: 检查CPU ID, Architecture Type,初始化BSS等操作,并跳到start_kernel函数 16 | 17 | ``` 18 | arch/arm/kernel/head-armv.S 19 | ``` 20 | 21 | ``` 22 | r0 - should be 0 // 寄存器关闭 23 | r1 - unique architecture number 24 | MMU - off 25 | I-cache - on or off 26 | D-cache – off 27 | ``` 28 | 29 | 2. ENTRY(stext)启动源码分析 30 | 31 | ``` 32 | /* 部分源代码分析 */ 33 | /* 内核入口点 */ 34 | ENTRY(stext) 35 | /* 程序状态,禁止FIQ、IRQ,设定SVC模式 */ 36 | mov r0, #F_BIT | I_BIT | MODE_SVC@ make sure svc mode 37 | /* 置当前程序状态寄存器 */ 38 | msr cpsr_c, r0 @ and all irqs disabled 39 | /* 判断CPU类型,查找运行的CPU ID值与Linux编译支持的ID值是否支持 */ 40 | bl __lookup_processor_type 41 | /* 跳到__error */ 42 | teq r10, #0 @ invalid processor? 43 | moveq r0, #'p' @ yes, error 'p' 44 | beq __error 45 | /* 判断体系类型,查看R1寄存器的Architecture Type值是否支持 */ 46 | bl __lookup_architecture_type 47 | /* 不支持,跳到出错 */ 48 | teq r7, #0 @ invalid architecture? 49 | moveq r0, #'a' @ yes, error 'a' 50 | beq __error 51 | /* 创建核心页表 */ 52 | bl __create_page_tables 53 | adr lr, __ret @ return address 54 | add pc, r10, #12 @ initialise processor 55 | /* 跳转到start_kernel函数 */ 56 | b start_kernel 57 | ``` 58 | 59 | 3. [start_kernel()源码详解](https://www.linuxidc.com/Linux/2014-10/108034.htm) -------------------------------------------------------------------------------- /OS/Linux内核和用户程序运行在物理地址还是虚拟地址.md: -------------------------------------------------------------------------------- 1 | ## CPU , Cache,MMU ,内存之间的关系? 2 | 3 | ![MMU_cache.png](/OS/photo/MMU_cache.png) 4 | 5 | ### MMU的有无 6 | 7 | 1. 带有MMU的系统: 8 | + linux 内核和用户程序都运行在虚拟地址模式; 9 | 10 | 2. 没有MMU的系统 11 | + 用户空间和内核空间是不做区分的; 12 | + 不能使用处理器的虚拟内存管理技术; -------------------------------------------------------------------------------- /OS/Linux内核的五个模块描述.md: -------------------------------------------------------------------------------- 1 | ## [Linux内核的五个子系统](https://blog.csdn.net/xiaomage_307_/article/details/79117881) 2 | 3 | + 进程调度模块、内存管理模块、文件系统模块、进程间通信模块、网络接口模块。 4 | 5 | 1. 进程调度模块(SCHED) 6 | 7 | + 作用:用来负责控制系统中的多个进程对CPU的访问;多个进程能在CPU中“微观串行,宏观并行”地执行; 8 | + 采用多级反馈队列的策略 + 时间片轮转RR + 进程上下文的切换; 9 | + 地位:进程调度处于系统的**中心位置**,内核中其他的子系统都**依赖**它,因为每个子系统都需要**挂起或恢复进程** 10 | 11 | 2. 内存管理模块(MM) 12 | 13 | + 作用:是控制多个进程安全地**共享**主内存区域 14 | + MMU:完成虚拟内存到物理内存的转换 15 | + 内存的管理:分页式管理,Linux下每页是4kb; 16 | 17 | 3. 虚拟文件系统(VFS) 18 | 19 | ![VFS_kernel.png](/OS/photo/VFS_kernel.png) 20 | 21 | + 作用: 22 | + **隐藏**各种了硬件的具体细节,为所有的设备提供了统一的**接口** 23 | + **独立**于各个具体的文件系统,是对各种文件系统的一个**抽象** 24 | + 三部分: 25 | + 超级块super block:存放文件系统相关信息 26 | + 索引节点inode:存放文件的物理信息 27 | + 目录项dentry存放文件的逻辑信息 28 | 29 | 4. 网络接口 30 | 31 | + 作用:提供对多种网络通信标准的访问并支持许多网络硬件 32 | 33 | 5. 进程间通信 34 | 35 | + 作用:用于支持多种进程间的信息交换方式; 36 | + Linux支持进程间的多种通信机制,包含信号量、共享内存、管道等,这些机制可协助多个进程、多资源的互斥访问、进程间的同步和消息传递。 37 | 38 | ### 子系统之间的依赖关系 39 | 40 | 1. 进程调度和内存管理: 41 | + 相互**依赖**关系; 42 | + 程序要运行必须为之创建进程,而创建进程的第一件事情,就是将程序和数据装入内存。 43 | 2. 进程间通信和内存管理: 44 | + 进程间通信子系统要依赖内存管理支持共享**内存通信机制**; 45 | + 这种机制允许两个进程除了拥有自己的私有空间,还可以存取共同的内存区域。 46 | 3. 虚拟文件系统和网络接口 47 | + 虚拟文件系统:利用网络接口**支持**网络文件系统(NFS),也利用内存管理支持RAMDISK设备。 48 | 4. 内存管理和虚拟文件系统 49 | + 内存管理利用虚拟文件系统支持交换,交换进程(swapd)定期由调度程序调度,这 也是内存管理依赖于进程调度的惟一原因 50 | + 当一个进程存取的内存映射被换出时,内存管理向文件系统发出请求,同时,挂起当前正在运行的进程。 51 | 5. 内核中的所有子系统还要依赖于一些共同的资源,如分配和释放内存空间的函数、打印警告或错误信息的函数及系统提供的调试例程等。 -------------------------------------------------------------------------------- /OS/Linux字符驱动和块驱动模型.md: -------------------------------------------------------------------------------- 1 | ## Linux字符驱动和块驱动模型 2 | 3 | ### 字符驱动和块驱动的区别 4 | 5 | | 区别 | 字符驱动 | 块驱动 | 6 | | -------- | ---------------------- | ---------------------------------- | 7 | | 硬件 | 鼠标、键盘、摄像头 | u盘,SD卡,磁盘 | 8 | | 数据提供 | 提供字符流数据 | 数据块(512byte) | 9 | | 数据访问 | 顺序 | 支持偏移访问过lessk | 10 | | 寻址方式 | 字符寻址 | 不支持字符寻址 | 11 | | 结构体 | cdev, file_opeartions | gendisk, block_device_operation | 12 | | 函数 | open,close,read和write | 无读写的操作函数 | 13 | | | | bio, request, request_queue 结构体 | 14 | 15 | + 符设备和块设备的区别:仅仅在于内核内部管理数据的方式,也就是内核及驱动程序之间的软件接口,而这些不同对用户来讲是**透明**的。 16 | + 在内核中,和字符驱动程序相比,块驱动程序具有完全不同的接口。 17 | 18 | ### 字符设备驱动程序框架 19 | 20 | ![driver_enter.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/driver_enter.png) 21 | 22 | 1. 字符设备的注册 23 | + init函数注册设备,建立设备节点 24 | + 通过module_init宏来保证加载模块时会调用init函数。 25 | 2. 字符设备操作 26 | + 调用file_operation结构体的open、read、write函数 27 | 3. 总线模型和字符模型区别 28 | + probe函数跟init函数的区别 29 | + 使用平台总线模型时,才使用probe函数 30 | + 平台总线设备驱动模时 31 | + init函数只是向总线设备列表中添加了设备, 32 | + 当检测到相同名字的驱动程序,probe函数就会接着init函数的工作完成设备注册 33 | 34 | ### 块设备驱动系统架构: 35 | 36 | ![mtd_struct.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/mtd_struct.png) 37 | 38 | -------------------------------------------------------------------------------- /OS/Linux抽象出framebuffer这个设备的作用.md: -------------------------------------------------------------------------------- 1 | ## Linux抽象出framebuffer这个设备的作用 2 | 3 | 1. Linux抽象出FrameBuffer这个设备来供用户态进程实现直接写屏。 4 | 2. Framebuffer机制模仿显卡的功能,将显卡硬件结构抽象掉,可以通过Framebuffer的读写直接对显存进行操作。 5 | 3. 用户可以将Framebuffer看成是显示内存的一个映像,通过mmap将其映射到进程地址空间之后,就可以直接进行读写操作,而写操作可以立即反应在屏幕上 6 | 4. 用户不必关心物理显存的位置、换页机制等等具体细节,这些都是由Framebuffer设备驱动来完成的。通过mmap调用把显卡的物理内存空间映射到用户空间 -------------------------------------------------------------------------------- /OS/Linux系统调用函数copy_from_user.md: -------------------------------------------------------------------------------- 1 | ## copy_to_user 、copy_from_user函数 2 | 3 | | 区别 | copy_to_user() | copy_from_user() | 4 | | -------------------- | ------------------------------------------------------------ | ----------------------------------------------------------- | 5 | | **系统调用**中的函数 | 将**内核空间**的数据复制到 --> 用户空间 | 将**用户空间**的数据复制到 -->内核空间 | 6 | | 返回值 | 成功返回0
失败返回没有拷贝成功的数据**字节数** | 同左 | 7 | | | access_ok(); 检测用户空间缓存区的合法性, 才能进行读写; | | 8 | | | | | 9 | | **内核**中的函数 | put_user(data, ptr) | get_user(data, ptr) | 10 | | 作用 | 将**内核空间**的变量data中的数值,保存到到用户空间指定的ptr处 | 获取**用户空间**指定地址ptr中的数值,并保存到内核变量data中 | 11 | | 返回值 | 成功返回0,不成功返回非0 | | 12 | 13 | ### 函数详解 14 | 15 | 1. copy_from_user() 16 | 17 | ``` 18 | unsigned long copy_from_user(void *to, const void *from, unsigned long n); 19 | // to: 目标地址 -- 内核空间 20 | // from: 源地址 -- 用户空间 21 | // n:就是拷贝的字节数 22 | ``` 23 | 24 | + 将用户空间中的n个数据拷贝到内核空间; 25 | + 成功返回0,失败返回没有拷贝成功的数据**字节数** 26 | 27 | 2. get_user宏 28 | 29 | ``` 30 | int get_user(data, ptr); 31 | // data: 可以是字节、半字、字、双字类型的内核变量 32 | // ptr:用户空间的内存指针; 33 | ``` 34 | 35 | + 成功返回0,失败返回非0 36 | + 获取用户空间指定地址ptr中的数值,并保存到内核变量data中 37 | 38 | 3. copy_to_user() 39 | 40 | ``` 41 | unsigned long copy_to_user(void *to, const void *from, unsigned long n) 42 | // to:目标地址 -- 用户空间 43 | // from:源地址 -- 内核空间 44 | // n:就是拷贝的字节数 45 | ``` 46 | 47 | + 将内核空间中的n个数据拷贝到用户空间; 48 | + 成功返回0,失败返回没有拷贝成功的数据字节数 49 | 50 | 4. put_user宏: 51 | 52 | ``` 53 | int put_user(data, prt) 54 | // data: 可以是字节、半字、字、双字类型的内核变量 55 | // ptr:用户空间的内存指针; 56 | ``` 57 | 58 | + 成功返回0,失败返回非0 59 | + 将内核空间的变量data中的数值,保存到到用户空间指定的ptr处。 60 | 61 | ### copy_from_user() 函数和memcpy()的区别 62 | 63 | 1. 崩溃影响? 64 | 65 | + 用户空间的进程崩溃:不会影响系统的其它进程; 66 | + 系统内核崩溃:就什么都结束了 67 | 68 | 2. memcpy 69 | 70 | ``` 71 | void *memcpy(void *dest, const void *src, size_t n); 72 | ``` 73 | 74 | 3. copy_from_user() 75 | 76 | + access_ok(); 检测用户空间缓存区的合法性, 才能进行读写; 77 | + 如果直接用memcpy操作,进入缺页异常处理,因为无法进行修复,导致**内核崩溃** -------------------------------------------------------------------------------- /OS/Linux虚拟文件系统的关键数据结构有哪些.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## linux[虚拟文件系统](https://www.baidu.com/s?wd=虚拟文件系统&tn=SE_PcZhidaonwhc_ngpagmjz&rsv_dl=gh_pc_zhidao)核心数主要有以下几个数据结构: 4 | 5 | * 超级块结构(struct super_block {...} ) 6 | 该结构保存了一个被安装在[linux系统](https://www.baidu.com/s?wd=linux系统&tn=SE_PcZhidaonwhc_ngpagmjz&rsv_dl=gh_pc_zhidao)上的文件系统的信息。对于基于磁盘的文件系统,该结构一般和保存在磁盘上的"文件系统控制块"对应。也就是说如果是磁盘文件系统,该结构保存的**磁盘文件系统的控制信息**。 7 | * inode结构( struct inode {...} ) 8 | 该结构中存储的是一个特定文件的一般信息,对于一个基于磁盘的文件系统,该结构对应磁盘上的"文件数据控制块"。每一个inode结构都对应一个**inode节点号**,这个节点号是唯一的,**它也唯一标识一个文件系统中的文件**。 9 | * file结构( struct file {...} ) 10 | 该结构中存储的是**一个打开的文件和打开这个文件的进程间的交互信息**。该结构保存在kernel的内存区,在打开文件时被创建,关闭文件时被释放。 11 | * dentry结构( struct dentry {...} ) 12 | 该结构存储的是**目录实体和对应的文件的关联信息**。 13 | 14 | ## Linux是通过什么组件来实现支持多种文件系统? 15 | 16 | 1. VFS--虚拟文件系统 17 | + 采用标准的Unix系统调用读写位于不同物理介质上的不同文件系统。 18 | + 通过VFS:一个抽象的通用访问接口屏蔽了底层文件系统和物理介质的差异性。 19 | + VFS是一个可以让open()、read()()、write()等系统调用不用关心底层的存储介质和文件系统类型就可以工作的粘合层。 20 | 2. 在古老的[DOS操作系统](https://www.baidu.com/s?wd=DOS操作系统&tn=SE_PcZhidaonwhc_ngpagmjz&rsv_dl=gh_pc_zhidao)中 21 | + 要访问本地文件系统之外的文件系统需要使用特殊的工具才能进行。 22 | 23 | ## 对文件和设备的操作函数保存在哪个数据结构中 24 | 25 | ``` 26 | struct file_operations{ 27 | 28 | } 29 | ``` 30 | 31 | -------------------------------------------------------------------------------- /OS/Linux进程上下文切换和中断上下文切换.md: -------------------------------------------------------------------------------- 1 | ## Linux进程上下文切换和中断上下文切换 2 | 3 | | 区别 | 进程上下文切换 | 中断上下文切换 | 4 | | ---------- | ------------------------------------------ | --------------------------------------------------- | 5 | | 引发原因 | 进程进行**系统调用** | 硬件触发信号, 导致内核调用ISR | 6 | | 状态切换 | 用户态 -- > 内核态(**进程**运行于内核空间) | 用户态 -- > 内核态(**硬件**运行于内核空间) | 7 | | 保存现场 | 进程的三部分内容都切换 | 内核保存**硬件传递的参数** 和 被中断程序相关寄存器; | 8 | | 切换区别 | 进程切换 | 程序中止, 和特定进程无关 | 9 | | 抢占 | 可抢占 | 不可抢占 | 10 | | | 不可能同时发生 | | 11 | | 切换的内容 | 用户级/寄存器/系统级 | 相关寄存器入栈 | 12 | 13 | ### Linux缺页中断和中断区别 14 | 15 | | 区别 | 缺页中断 | 中断 | 16 | | -------- | ------------------------------------------- | ------------------------ | 17 | | 产生原因 | CPU访问的页不存在与内存中,需要去外存中读取 | 内/外部事件触发 | 18 | | 中断次数 | 一条指令在执行期间:可能产生多次缺页中断 | 一条指令,产生一次中断 | 19 | | 中断返回 | 执行产生中断的那一条指令 | 执行中断发生的下一条指令 | 20 | 21 | -------------------------------------------------------------------------------- /OS/Linux驱动模型platform.md: -------------------------------------------------------------------------------- 1 | ## Linux驱动模型platform 2 | 3 | 1. Linux加入了一套驱动管理和注册机制 4 | + platform平台总线驱动模型。 5 | 2. 内核中的设备: 需要设备号, 通过注册得到; 6 | 7 | ### platform平台总线 8 | 9 | 1. platform平台总线是一条虚拟总线 10 | 11 | + platform_device为相应的设备 12 | + platform_driver为相应的驱动 13 | 14 | 2. 与传统的bus/device/driver机制相比,platform由内核统一进行管理;提高了代码的可移植性和安全性 15 | 16 | 3. Linux总线设备驱动模型的框架 17 | 18 | ![platform.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/platform.png) 19 | 20 | + 总线、设备和驱动这3个实体,同时总线将设备和驱动**绑定** 21 | + match() : 进行匹配 22 | + probe(): 进行绑定 23 | + platform_driver_register 24 | + 将驱动程序注册到总线,并将其放入所属总线的drv链表中 25 | + 调用所属总线的match函数 : 寻找该总线上与之匹配的每一个设备, 26 | + probe函数 : 将相应的设备和驱动进行绑定 27 | + platform_device_register 28 | + 将设备注册到总线,并将其放入所属总线的dev链表中 29 | + 调用所属总线的**match函数**: 寻找该总线上与之匹配的每一个驱动程序, 30 | + **probe函数**: 将相应的设备和驱动进行绑定 31 | 32 | ### match()是如何进行匹配的 33 | 34 | 1. platform_device 和 platform_driver匹配的四种可能性? 35 | + 基于设备树风格匹配 36 | + 基于ACPI风格匹配 37 | + 匹配ID表(platform_device设备名是否出现在platform_driver的ID表内) 38 | + 匹配 platform_device设备名和驱动名字 39 | -------------------------------------------------------------------------------- /OS/MIPScpu地址空间划分.md: -------------------------------------------------------------------------------- 1 | ## MIPS cpu地址空间划分 2 | 3 | 1. 4 | -------------------------------------------------------------------------------- /OS/OS信号量互斥体自旋锁的概念.md: -------------------------------------------------------------------------------- 1 | ## Linux中的锁 2 | 3 | | 锁的机制 | 自旋锁 | 互斥锁 | 读写锁 | RCU | 顺序锁 | 4 | | -------- | ------------------------------------------ | -------------------- | -------------- | ----------------------------------- | ------------------ | 5 | | lock | spinlock | mutexlock | rwlock | Read-Copy Update | seqlock | 6 | | 特性 | 循环-旋转-等待锁
忙等待 | 睡眠等待和唤醒 | 区分读和写 | 允许多个读-不加锁;
写需要加锁 | 对读写锁的一种优化 | 7 | | 缺陷 | 自旋锁一直占用着CPU | 进程会睡眠 | 只允许一种状态 | | | 8 | | | 阻塞等待,造成死锁:
copy_to_user()等 | | | | | 9 | | 适用于 | 保持锁的时间较短的情况下 | 防止资源读写竞争关系 | | 多个读,少量写 | | 10 | 11 | ### 互斥锁 12 | 13 | 1. 互斥体禁止多个线程同时进入受保护的代码“临界区”. 14 | 2. 在任意时刻,只有一个线程被允许进入这样的代码保护区。 15 | 3. 任何线程在进入临界区之前 16 | + 必须获取(acquire)与此区域相关联的互斥体的所有权。 17 | + 如果已有另一线程拥有了临界区的互斥体,其他线程就不能再进入其中。 18 | + 这些线程必须等待,直到当前的属主线程释放(release)该互斥体 19 | 4. 什么时候需要使用互斥体呢? 20 | + 互斥体用于保护共享的易变代码, 21 | + 也就是,全局或静态数据。 22 | 23 | ### 自旋锁 24 | 25 | 1. 它是为实现保护共享资源而提出一种锁机制。 26 | 2. 自旋锁与互斥锁相同点? 27 | + 它们都是为了解决对某项资源的互斥使用。 28 | + 在任何时刻最多只能有一个执行单元获得锁。 29 | 3. 自旋锁与互斥锁不同点? 30 | + 两者在调度机制上略有不同。 31 | + 对于互斥锁,如果资源已经被占用,资源申请者只能进入**睡眠状态**。 32 | + 自旋锁: 调用者就一直循环, 等待锁的释放; 33 | -------------------------------------------------------------------------------- /OS/OS同步机制的实现.md: -------------------------------------------------------------------------------- 1 | ## [四种进程或线程同步互斥的控制方法](https://blog.csdn.net/bao_qibiao/article/details/4516196) 2 | 3 | | 区别 | 临界区 | 互斥量 | 信号量 | 事件 | 管程 | 4 | | ------------ | ------------------------------ | ---------------------------------------- | ------------------------------------------- | ---------------- | ---------------------------- | 5 | | 目的 | 原子操作 | 共享资源互斥 | 共享资源同步 | 同步 | 同步 | 6 | | 访问数据 | 任意时刻只有**一个线程**能访问 | 任意时刻只有**一个线程**能访问 | 多个线程同时 | **等待**事件发生 | 同一时刻只允许**一个**访问者 | 7 | | 多个线程 | **挂起** | | 睡眠等待 | | | 8 | | 临界区释放 | **抢占** | | 按队列调度 | | | 9 | | 操作原语 | 进入/离开 临界区 | 创建/打开/释放/等待 | 同左 | 同左 | | 10 | | MFC提供 | lock/unlock | CMutex | sem_wait/sem_post | Event | | 11 | | **作用范围** | 同一进程的不同线程 | 同一进程的不同线程
跨进程的线程之间 | 不同进程的多个线程
同一进程的多个线程 | 跨进程 | 优化信号量; | 12 | 13 | 1. 同步和互斥? 14 | - 互斥:对于某一资源,同一时间只能由一个任务进行访问; 15 | - 同步:B任务的执行需要A任务返回一个事件才能继续执行; 16 | 2. 临界区和互斥量区别? 17 | + 互斥量是**可以命名**的,也就是说它可以**跨进程**使用; 18 | + 所以创建互斥量需要的资源更多,所以如果只为了在进程内部是用的话使用临界区会带来速度上的优势并能够减少资源占用量 19 | 20 | ### 临界区(**Critical Section**) 21 | 22 | 1. 临界区:通过对多线程的**串行化**来访问**公共资源或一段代码**,速度快,适合控制数据访问。 23 | 2. 特性: 24 | + 保证在某一时刻只有一个**线程**能访问数据 25 | + 多个线程试图访问此临界区,将会被**挂起**,并一直持续到进入临界区的线程离开 26 | + 临界区在被释放后,其他线程可以继续**抢占** 27 | + 实现用**原子方式**操作共享资源的目的 28 | 3. 临界区包含两个操作原语: 29 | + EnterCriticalSection() 进入临界区 30 | + LeaveCriticalSection() 离开临界区 31 | 4. 作用范围:同一进程的不同线程 32 | 5. MFC实现实现临界区 33 | + MFC为临界区提供有一个 CCriticalSection类,实现临界区的同步; 34 | + 用CCriticalSection类成员函数Lock()和UnLock()标定出被保护代码片段 35 | 36 | ### 互斥量(**Mutex**) 37 | 38 | 1. 互斥量:为协调共同对一个共享资源的**单独访问**而设计的。 39 | 2. 特性: 40 | + 访问权限:**互斥量跟临界区很相似**,只有**拥有互斥对象**的线程才具有访问资源的**权限** 41 | + **互斥对象只有一个**:因此就决定了任何情况下此共享资源都不会同时被多个线程所访问 42 | 3. 互斥量的操作原语 43 | + CreateMutex() **创建**一个互斥量 44 | + OpenMutex() **打开**一个互斥量 45 | + ReleaseMutex() **释放**互斥量 46 | + WaitForMultipleObjects() **等待**互斥量对象 47 | 4. 互斥量和临界区的区别 48 | - 互斥不仅仅能够在**同一应用程序不同线程**中实现资源的安全共享 49 | - 而且可以在**不同应用程序的线程之间**实现对资源的安全共享。 50 | 5. MFC实现实现互斥量 51 | + MFC为互斥量提供有一个**CMutex**类; 52 | 53 | ### 信号量(**Semaphores**) 54 | 55 | 1. 信号量:为控制一个具有**有限数量**用户资源而设计。 56 | 2. 特性 57 | + 信号允许**多个线程同时**使用共享资源,限制在同一时刻访问此资源的**最大线程数目** 58 | + 信号量本质:就是一个计数器 59 | + PV操作:P操作--申请资源,sem减1;V操作--释放资源--sem加1 60 | + ![sem_pv.png](/OS/photo/sem_pv.png) 61 | 3. 信号量包含的几个操作原语: 62 | + CreateSemaphore() 创建一个信号量 63 | + OpenSemaphore() 打开一个信号量 64 | + ReleaseSemaphore() 释放信号量 65 | + WaitForSingleObject() 等待信号量 66 | 67 | ### 事 件 68 | 69 | 1. 事 件:用来**通知**线程有一些事件已发生,从而启动后继任务的开始。 70 | 2. 特性 71 | + 事件对象也可以通过**通知操作**的方式来保持**线程的同步**。并且可以实现不同进程中的线程同步操作。 72 | 3. 事 件包含的几个操作原语 73 | + CreateEvent() 创建一个事件 74 | + OpenEvent() 打开一个事件 75 | + SetEvent() 回置事件 76 | + WaitForSingleObject() 等待一个事件 77 | + WaitForMultipleObjects() 等待多个事件 78 | 79 | ## 多线程并发的情况 80 | 81 | 1. 并发的情况? 82 | + 共享唯一的硬件设备 83 | + 共享同一块内存区域 84 | + 一个进程的运行依赖另一进程对共享资源的执行结果 85 | 86 | ### 管程的用法 87 | 88 | 1. Semaphore 机制的缺陷: 89 | + 程序的易读性相对较差,对于信号量的管理也分散在各个参与对象中; 90 | + 因此有可能引起**死锁,进程饿死**等问题 91 | 2. 管程的定义 92 | + 管程:是可以被多个进程/线程安全访问的对象或模块 93 | + 管程汇总的方法是受到Mutex保护的,意味着同一时刻只允许一个访问者来使用它们。 94 | 3. 管程的特性 95 | + 安全性;互斥性;共享性 -------------------------------------------------------------------------------- /OS/Oops.md: -------------------------------------------------------------------------------- 1 | ## Oops 2 | 3 | 1. 当内核出现类似于用户空间的Segmentation Fault时,Oops会被打印到控制台和写入内核log缓冲区; 4 | 5 | ``` 6 | cat /dev/globalmem // 读取设备中节点的段错误信息 7 | ``` 8 | 9 | 2. 如何处理Oops? 10 | 11 | + 栈回溯信息 12 | 13 | ``` 14 | $ backtrace; // 在gdb调试的时候,使用的方法;显示出错指令附近的机器码; 15 | ``` 16 | 17 | + 使用valgrind命令 18 | 19 | ``` 20 | // 编译: gcc -Wall -g valgrind_demo.c -o valgrind_demo 21 | // 执行条件 : valgrind --tool=memcheck --leak-check=full ./valgrind_demo 22 | // 将错误写进日志: valgrind --tool=memcheck --leak-check=full --log-file=mem_leak.log ./valgrind_demo 23 | // 和gdb一起调试: valgrind --tool=memcheck --leak-check=full --log-file=mem_leak.log gdb valgrind_demo 24 | ``` 25 | 26 | 3. **[分析 Oops 信息](https://blog.csdn.net/kangear/article/details/8217329)** 27 | 28 | + 明确出错原因:可知内核是因为非法地址访问出错,使用了空指针。 29 | + 根据栈回溯信息找出函数调用关系。 30 | + 根据 pc 寄存器的值确定出错位置。 31 | + 结合内核源代码和反汇编代码定位问题。 32 | 33 | ## kernel panic 34 | 35 | 1. Panic 的等级大于 Oops 36 | 37 | + Oops英文单词的中文含义是“哎呀”,表示“惊叹”; 38 | 39 | + Panic英文单词的中文含义是“惊慌”。 40 | 41 | 2. kernel panic 42 | 43 | + 内核panic后,就死机了,俗称内核崩溃; 44 | + 内核报oops,这个时候不见得会panic,它可能只是报个oops,杀死进程而已 45 | 46 | ### 什么原因导致的kernel panic 47 | 48 | 1. 内核堆栈溢出,或者指针异常访问时,会出现kernel panic。 49 | + 堆栈溢出:程序循环或者多层嵌套的深度过多时,可能会导致栈溢出。 50 | 2. Linux在中断处理程序中,它不处于任何一个进程上下文,如果使用可能**睡眠的函数**,则系统调度会被破坏,导致kernel panic 51 | + 在中断处理程序中,是不能使用有可能导致睡眠的函数(例如信号量等) -------------------------------------------------------------------------------- /OS/Uboot如何给kernel传参数.md: -------------------------------------------------------------------------------- 1 | ## ARM下U-boot给Kernel传参数 2 | 3 | 1. U-boot 引导程序,在启动的时候会给Linux Kernel传递很多参数 4 | 5 | + 串口波特率,RAM Size,videofb、MAC Address等 6 | + 设备树的入口地址 7 | 8 | 2. u-boot如何进行传递的? 9 | 10 | + U-boot把要传递给kernel的东西:保存在struct tag数据结构中 11 | + 启动kernel时,把这个结构体的物理地址传给kernel; 12 | 13 | 3. kernel解析传递的参数? 14 | 15 | + Linux kernel通过这个地址,用parse_tags分析出传递过来的参数 16 | 17 | 4. ARM架构上,u-boot向Linux内核传递参数利用了R0,R1和R2三个寄存器 18 | 19 | | 寄存器 | 作用 | 20 | | ------ | ------------------------------------------------------------ | 21 | | R0 | 暂时不用,缺省放0 | 22 | | R1 | 机器号,标识计算机系统的型号,
内核支持的所有使用**ARM处理器的设备ID号**定义在arch/arm/tools/mach-types文件中,
编译内核过程中会被转换为一个头文件include/asm-arm/mach-types.h供其他文件包含使用。 | 23 | | R2 | R2寄存器传递的是一个地址,也就是指针的概念,这个指针指向一个**TAG区域**.
UBOOT和Linux内核之间正是通过这个扩展了的TAG区域来进行复杂参数的传递,
如 command line,文件系统信息等等,用户也可以扩展这个TAG来进行更多参数的传递。 | 24 | 25 | -------------------------------------------------------------------------------- /OS/cache的解析.md: -------------------------------------------------------------------------------- 1 | ## [Cache的解析](https://blog.csdn.net/ENSHADOWER/article/details/89083447) 2 | 3 | ### cache的定义?价值? 4 | 5 | 1. 什么是cache? 6 | + 缓存是介于**中央处理器CPU和主存储器之间**的高速小容量**存储器**,不属于主存的一部分。 (速度快、容量小、由硬件实现) 7 | 2. 为什么需要cache? 8 | + 作为中间存储器,加快CPU与主存储之间的**访问速度**; 9 | + 当CPU发生调用时,先在cache中进行查找;如果此时cache中刚好存在,**Cache命中**,也叫作cache hit,TLB的命中; 10 | + **缓存**又可以分为一级和二级缓存,一级的速度大于二级的速度。 11 | 3. 抽象模型: 12 | + 医生 -- 护士 -- 手术工具箱 13 | 14 | ### 什么是二级缓存? 15 | 16 | | 存储器 | 特点 | 用在哪一级存储器 | 17 | | ------ | ------------------------------------------------------------ | ---------------- | 18 | | RAM | 随机存取存储器(数据**可读可写**,但断电就消失) | | 19 | | ROM | 只读存储器(只允许**一次写入**永久只能读,断电了还是存在的) | BIOS是写进ROM | 20 | | SRAM | **静态**随机存储器:**不刷新**电路即能保存它内部存储的数据 | 一级缓存 | 21 | | DRAM | **动态**随机存储器:常见的系统内存DRAM,电脑和手机里面内存;
使用**电容存储**:DRAM 只能将数据保持很短的时间,**定时刷新数据** | 二级缓存 | 22 | 23 | ### Cache与主存系统之间访问 24 | 25 | 1. 两者关系? 26 | 27 | + CPU 和 cache之间:**字**为单位; 28 | + cache 和 主存之间:**数据块**为单位; 29 | 30 | 2. CPU访问分为:命中和未命中两种情况? 31 | 32 | ![cache.png](/OS/photo/cache.png) 33 | 34 | 3. 补充 35 | 36 | + **硬盘中的数据会先写入内存才能被CPU使用。** 37 | + 内存+缓存 -> 内存储空间 38 | + 硬盘 -> 外存储空间 39 | 40 | ### 缺页中断与页面置换算法 41 | 42 | 1. 缺页中断的过程? 43 | + 缺页中断:是由于所要访问的页面不存在于**内存**时(需要从外存中读取),由硬件所产生的一种**特殊的中断** 44 | + 在指令**执行期间**:产生和处理缺页中断信号。 45 | + 一条指令在执行期间,可能产生**多次缺页中断**。 46 | + **缺页中断返回时,执行产生中断的那一条指令;**而一般的中断返回时,执行**下一条**指令。 47 | 2. [页面置换算法?](/8.1Dji大疆/OScache多任务调度描述.md) 48 | + 将新页面调入内存时,**如果内存中所有的物理页都已经分配出去,就要按某种算法(页面置换算法)来废弃某个页面,将其所占据的物理页释放出来,**好的算法会让缺页率降低 49 | + LRU算法置换算法:最近最不常用调度算法(least recently used) 50 | 51 | -------------------------------------------------------------------------------- /OS/ioctl和unlock_ioctl的区别.md: -------------------------------------------------------------------------------- 1 | ## ioctl和unlock_ioctl的区别 2 | 3 | 1. 首先说明在2.6.36以后ioctl函数已经不再存在了 4 | 5 | + 而是用unlocked_ioctl和compat_ioctl两个函数实现以前版本的ioctl函数。 6 | + 区别:去除了原来ioctl中的**struct inode参数**,同时改变了返回值。 7 | 8 | ``` 9 | int (*ioctl) (struct inode * node,struct file *filp, unsigned int cmd, unsigned long arg); 10 | ``` 11 | 12 | 2. 驱动设计过程中存在的问题变化并不是很大 13 | 14 | + 同样在应用程序设计中我们还是采用ioctl实现访问 15 | + 而并不是unlocked_ioctl函数,因此我们还可以称之为ioctl函数的实现。 16 | 17 | 3. inode 参数 18 | 19 | + 文件的元数据 20 | 21 | + inode和file:ioctl的操作有可能是要修改文件的属性,或者访问硬件。要修改 22 | 23 | 文件属性的话,就要用到这两个结构体了,所以这里传来了它们的指针。 -------------------------------------------------------------------------------- /OS/linux7种文件类型.md: -------------------------------------------------------------------------------- 1 | ## linux 7种文件类型 2 | 3 | ### 在Linux中一切都是文件 4 | 5 | 1. 那如何查看文件是什么类型了? 6 | 7 | ``` 8 | $ ls -l ; 9 | ``` 10 | 11 | 2. 7种文件的属性的 12 | 13 | + 占用存储空间:文件、目录、符号链接 14 | + 伪文件系统,不占用存储空间:套接字、块设备、字符设备、管道 15 | 16 | ### 7 种文件类型 17 | 18 | | 文件属性 | 文件类型 | 查看 | 19 | | -------- | ------------------------------------------------------------ | ---------- | 20 | | | ls -al : 文件的信息中,第一个字母所表示的文件信息; | | 21 | | - | 常规文件,即file | | 22 | | d | 目录文件 | . / .. | 23 | | l | 符号链接文件 | | 24 | | b | block device 即块设备文件,如硬盘;支持以block为单位进行随机访问 | ls -l /dev | 25 | | c | character device 即字符设备文件,如键盘支持以character为单位进行线性访问 | | 26 | | p | pipe 即命名管道文件 | | 27 | | s | socket 即套接字文件,用于实现两个进程进行通信 | | 28 | -------------------------------------------------------------------------------- /OS/linux中netfilter的实现机制.md: -------------------------------------------------------------------------------- 1 | ## linux中netfilter的实现机制? 2 | 3 | 1. Linux netfilter就是借助一整套的 hook 函数的管理机制,实现数据包在三层以上的过滤、地址转换(SNAT、DNAT)、基于协议的连接跟踪。 4 | 5 | + 我们所说的内核的netfilter,应该包括二层数据的filter操作,以及对三层及三层以上数据的filter等操作。 6 | 7 | 2. 只不过二层的filter实现与三层及三层也上的filter实现有所不同 8 | 9 | + 其中二层的filter与应用层程序ebtables结合使用, 10 | + 而三层及以上的filter结合iptables使用。 11 | + 但是二层filter与三层filter使用的都是统一的hook机制。 12 | 13 | 3. linux抽象出整体的hook架构,通过在以下几个数据流经点添加hook机制 14 | 15 | + NF_IP_PRE_ROUTING、NF_IP_LOCAL_IN、NF_IP_FORWARD、NF_IP_LOCAL_OUT、NF_IP_POST_ROUTING 16 | 17 | ![linux_hook.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/linux_hook.png) 18 | 19 | -------------------------------------------------------------------------------- /OS/linux中系统调用过程.md: -------------------------------------------------------------------------------- 1 | ## linux中系统调用过程? 2 | 3 | ### linux中系统调用过程 4 | 5 | 1. 系统调用的作用? 6 | 1. **控制硬件:**系统调用往往作为硬件资源和用户空间的抽象接口,比如读写文件时用到的write/read调用。 7 | 2. **设置系统状态或读取内核数据:**因为系统调用是用户空间和内核的唯一通讯手段,所以用户设置系统状态,比如开/关某项内核服务(设置某个内核变量),或读取内核数据都必须通过系统调用。比如getpgid、getpriority、setpriority、sethostname 8 | 3. **进程管理:**用来保证系统中进程能以多任务在虚拟内存环境下得以运行。比如 fork、clone、execve、exit等 9 | 10 | 2. 系统调用实现过程? 11 | + (1)程序调用libc库的API函数,查找到**系统调用号**; 12 | + (2)通过汇编指令int 0x80, 调用软中断进入内核; 13 | + (3)内核中首先执行system_call 函数;通过SAVE_ALL**保存**系统调用号(eax)和CPU寄存器到相应的堆栈中; 14 | + 接着根据系统调用号在系统调用表中查找到对应的系统调用服务例程。 15 | + (4)**执行该服务例程**。 16 | + (5)执行完毕后,转入ret_from_sys_call 例程,从**系统调用返回** 17 | 18 | ![ret_sys.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/ret_sys.png) 19 | 20 | 3. 系统调用的处理函数 21 | 22 | + 函数的名称前缀都是 sys_:标识为一个系统调用的处理程序函数 23 | + 所有的处理程序函数都最多接收 5 个参数。否则,用一个单独的寄存器指向进程 地址空间中这些参数值所在的一个内存区即可。 24 | + 所有的系统调用都在内核态执行 25 | + 系统调用由内核分配的一个编号唯一标识(系统调用号) 26 | 27 | ![sys_call.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/sys_call.png) 28 | 29 | 4. [其他例子](https://blog.csdn.net/cs2539263027/article/details/78977054) 30 | 31 | ### 举例:read的系统调用过程? 32 | 33 | 1. 举例:read的系统调用过程? 34 | 35 | + 例如read系统调用,0x80 中断处理程序接管执行后,先检查其系统调用号,然后根据系统调用号查找系统调用表,并从系统调用表中得到处理 read 系统调用的内核函数 sys_read ,最后传递参数并运行 sys_read 函数。 36 | + 至此,内核真正开始处理** read 系统调用**(sys_read 是 read 系统调用的内核入口) 37 | 38 | [如:应用程序中read()在linux中执行过程即从用户空间到内核空间?](https://my.oschina.net/haomcu/blog/468656) -------------------------------------------------------------------------------- /OS/linux内存管理.md: -------------------------------------------------------------------------------- 1 | ## linux 用户空间中内存管理 2 | 3 | ### **Linux** **的虚拟内存管理有几个关键概念:** 4 | 5 | 1. 每个**进程**都有独立的虚拟地址空间,进程访问的虚拟地址并不是真正的物理地址; 6 | 2. 虚拟地址可通过每个进程上的页表(在每个进程的内核虚拟地址空间)与物理地址进行映射,获得真正物理地址; 7 | 3. 如果虚拟地址对应物理地址不在物理内存中,则产生缺页中断,真正分配物理地址,同时更新进程的页表;如果此时物理内存已耗尽,则根据内存替换算法淘汰部分页面至物理磁盘中。 8 | 9 | ### Linux 用户空间中虚拟地址的分布? 10 | 11 | 1. Linux 使用虚拟地址空间,大大增加了进程的寻址空间,**由低地址到高地址分别为**: 12 | 13 | + 代码段:该部分空间只能读,不可写;(包括:代码段、rodata 段(C常量字符串和#define定义的常量) ) 14 | 15 | + 数据段:保存全局变量、静态变量的空间; 16 | 17 | + **堆 :**就是平时所说的动态内存, malloc/new 大部分都来源于此。其中堆顶的位置可通过函数 brk 和 sbrk 进行动态调整。 18 | 19 | + 文件映射区域:如动态库、共享内存等映射物理空间的内存,一般是 mmap 函数所分配的虚拟地址空间 20 | 21 | + 栈:用于维护函数调用的上下文空间,一般为 8M ,可通过 ulimit –s 查看。 22 | 23 | + 内核虚拟空间:用户代码不可见的内存区域,由内核管理(页表就存放在内核虚拟空间)。 24 | 25 | ![linux_memory.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/linux_memory.png) 26 | 27 | 2. 32bit的地址空间划分 28 | 29 | + 0x08048000~0xbfffffff 是用户空间 30 | + 0xc0000000~0xffffffff 是内核空间,包括内核代码和数据、与进程相关的数据结构(如页表、内核栈) 31 | + **%esp 执行栈顶,往低地址方向变化;** 32 | + **brk/sbrk 函数控制堆顶_edata往高地址方向变化** 33 | 34 | 3. **64bit系统的划分** 35 | 36 | + **地址空间大小不是2^32,也不是2^64,而一般是2^48 37 | + 因为并不需要 2^64 这么大的寻址空间,过大空间只会导致资源的浪费 38 | 39 | ``` 40 | cat /proc/cpuinfo // 64位Linux一般使用48位来表示虚拟地址空间,40位表示物理地址, 41 | ``` 42 | 43 | ## malloc和free是如何分配和释放内存? 44 | 45 | ### 查看进程发生缺页中断的次数 46 | 47 | ``` 48 | $ ps -o majflt,minflt -C program //majflt -- major fault 大错误;minflt -- minor fault 49 | ``` 50 | 51 | + *两个数值表示一个进程自启动以来所发生的缺页中断的次数。 52 | 53 | 1. 发成缺页中断后,执行了那些操作? 54 | + 当一个进程发生缺页中断的时候,进程会陷入内核态,执行以下操作 55 | + 检查要访问的虚拟地址是否合法 56 | + 查找/分配一个物理页 57 | + 充物理页内容(读取磁盘,或者直接置0,或者啥也不干) 58 | + 建立映射关系(虚拟地址到物理地址) 59 | 2. 系统缺页时,操作系统做了什么? 60 | + 在第一次访问**已分配**的虚拟地址空间的时候,发生缺页中断 61 | + 操作系统负责分配物理内存,然后建立虚拟内存和物理内存之间的映射关系。 62 | 63 | ### malloc 进程分配内存,使用的系统调用:brk 和mmap 64 | 65 | + 这两种方式分配的都是虚拟内存,没有分配物理内存 66 | + 第一次读/写数据时,引起**内核缺页中断**,内核才分配对应的物理内存,然后虚拟地址空间建立映射关系) 67 | 68 | 1. brk是将数据段(.data)的最高地址指针_edata往高地址推; 69 | 70 | + _edata: **指向数据段的最高地址** 71 | 72 | 2. mmap是在进程的虚拟地址空间中(堆和栈中间,称为**文件映射区域**的地方)找一块空闲的虚拟内存 73 | 74 | 3. **内存分配的几种情况** 75 | 76 | | 内存分配大小 | 方法 | 具体过程 | 77 | | -------------------- | ------------ | ------------------------------------------------------------ | 78 | | malloc(size < 128k ) | brk | _edata+size;(没有分配物理地址) | 79 | | malloc(size > 128k ) | mmap | 从堆和栈的文件映射区分配一块虚拟内存 | 80 | | **方法** | **内存释放** | **注意** | 81 | | brk | free(ptr) | 只有高地址释放,才能释放低地址;否则会出现**内存碎片**
当释放的两块内存和大于128k时,执行**内存紧缩操作**(返回内存) | 82 | | mmap | munmap | 可以随时释放内存空间 | 83 | 84 | ![memory_malloc.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/memory_malloc.png) 85 | 86 | 4. malloc()申请的内存空间范围? 87 | 88 | ``` 89 | 0x00000000 -- 0xBFFFFFFF; //32bit的地址当中 90 | ``` 91 | 92 | 93 | 94 | 5. 如何查看堆内内存的碎片情况 ? 95 | 96 | ``` 97 | glibc 提供的结构体: 98 | struct mallinfo { 99 | } 100 | ``` 101 | 102 | 6. 如果想知道堆内究竟有多少碎片: 103 | 104 | + 可通过 mallinfo 结构中的 fsmblks 、smblks 、ordblks 值得到,这些值表示不同大小区间的碎片总个数,这些区间分别是 0~80 字节,80~512 字节,512~128k**。 105 | 106 | ### 为何不用mmap替代brk,申请内存? 107 | 108 | 1. 两个问题: 109 | + 既然堆内碎片不能直接释放,导致疑似“内存泄露”问题,为什么 malloc 不全部使用 mmap 来实现呢? 110 | + 而是仅仅对于大于 128k 的大块内存才使用 mmap ? 111 | 2. 为什么申请空间小于128k的使用brk? 112 | + 进程向 OS 申请和释放地址空间的接口: sbrk/mmap/munmap 都是系统调用,频繁调用系统调用都比较消耗系统资源的。 113 | + mmap 申请的内存被 munmap 后,重新申请会产生更多的缺页中断 114 | + 缺页中断是内核行为,会导致内核态CPU消耗较大。如果使用 mmap 分配小内存,会导致地址空间的分片更多,内核的管理负担更大。 115 | 3. 为什么申请空间大于128k时使用mmap? 116 | + 堆是一个连续空间,并且堆内碎片由于没有归还 OS ,如果可重用碎片,再次访问该内存很可能不需产生任何系统调用和缺页中断,这将大大降低 CPU 的消耗 117 | 4. mallopt(M_MMAP_THRESHOLD, ) 来修改这个临界值 118 | 119 | ### mmap的原理 120 | 121 | 1. 问题一:如何将mmap后读写映射区域和普通的read/write联系起来? 122 | - 普通的read/write和mmap后的映射区域的读写到底有什么区别 123 | - 为什么有时候会选择mmap而放弃普通的read/write 124 | 2. page chache 页缓存的原理 125 | 1. 在真正的把用户数据读写到磁盘或者是存储设备前 126 | - 内核还会在page cache中管理这些数据。 127 | - page的存在有效的管理了用户数据和读写的效率 128 | 2. 用户数据不是直接来自于应用层,读(read)或者是写入(write)磁盘和存储介质; 129 | - 被一层一层的应用所划分,在每一层次中都会有不同的功能对应 130 | - 最后发生交互时,在最恰当的时机**触发磁盘**的操作 131 | 3. IO驱动写入磁盘和存储介质 132 | - page的管理设计到了缓存,这些缓存以page的单位管理 133 | - 在没有IO操作之前,暂时存放在系统空间中,而并未直接写入磁盘或者存贮介质。 134 | 3. 系统调用中的mmap 和read/write关系 135 | 1. mmap的执行,仅仅是在内核中建立了文件与虚拟内存空间的对应关系。用户访问这些虚拟内存空间时,页面表里面是没有这些空间的表项的。 136 | 2. 当用户程序试图访问这些映射的空间时,于是产生**缺页异常**。内核捕捉这些异常,逐渐将文件载入。 137 | 3. 所谓的**载入过程**,具体的操作就是read和write在管理pagecache。 138 | 4. [效率对比](https://blog.csdn.net/edwardlulinux/article/details/8604400) 139 | + 看出使用mmap后发现,系统调用所消耗的时间远远比普通的read少很多。 -------------------------------------------------------------------------------- /OS/linux内核中的锁和同步机制.md: -------------------------------------------------------------------------------- 1 | ## Linux 内核锁主要是自旋锁和信号量 2 | 3 | | 区别 | 自旋锁 | 信号量--用户空间 | 信号量--内核空间 | 4 | | ---------- | ---------- | ---------------- | ---------------- | 5 | | 申请锁失败 | 忙循环等待 | 等待队列,睡眠 | 等待队列,睡眠 | 6 | | ISR中 | 可以 | 不可以 | 不可以 | 7 | 8 | + 进程和ISR都要访问同一内核数据时: 9 | 10 | + 要在进程或者内核代码中申请自旋锁时:要**禁止中断**,避免死锁 11 | 12 | + ``` 13 | spin_lock_irqsave; 14 | spin_unlock_irqstroe; 15 | ``` 16 | 17 | ### 自旋锁 18 | 19 | ``` 20 | spin_lock() // 阻塞获取锁 21 | spin_trylock() // 得阻塞获取锁 22 | spin_unlock() //释放锁 23 | ``` 24 | 25 | ### 内核信号量 26 | 27 | 1. 内核信号量:只能在内核中使用 28 | 29 | ``` 30 | void down(); // 获取信号量,会导致睡眠; 31 | void up(); // 释放sem信号量,将信号量加1; 32 | ``` 33 | 34 | 2. IPC信号量:只能在用户空间中使用 35 | 36 | ``` 37 | sem_wait(); // 获取信号量,会导致睡眠; 38 | sem_post(); // 释放信号量,使得信号量加1 39 | ``` 40 | -------------------------------------------------------------------------------- /OS/linux计算页表项大小.md: -------------------------------------------------------------------------------- 1 | ## linux计算页表项大小 2 | 3 | ### Bit、 Byte、KB、MB、GB之间的换算 4 | 5 | ``` 6 | 1 Byte = 8 Bits(即 1B=8b) 7 | 1 KB = 1024 Bytes 8 | 1 MB = 1024 KB 9 | 1 GB = 1024 MB 10 | ``` 11 | 12 | ### 几个概念 13 | 14 | | 关键词 | 概念 | 15 | | -------- | ------------------------------------------------------------ | 16 | | 逻辑地址 | **程序编译**:生成的目标模块进行编址时都是从0号开始编址,称之为目标模块的相对地址 | 17 | | 虚拟地址 | 计算机处理器的地址有32位和64位的两种,对应的虚拟地址的空间大小分别是2^32字节和2^64**字节**,字节用B表示 | 18 | | 页 | 分页存储管理将进程的逻辑地址空间划分为若干页(面),并且对其编号,号数从0开始,每个页(面)的大小称为页面大小,且大小应为2的幂。Linux下一页大小4KB | 19 | 20 | ### 如何计算内存中的页大小 21 | 22 | + 32位寻址空间:含有1M个页,页表占用内存4M,含有1M页表项; 23 | 24 | 1. 题目:32位逻辑地址空间中,一页的大小是(页框)4KB,按字节编制,页式内存管理中如何确定页表项大小? 25 | 26 | 2. 计算寻址空间包含多少个**页**? 27 | 28 | + ``` 29 | (1)寻址空间大小:size = 2^32 Bytes 30 | (2)一页的大小:page_one = 4 * 2^10 Bytes 31 | (3)计算多少个页:page_number = size / page_one = 1M 页 32 | ``` 33 | 34 | ![page_number.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/page_number.png) 35 | 36 | 3. 如何计算**页表**的大小? 37 | 38 | + 页表是对这些页的记录;有多少个页,就需要多少个页表 39 | 40 | + ``` 41 | (1) 32bit的地址空间;一页的大小是 2^12 bits ,占据了逻辑地址的低12bits 42 | (2) 高20bits逻辑地址:表示1M页的数量; 43 | (3) 页表占用空间的大小 = 2^10*4KB=4MB大小内存 44 | ``` 45 | 46 | + 页表组成 = 页号 + 页框号 ; 47 | 48 | ![page_table.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/page_table.png) 49 | 50 | 4. 如何计算页表项? 51 | 52 | + 寻址空间中包含多少个页,就有多少个页表项; 53 | + 1M 54 | 55 | -------------------------------------------------------------------------------- /OS/photo/AIO_result.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/AIO_result.png -------------------------------------------------------------------------------- /OS/photo/DMA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/DMA.png -------------------------------------------------------------------------------- /OS/photo/IO_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/IO_model.png -------------------------------------------------------------------------------- /OS/photo/MMU_cache.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/MMU_cache.png -------------------------------------------------------------------------------- /OS/photo/VFS_kernel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/VFS_kernel.png -------------------------------------------------------------------------------- /OS/photo/bootloader.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/bootloader.png -------------------------------------------------------------------------------- /OS/photo/cache.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/cache.png -------------------------------------------------------------------------------- /OS/photo/driver_enter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/driver_enter.png -------------------------------------------------------------------------------- /OS/photo/interrupt_reason.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/interrupt_reason.png -------------------------------------------------------------------------------- /OS/photo/linux_hook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/linux_hook.png -------------------------------------------------------------------------------- /OS/photo/linux_kernel_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/linux_kernel_start.png -------------------------------------------------------------------------------- /OS/photo/linux_memory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/linux_memory.png -------------------------------------------------------------------------------- /OS/photo/memory_malloc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/memory_malloc.png -------------------------------------------------------------------------------- /OS/photo/mips_cpu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/mips_cpu.png -------------------------------------------------------------------------------- /OS/photo/mips_kseg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/mips_kseg.png -------------------------------------------------------------------------------- /OS/photo/mtd_struct.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/mtd_struct.png -------------------------------------------------------------------------------- /OS/photo/page_number.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/page_number.png -------------------------------------------------------------------------------- /OS/photo/page_table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/page_table.png -------------------------------------------------------------------------------- /OS/photo/platform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/platform.png -------------------------------------------------------------------------------- /OS/photo/process_status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/process_status.png -------------------------------------------------------------------------------- /OS/photo/ret_sys.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/ret_sys.png -------------------------------------------------------------------------------- /OS/photo/sem_pv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/sem_pv.png -------------------------------------------------------------------------------- /OS/photo/spin_lock_sem.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/spin_lock_sem.png -------------------------------------------------------------------------------- /OS/photo/sys_call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/OS/photo/sys_call.png -------------------------------------------------------------------------------- /OS/主设备号和次设备号的用途.md: -------------------------------------------------------------------------------- 1 | ## 主设备号和次设备号的用途 2 | 3 | 1. 主设备号 4 | 5 | + 主设备号标识设备对应的驱动程序。 6 | + 虽然现代的linux内核允许多个驱动程序共享主设备号,但我们看待的大多数设备仍然按照“一个主设备对应一个驱动程序”的原则组织。 7 | 8 | 2. 次设备号 9 | 10 | + 次设备号由内核使用,用于正确确定设备文件所指的设备。 11 | + 依赖于驱动程序的编写方式,我们可以通过次设备号获得一个指向内核设备的直接指针,也可将此设备号当作设备本地数组的索引。 12 | 13 | 3. 创建设备文件的方法 14 | 15 | + 手动创建 16 | 17 | ``` 18 | $ cat /proc/devices // 查看字符设备的驱动 19 | $ mknod /dev/globalmem c 230 0 //创建设备节点; 主设备号 和次设备号; 20 | ``` 21 | 22 | + **UDEV/MDEV**自动创建设备文件的方式 23 | 24 | ``` 25 | /etc/init.d/rcS // 脚本文件中会执行 mdev -s 自动创建设备节点。 26 | ``` 27 | 28 | 29 | 30 | ### 字符设备的两种注册方式 31 | 32 | + 可以再初始化时注册,也可以直接注册 33 | 34 | 1. void cdev_init(struct cdev *cdev, struct file_operations *fops) 35 | + 该注册函数可以将cdev结构嵌入到自己的设备特定的结构中。 36 | + cdev是一个指向结构体cdev的指针,而fops是指向一个类似于file_operations结构(可以是file_operations结构,但不限于该结构)的指针. 37 | 2. int register_chrdev(unsigned int major, const char *namem , struct file)operations *fopen); 38 | + 该注册函数是早期的注册函数,major是设备的主设备号,name是驱动程序的名称,而fops是默认的file_operations结构(这是只限于file_operations结构) 39 | + 对于register_chrdev的调用将为给定的主设备号注册0-255作为次设备号,并为每个 设备建立一个对应的默认cdev结构。 -------------------------------------------------------------------------------- /OS/内存泄漏的理解.md: -------------------------------------------------------------------------------- 1 | ## OS内存泄漏的理解 2 | 3 | 1. 内存泄漏(Memory leak): 4 | 5 | + 分配完了又不释放,就会慢慢耗尽系统内存 6 | 7 | - 内存泄漏的Bug很难找到,因为它不会像访问越界一样导致程序运行错误 8 | 9 | 2. 特殊情况 10 | 11 | - free : 只要不是释放野指针就没问题 12 | 13 | ``` 14 | malloc(0); return 非NULL的指针 15 | free(NULL); 合法的 16 | ``` 17 | 18 | - free 产生错误 19 | 20 | ``` 21 | malloc(p); 22 | free(p); 23 | free(p); //第二次释放的时候,找不到指针,到这里会报错 24 | ``` 25 | 26 | - 正确的free过程 27 | 28 | ``` 29 | free(p->msg); 30 | free(p); 31 | p = NULL; 32 | ``` 33 | 34 | 3. valgrind: 查找程序中内存泄露的问题 35 | 36 | ``` 37 | // 编译: gcc -Wall -g valgrind_demo.c -o valgrind_demo 38 | // 执行条件 : valgrind --tool=memcheck --leak-check=full ./valgrind_demo 39 | // 将错误写进日志: valgrind --tool=memcheck --leak-check=full --log-file=mem_leak.log ./valgrind_demo 40 | // 和gdb一起调试: valgrind --tool=memcheck --leak-check=full --log-file=mem_leak.log gdb valgrind_demo 41 | ``` 42 | 43 | -------------------------------------------------------------------------------- /OS/几组概念.md: -------------------------------------------------------------------------------- 1 | ## 几组概念 2 | 3 | ### 并发和竞态 4 | 5 | + 并发: 多个执行单元同时, **并行**被执行; 6 | + 竞态: **并发的执行单元**对共享资源的访问, 导致了竞态的发生; 7 | 8 | ### 自旋锁和互斥体 9 | 10 | + 解决并发和竞态的问题? 11 | 12 | ### 阻塞和非阻塞 13 | 14 | + 阻塞:就是调用函数,函数没有接收完数据或者没有得到结果之前,**不会返回。** 15 | 16 | ``` 17 | sleep_on(); wake_up() 18 | ``` 19 | 20 | + 非阻塞:就是调用我(函数),我(函数)立即返回,通过**select**通知调用者 21 | 22 | ``` 23 | poll(); select(); epoll(); //通过轮询查找; 24 | ``` 25 | 26 | ### 同步和异步 27 | 28 | + 同步:就是我调用一个功能,该功能没有结束前,我**死等结果** 29 | + 异步:就是我调用一个功能,不需要知道该功能结果,该功能有结果后通知我(**回调**通知) 30 | 31 | ## I/O模型 32 | 33 | ### 五种I/O模型 34 | 35 | + 1)阻塞I/O(blocking I/O) 36 | + 2)非阻塞I/O (nonblocking I/O) 37 | + 3) I/O复用(select 和poll) (I/O multiplexing) 38 | + 4)信号驱动I/O (signal driven I/O (SIGIO)) 39 | + 5)异步I/O (asynchronous I/O (the POSIX aio_functions)) 40 | + 前4种都是同步,最后一种才是异步。 41 | 42 | ### 同步I/O和异步I/O 43 | 44 | 1. 同步IO和异步IO的区别就在于:数据拷贝的时候进程是否**阻塞** 45 | 46 | 2. 阻塞IO和非阻塞IO的区别就在于:应用程序的调用是否**立即返回** 47 | 48 | ![IO_model.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/IO_model.png) 49 | 50 | ### 异步I/O 的实现 51 | 52 | 1. 方法:异步通知 53 | 54 | - 一旦设备**就绪**, 则**主动通知**应用程序, 这样应用程序就不用查询设备的状态; 55 | - 机制: 信号驱动的异步I/O; 56 | - 信号: 在软件层次上对中断机制的模拟, 信号是异步的; 57 | 58 | 2. 用户空间捕捉信号+内核空间释放信号 59 | 60 | ![AIO_result.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/AIO_result.png) -------------------------------------------------------------------------------- /OS/四大CPU体系结构.md: -------------------------------------------------------------------------------- 1 | ## 四大CPU体系结构 2 | 3 | ### RISC (reduced instruction set computer) 4 | 5 | 1. 精简指令集计算机性能 6 | + 性能特点一:由于指令集**简化**后,流水线以及常用指令均可用硬件执行; 7 | + 性能特点二:采用大量的寄存器,使大部分指令操作都在寄存器之间进行,提高了处理速度; 8 | + 性能特点三:采用**缓存—主机—外存**三级存储结构,**使取数与存数**指令分开执行,使处理器可以完成尽可能多的工作,且不因从存储器存取信息而放慢处理速度。 9 | 10 | ### ARM系列 11 | 12 | 1. 是一个32位精简指令集(RISC)处理器架构,其广泛地使用在许多嵌入式系统设计 13 | 14 | ### **x86系列/Atom处理器** 15 | 16 | 1. 英特尔Intel首先开发制造的一种微处理器体系结构的泛称。 17 | 2. x86架构是重要地可变指令长度的CISC(复杂指令集电脑) 18 | 19 | ### **MIPS系列** 20 | 21 | 1. MIPS是世界上很流行的一种RISC处理器。MIPS的意思是“无内部互锁流水级的微处理器”(Microprocessor without interlocked piped stages) 22 | 2. 机制是尽量利用软件办法避免流水线中的数据相关问题 23 | 24 | ### **PowerPC系列** 25 | 26 | 1. PowerPC 是一种精简指令集(RISC)架构的中央处理器(CPU) 27 | 2. 基本的设计源自IBM(国际商用机器公司)的IBM PowerPC 601 微处理器POWER 28 | 29 | ### **互补型的实时性(Real Time)较好的DSP架构** 30 | 31 | 1. DSP是微处理器的一种,这种微处理器具有极高的处理速度.因为应用这类处理器的场合要求具有很高的实时性(Real Time)。 32 | 33 | ## MIPS cpu地址空间划分 34 | 35 | 1. 2G的用户空间,2G内核空间 36 | 37 | ![mips_cpu.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/mips_cpu.png) 38 | 39 | 2. 具体地址空间内容 40 | 41 | ![mips_kseg.png](https://github.com/quronghui/Embedded-written-reference/blob/master/OS/photo/mips_kseg.png) 42 | 43 | -------------------------------------------------------------------------------- /OS/嵌入式的volatile变量.md: -------------------------------------------------------------------------------- 1 | ## 嵌入式的volatile变量 2 | 3 | ### volatile变量 4 | 5 | 1. Volatile是区分C程序员和嵌入式系统程序员最基本的问题。 6 | 7 | + 嵌入式系统程序员经常同硬件、中断、RTOS等打交道,所有这些都要求volatile变量 8 | + Volatile:作为指令关键字, 确保本条指令不会因编译器的优化而省略; 9 | + 寄存器中的值会被认为的改变,所以必须要求每次直接读值。 10 | 11 | 2. 实例区别 12 | 13 | ``` 14 | // 对一个变量进行连续的赋值 15 | void main(){ 16 | XBYTE[2]=0x55; 17 | XBYTE[2]=0x56; 18 | XBYTE[2]=0x57; 19 | XBYTE[2]=0x58; 20 | } 21 | ``` 22 | 23 | + 不加volatile: 译器就不能像对待纯粹的程序那样对上述四条语句进行优化只认为XBYTE[2]=0x58,而忽略前三条语句,并且只产生1条机器码 24 | + 用volatile修饰过,此时编译器会逐一的进行编译并产生相应的4条机器码。 25 | 26 | 3. **使用volatile变量的例子** 27 | 28 | 1). 并行设备的硬件寄存器(如:状态寄存器) 29 | 30 | 2). 一个中断服务子程序中会访问到的非自动变量(Non-automaticvariables) 31 | 32 | 3). 多线程应用中被几个任务共享的变量 33 | 34 | ### 其他的问题 35 | 36 | 1. 一个参数既可以是const还可以是volatile吗? 37 | 38 | + 可以的; 39 | + volatile修饰:因为它可能被意想不到地改变; 40 | + const修饰:因为程序不应该试图去修改它 41 | 42 | 2. 一个指针可以是volatile 吗? 43 | 44 | + 是的 45 | + 例子:一个中断服务子程序修改一个指向一个buffer的指针时 46 | 47 | ``` 48 | // 返回*ptr指向值的平方;但是达不到预期的效果,第二次读值的时候被改变了; 49 | int square(volatile int *ptr) 50 | { 51 |   return *ptr * *ptr; // 在这里,需要两次从内存中读取值 52 | } 53 | 54 | // 正确的代码:只进行一次读值 55 | long square(volatile int *ptr) 56 | { 57 |   int a; 58 |  a = *ptr; 59 |   return a * a; 60 | } 61 | ``` 62 | 63 | -------------------------------------------------------------------------------- /OS/访问固定的内存位置.md: -------------------------------------------------------------------------------- 1 | ## 嵌入式系统访问固定的内存位置 2 | 3 | 1. 考察的知识点: 4 | 5 | + 为了访问一绝对地址 6 | + 把一个整型数强制转换(typecast)为一指针是合法的 7 | 8 | 2. 题目:在某工程中,要求设置一绝对地址为0x67a9的整型变量的值为0xaa55 9 | 10 | ``` 11 | int *ptr; 12 | ptr = (int *) 0x67a9; // 将整数强制转化为一个( int * )地址 13 | *ptr = 0xaa55; // 将值存入特定的地址中 14 | ``` 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /OS/驱动中的一些查看命令.md: -------------------------------------------------------------------------------- 1 | ## 驱动中的一些查看命令 2 | 3 | 1. demsg 4 | 5 | + 查看驱动模块中打印信息的命令 6 | 7 | 2. 命令 8 | 9 | ``` 10 | $ insmod hello.ko // 模块加载函数 , 只加载hello.ko模块; 11 | $ modprobe -r hello.ko // 模块加载函数, 将加载hello.ko 依赖的所有模块; 12 | 13 | $ rmmod hello.ko // 模块卸载函数 , 只卸载hello.ko模块; 14 | 15 | $ lsmod // 查询模块之间的依赖关系; == cat /proc/modules 16 | $modinfo hello.ko // 得到模块相关参数信息 17 | $ mknod /dev/globalmem c 230 0 //创建设备节点; 主设备号 和次设备号; 18 | ``` 19 | 20 | 3. insomd 加载 一个驱动模块,会执行模块中的哪个函数?rmmod呢?这两个函数在设计上要注意哪些?遇到过卸载驱动出现异常没?是什么问题引起的? 21 | 22 | + (1)insmod调用init函数,rmmod调用exit函数; 23 | + (2)卸载模块时曾出现卸载失败的情形:原因是存在进程正在使用模块,检查代码后发现产生了死锁的问题。 24 | + (3)init函数中申请的资源在exit函数中要释放:也就是一个模块注册进内核,退出内核时要清理所带来的影响,带走一切不留下一点痕迹。 25 | 26 | -------------------------------------------------------------------------------- /TCP/DNS服务器是如何工作的.md: -------------------------------------------------------------------------------- 1 | ## DNS服务器是如何工作的 2 | 3 | 1. DNS 处于应用层 4 | 5 | 2. DNS域名解析系统作用: 6 | 7 | - 将域名(主机名) --> 解析为 IP地址(4/6) 8 | - 例子: 将应用层的网址, 解析为IP地址才能正常访问, 因为IP地址是区分不同主机的标识; 9 | 10 | 3. 域名的构成和分层 11 | 12 | - 构成:由英文字母 + 点构成 13 | 14 | ``` 15 | piyo.kusa.ac.jp // jp 根域名 16 | ``` 17 | 18 | - 分层: 根域名 + 第1层域名 + ... + 主机域名 19 | 20 | 4. 域名服务器: 用于管理域名的主机和相应软件; 21 | 22 | - 每一层都有一个域名服务器; 23 | - 注册: 每一层的域名服务器都必须注册**根域名服务器的IP地址** 24 | - 上一层的域名服务器: 注册了下一层的IP地址 25 | - 原因: 本层没有: 向根域名请求查询, 从**根域名**顺序向下查找 26 | 27 | 5. DNS查询 28 | 29 | - 工具: 解析器 30 | - 先在本层的域名服务器查找相关域名; 从**根域名**顺序向下查找 31 | 32 | 6. DNS解析情况 33 | 34 | - 主机名 --> 检索IP地址: "A类" --- 正常的DNS解析 35 | - IP地址 --> 检索主机名: "PTR类" --- IP地址的反向解析 36 | -------------------------------------------------------------------------------- /TCP/IGMP组播中的MAC地址.md: -------------------------------------------------------------------------------- 1 | ## IGMP组播中的MAC地址 2 | 3 | | ip地址 | 作用/组播地址 | 用途 | 4 | | -------------------------- | ---------------------------------- | ------------------------------------------------- | 5 | | 224.0.0.0~224.0.0.255 | **预留**的[组播地址](永久组地址) | 地址224.0.0.0**不做分配**,其他供**路由协议**使用 | 6 | | 224.0.1.0~224.0.1.255 | **公用**的组播地址 | 用于Internet | 7 | | 224.0.2.0~238.255.255.255 | **用户**可用的 | 全网范围内有效 | 8 | | 239.0.0.0~239.255.255.255 | **本地**管理组播地址 | 仅在特定的本地范围内有效 | 9 | 10 | -------------------------------------------------------------------------------- /TCP/OSI七层中的硬件设备.md: -------------------------------------------------------------------------------- 1 | ## OSI 七层模型的协议 2 | 3 | | 分层 | 功能 | 协议 | 4 | | ---------- | ------------------------------------------------------------ | ------------------------------------------------------------ | 5 | | 应用层 | 针对特定应用的协议 电子邮件,文件传输,虚拟终端 | HTTP: 万维网(WWW) web; 数据格式 -- HTML
SMTP: Email使用(simple mail transfer protocol)
FTP: 文件传输(file...); **建立两个TCP连接**-- 控制和数据
TELENT SSH 远程连接 (secure shell)(更安全)
SNMP 网络管理: (simple network management)
**DNS**: 域名解析服务器 | 6 | | 表示层 | 数据格式转换:转化为网络标准格式 | 无 | 7 | | 会话层 | 通信管理:**决定**何时建立/断开连接 采用何种连接方式(TCP/UDP) | 无 | 8 | | 传输层 | 提供端对端的连接; 实际建立**逻辑**上的通道 | TCP : 面向连接的传输协议; 有重传机制
UDP: 面向无连接; 主要用于多播, 广播和视频 | 9 | | 网络层 | **完整**数据包发送,进行数据链路转换(完整行程列表) 路由选择 | IP:根据IP地址进行转发分包数据, 不具备重发机制
ICMP: IP数据包出故障时, 发送异常通知给发送端

CIDR:路由聚合,减小路由控制表
IGMP:组内控制协议,实现多播
DHCP: 实现即插即用,自动分配获取IP地址
RIP,OSPF,BGP | 10 | | 数据链路层 | 负责一个**数据段**帧的发送 | MTU:以太网链路最大传输单元;
WLAN : 无线局域网
PPP: 点对点协议,身份认证,明文传输
ATM:异步传输,以信元为单位进行数据连接;
ARP,RARP | 11 | | 物理层 | 以**二进制数据**形式在物理媒介上传输数据 | IEEE802.1,IEEE802.11 | 12 | 13 | ## TCP/IP的五层模型 14 | 15 | | 属性 | 分层 | 数据单位 | 硬件 | 16 | | ----------------------- | ------------------------------ | --------------------- | ------------------------------------------------------------ | 17 | | 应用程序 | 应用层(会话层以上) | 统称为报文 | 网关:协议翻译, 数据转换;
代理服务器 | 18 | | 操作系统 | 传输层 | TCP--段; UDP--数据报 | 4-7层交换机:分析收发数据,进行特定处理;
负载均衡器(窗口大小啥的) | 19 | | | 互联网层(网络层) | 数据包 | 路由器/3层交换机:分组数据转换 | 20 | | 设备驱动程序 与网络接口 | 网络接口层 (数据链路层) 网卡层 | 数据帧 | 网桥/2层交换机:连接两个网络
以太网使用:交换集线器hub | 21 | | | 物理层 | 二进制比特流 | 中继器:信号整形放大,延长网络;
中继集线器, 多个端口的中继器 | 22 | 23 | ## 路由协议 24 | 25 | ![RIP.png](https://github.com/quronghui/Embedded-written-reference/blob/master/TCP/photo/RIP.png) 26 | 27 | -------------------------------------------------------------------------------- /TCP/Socket建立连接过程.md: -------------------------------------------------------------------------------- 1 | ### Socket 套接字 2 | 3 | 1. Socket 套接字 4 | - 支持TCP/IP协议的网络通信的基本操作单元, 5 | - 中间软件抽象层,它是一组接口 6 | - 在设计模式中,Socket其实就是一个门面模式, 它把复杂的TCP/IP协议族隐藏在Socket接口后面 7 | 2. Socket网络通信要求: 8 | + 连接协议(TCP/UDP), 9 | + 本地主机IP,本地进程的协议端口, 10 | + 远地主机IP,远地进程的协议端口。 11 | 3. 建立socket连接 12 | - 需要一对套接字: 一个运行于客户端,称为ClientSocket ,另一个运行于服务器端,称为ServerSocket 13 | - 套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认 14 | - 服务器监听:服务器端套接字, 等待客户端的连接请求。 15 | - 客户端请求: 客户端描述连接的服务器的套接字,指出服务器端套接字的地址和端口号 16 | - 连接确认: server建立一个新的**线程**,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接 17 | - 服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求 18 | 19 | ### socket连接建立过程 20 | 21 | 1. socket通讯的基本过程(基于TCP协议) 22 | 23 | (1)服务器端建立一个Socket, 24 | 25 | (2)服务器端通过bind()绑定Socket端口,并通过调用listen()对端口进行监听; 26 | 27 | (3)服务器端Socket通过调用accept()方法,使之处于阻塞,等待客户端连接。 28 | 29 | (4)客户端创建一个Socket,并设置好服务器的IP和端口。 30 | 31 | (5)客户端调用connect()发送连接请求,建立连接。 32 | 33 | (6)建立连接后服务器和客户端通过send(),recv()进行发送和接收操作 34 | 35 | (7)通信结束后服务器和客户端都通过调用close()将套接字关闭。 36 | 37 | 2. 基于UDP协议 38 | 39 | (1)服务端建立socket, 40 | 41 | (2)服务端通过bind()进行绑定到本地地址和端口 42 | 43 | (3)服务器端调用recvfrom()进行等待接收数据 44 | 45 | (4)客户端建立socket,调用sendto()向服务器 46 | 47 | (5)完成数据传输后,close()关闭套接字 -------------------------------------------------------------------------------- /TCP/http和TCP之间的关联.md: -------------------------------------------------------------------------------- 1 | ## Http 和 TCP之间的区别和联系 2 | 3 | 1. TCP/IP是一个通信协议群,是底层通讯协议,定义的是数据传输和连接方式的规范 4 | 2. HTTP协议中的数据是利用TCP协议传输的,所以支持HTTP也就一定支持TCP 5 | 6 | ## Http 和 Https 区别 7 | 8 | | 区别 | Http | Https | 9 | | --------- | ------------------------------------------------------------ | ---------------------------------------------------------- | 10 | | URL | http:// | http:// | 11 | | OSI模型中 | 应用层 | HTTPS 的**安全传输机制工作在传输层** | 12 | | 协议 | 超文本传输协议,信息是明文传输 | 具有安全性的ssl加密传输协议 | 13 | | 证书 | 无需证书 | 向CA申请证书,且不是免费 | 14 | | 端口 | 80 | 443 | 15 | | 连接 | client/server:基于标准TCP
无连接:限制每次连接只处理一个请求\|
无状态:协议对于事务处理没有记忆能力,缺少就重传 | **SSL+HTTP协议**:构建的可进行加密传输、身份认证的网络协议 | 16 | | 用途 | 用于从WWW服务器传输超文本到本地浏览器的传输协议 | 一种是建立一个信息安全通道;另一种就是确认网站的真实性 | 17 | | 优缺点 | 传输快,连接简单;不安全 | 安全;连接过程复杂 | 18 | 19 | ## HTTP 20 | 21 | 1. HTTP协议即超文本传送协议(Hypertext Transfer Protocol ) 22 | - 是Web联网的基础,也是手机联网常用的协议之一 23 | - HTTP协议是建立在**TCP协议**之上的一种应用 24 | 2. HTTP特点 25 | - 客户端发送的每次请求都需要服务器回送响应,在请求结束后,会**主动释放连接** 26 | - 从建立连接到关闭连接的过程称为“一次连接” 27 | 3. http 连接并完成一次请求? 28 | - a. 域名解析 29 | - b. 发起TCP的3次握手 30 | - c. 建立TCP连接后发起http请求 31 | - d. 服务器端响应http请求,浏览器得到html代码 32 | - e. 浏览器解析html代码,并请求html代码中的资源 33 | - f. 浏览器对页面进行渲染呈现给用户 34 | 35 | ### HTTP是无状态协议和解决? 36 | 37 | 1. 如何理解HTTP是无状态的协议? 38 | + 无状态协议对于事务处理没有记忆能力 39 | + 缺少状态意味着如果后续处理需要前面的信:客户端需要再发送一次HTTP请求,HTTP并不知道当前客户端是一个”老用户“ 40 | 2. 如何解决HTTP的无状态协议? 41 | + 使用Cookie来解决无状态的问题; 42 | + Cookie就相当于一个通行证,第一次访问的时候给客户端发送一个Cookie,当客户端再次来的时候,拿着Cookie(通行证),那么服务器就知道这个是”老用户“ 43 | 44 | ### HTTP的方法有哪些? 45 | 46 | 1. http的方法有哪些? 47 | 48 | ![http_ways.png](https://github.com/quronghui/Embedded-written-reference/blob/master/TCP/photo/http_ways.png) 49 | 50 | 2. GET/POST的区别? 51 | 52 | + GET的语义是请求获取指定的资源。GET方法是安全、幂等、可缓存的(除非有 Cache-ControlHeader的约束),GET方法的报文主体没有任何语义。 53 | + POST的语义是根据请求负荷(报文主体)对指定的资源做出处理,具体的处理方式视资源类型而不同。POST不安全,不幂等,(大部分实现)不可缓存。 54 | 55 | 3. **安全、幂等、缓存是什么?** 56 | 57 | + 安全:如果一个方法的语义在本质上是「**只读**」的,那么这个方法就是安全的。 58 | + 户端向服务端的资源发起的请求如果使用了是安全的方法,就不应该引起服务端任何的状态变化,因此也是无害的 59 | + 此RFC定义,GET, HEAD, OPTIONS 和 TRACE 这几个方法是安全的。 60 | + 幂等:指同一个请求方法执行多次和仅执行一次的效果完全相同 61 | + 缓存:顾名思义就是一个方法是否可以被缓存 62 | + HEAD 和 某些情况下的POST都是可缓存的 63 | + 但是绝大多数的浏览器的实现里仅仅支持GET和HEAD。 64 | 65 | ## Https 66 | 67 | ### Https 工作流程 68 | 69 | ![https_connect.png](https://github.com/quronghui/Embedded-written-reference/blob/master/TCP/photo/https_connect.png) 70 | 71 | ### [SSL 建立连接,确认密钥的过程](https://www.cnblogs.com/barrywxx/p/8570715.html) 72 | 73 | ![ssl_connect.png](https://github.com/quronghui/Embedded-written-reference/blob/master/TCP/photo/ssl_connect.png) 74 | 75 | ### HTTPS是如何保证数据的安全? 76 | 77 | + 服务器和客户端双方用公有的相同的**对称秘钥对数据进行加密解密**,可以保证在数据收发过程中的安全 78 | + 1)客户端向服务器端发起SSL连接请求;(在此过程中依然存在数据被中间方盗取的可能,下面将会说明如何保证此过程的安全) 79 | + 2) 服务器把公钥发送给客户端,并且服务器端保存着唯一的私钥 80 | + 3)客户端用公钥对双方通信的对称秘钥进行加密,并发送给服务器端 81 | + 4)服务器利用自己唯一的私钥对客户端发来的对称秘钥进行解密,在此过程中,中间方无法对其解密(即使是客户端也无法解密,因为只有服务器端拥有唯一的私钥),这样保证了对称秘钥在收发过程中的安全,此时,服务器端和客户端拥有了一套完全相同的对称秘钥。 82 | + 5)进行数据传输,服务器和客户端双方用公有的相同的对称秘钥对数据进行加密解密,可以保证在数据收发过程中的安全,即是第三方获得数据包,也无法对其进行加密,解密和篡改。 83 | 84 | -------------------------------------------------------------------------------- /TCP/photo/RIP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/TCP/photo/RIP.png -------------------------------------------------------------------------------- /TCP/photo/TCP_MSL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/TCP/photo/TCP_MSL.png -------------------------------------------------------------------------------- /TCP/photo/http_connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/TCP/photo/http_connect.png -------------------------------------------------------------------------------- /TCP/photo/http_ways.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/TCP/photo/http_ways.png -------------------------------------------------------------------------------- /TCP/photo/https_connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/TCP/photo/https_connect.png -------------------------------------------------------------------------------- /TCP/photo/port.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/TCP/photo/port.png -------------------------------------------------------------------------------- /TCP/photo/ssl_connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/TCP/photo/ssl_connect.png -------------------------------------------------------------------------------- /TCP/photo/tcp_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/TCP/photo/tcp_flow.png -------------------------------------------------------------------------------- /TCP/photo/tcp_three.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/TCP/photo/tcp_three.png -------------------------------------------------------------------------------- /TCP/tcp和udp的区别.md: -------------------------------------------------------------------------------- 1 | ## TCP和UDP的区别 2 | 3 | | 区别 | TCP | UDP | 4 | | ---------------- | ---------------------------------------------- | ------------------------------------------------------------ | 5 | | 数据包分割与重组 | TCP层完成分割,目的主机TCP重组 | 源路由器数据分割,目的主机重组 | 6 | | 连接 | 三次握手,四次挥手 | 不建立连接 | 7 | | 数据单位 | 段(面向字节流) | 数据报 | 8 | | 丢包重试 | 丢包重发控制,顺序控制,超时重传,窗口流量控制 | 不会进行丢包重试,也不会纠正到达的顺序 | 9 | | 对应关系 | 一对一 | 支持一对一,一对多,多对一和多对多的交互通信 | 10 | | 头部开销 | 最小20字节 | 只有8字节 | 11 | | 拥塞控制 | 有控制 | 有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如IP电话,实时视频会议等) | 12 | 13 | ### 熟知的端口号 14 | 15 | ![port.png](/TCP/photo/port.png) 16 | 17 | ### [TCP的三次握手](https://blog.csdn.net/qzcsu/article/details/72861891) 18 | 19 | + netstat -ant : 查看tcp的状态; 20 | + Synchronize Sequence Numbers 21 | 22 | 1. TCP 的通过三次握手过程 23 | 24 | + ![tcp_three.png](/TCP/photo/tcp_three.png) 25 | 26 | 1. client : 发送SYN( syn_j = j )请求包给server; 并进入SYN_SEND状态,等待服务器确认; 27 | 2. server: 收到请求并确认 , 发送ACK(ack = syn_j+1); 同时server发送一个SYN(syn_k = k); 并进入**SYN_RECV**状态; 28 | 3. client: 收到SYN+ACK包, 向server发送ACK(ack = syn_k + 1); 29 | 4. client 和 server 同时进入**established**状态; 30 | 31 | 2. 为什么TCP客户端最后还要发送一次确认呢? 32 | - 防止已经**失效的连接**请求报文突然又传送到了服务器,从而产生错误 33 | - 防止服务器一直处于**SYN_RECV**,空等待客户端的报文; 34 | - **假设是两次握手建立连接**:客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中**滞留的时间**太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时**重新**向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。 35 | 36 | ### TCP四次挥手 37 | 38 | 1. TCP的四次挥手,断开连接过程? 39 | 40 | ![TCP_MSL.png](/TCP/photo/TCP_MSL.png) 41 | 42 | 2. 为什么建立连接是三次握手,关闭连接确是四次挥手呢? 43 | 44 | + **建立连接的时候:**服务器在**LISTEN**状态下,收到建立连接请求的**SYN**报文后,把ACK和SYN放在一个报文里发送给客户端。 45 | + **关闭连接时:**服务器收到对方的FIN报文时,**客户端不发数据但是还能接收数据**, 46 | + server可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。 47 | + 也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。 48 | 49 | 3. TCP第4次挥手client为何要等待2MSL才关闭? 50 | 51 | - MSL(Maximum Segment Lifetime)报文最大生存时间 52 | 53 | - 任何报文在网络上存活的最大时间,一旦超过该时间,报文就会被丢弃。 54 | - **TIME_WAIT = 2MSL**也就是指的2倍MSL的时间。 55 | - 保证client发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失; 56 | - **服务器**的角度:我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次;**客户端**在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。 57 | 58 | 4. 如果已经建立了连接,但是客户端突然出现故障了怎么办? 59 | 60 | + TCP还设有一个保活计时器,显然,客户端如果出现故障,服务器不能一直等下去,白白浪费资源。 61 | + 服务器每收到一次客户端的请求后都会**重新复位**这个计时器,时间通常是设置为2小时,若两小时还没有收到客户端的任何数据,服务器就会发送一个探测报文段,以后每隔**75秒**发送一次。若一连发送**10个探测报文**仍然没反应,服务器就认为客户端出了故障,接着就关闭连接。 62 | 63 | ### TCP 的窗口控制和重发控制 64 | 65 | ![tcp_flow.png](https://github.com/quronghui/Embedded-written-reference/blob/master/TCP/photo/tcp_flow.png) 66 | 67 | ### TCP的分包机制 68 | 69 | 1. TCP/ IP 数据传输中, 数据如何进行分包? 70 | - 按照最大的传输单元MTU进行计算; 71 | - 注意数据包需要包含首部 -------------------------------------------------------------------------------- /TCP/基于UDP实现可靠传输.md: -------------------------------------------------------------------------------- 1 | ## 基于UDP实现可靠传输 2 | 3 | 1. UDP的特性? 4 | + UDP处在传输层,那么udp在传输层是不能保证可靠传输的; 5 | 2. 实现UDP的可靠传输? 6 | + 要实现udp的可靠传输,只能在**应用层**实现; 7 | + 实现确认机制、重传机制、窗口确认机制。 8 | 3. 通过UDP模仿TCP提高可靠性? 9 | + 添加 seq/ack机制,确保数据发送到对端;(分包后添加序列号,应答ack) 10 | + 添加发送和接收缓冲区,确保重传数据还存在。 11 | + 添加超时重传机制,确保报文超过生存时间后,进行重传; 12 | 4. 详细说明:发送端发送数据时,生成一个随机seq=x,然后每一片按照数据大小分配seq。数据到达接收端后接收端放入缓存,并发送一个ack=x的包,表示对方已经收到了数据。发送端收到了ack包后,删除缓冲区对应的数据。时间到后,定时任务检查是否需要重传数据。 -------------------------------------------------------------------------------- /code/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /workspace.xml -------------------------------------------------------------------------------- /code/.idea/code.iml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /code/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | -------------------------------------------------------------------------------- /code/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /code/.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /code/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.14) 2 | project(code C) 3 | 4 | set(CMAKE_C_STANDARD 99) 5 | 6 | add_executable(code main.c) 7 | add_executable(one_array_transmit_paramter one_array_transmit_paramter.c) 8 | add_executable(double_array_tran_pram double_array_tran_pram.c) 9 | add_executable(funcation_array funcation_array.c) 10 | add_executable(pointer_funcation pointer_funcation.c) 11 | add_executable(sizeof_value sizeof_value.c) 12 | 13 | -------------------------------------------------------------------------------- /code/README.md: -------------------------------------------------------------------------------- 1 | # Code 2 | 3 | ## 数组,函数,指针 4 | 5 | 1. one_array_transmit_paramter.c 6 | 7 | ``` 8 | // 题目一:一维数组的传参方式; 9 | ``` 10 | 11 | 2. double_array_tran_pram.c 12 | 13 | ``` 14 | //题目二:二维数组名的传参方式 15 | ``` 16 | 17 | 3. funcation_array.c 18 | 19 | ``` 20 | // 题目三:函数指针,函数指针数组,函数指针数组的指针 21 | ``` 22 | 23 | 4. pointer_funcation.c 24 | 25 | ``` 26 | // 题目四:指针函数和函数指针的用法 27 | ``` 28 | 29 | 5. sizeof_value.c 30 | 31 | ``` 32 | // sizeof 和strlen的计算; 33 | * 题目一:指针数组和数组指针的计算; 34 | * 题目二:数组名和指针名的计算 35 | * 题目三:指针数组和数组名; 36 | ``` 37 | 38 | 6. memory_visit.c 39 | 40 | ``` 41 | 题目:实现C语言实现程序跳转到绝对地址0x100000处执行 42 | (1)函数调用的方法; 43 | (2)typedef 定义一个函数指针 44 | ``` 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/3.14.5/CMakeCCompiler.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_C_COMPILER "/usr/bin/cc") 2 | set(CMAKE_C_COMPILER_ARG1 "") 3 | set(CMAKE_C_COMPILER_ID "GNU") 4 | set(CMAKE_C_COMPILER_VERSION "7.4.0") 5 | set(CMAKE_C_COMPILER_VERSION_INTERNAL "") 6 | set(CMAKE_C_COMPILER_WRAPPER "") 7 | set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "11") 8 | set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert") 9 | set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") 10 | set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") 11 | set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") 12 | 13 | set(CMAKE_C_PLATFORM_ID "Linux") 14 | set(CMAKE_C_SIMULATE_ID "") 15 | set(CMAKE_C_SIMULATE_VERSION "") 16 | 17 | 18 | 19 | set(CMAKE_AR "/usr/bin/ar") 20 | set(CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar-7") 21 | set(CMAKE_RANLIB "/usr/bin/ranlib") 22 | set(CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib-7") 23 | set(CMAKE_LINKER "/usr/bin/ld") 24 | set(CMAKE_MT "") 25 | set(CMAKE_COMPILER_IS_GNUCC 1) 26 | set(CMAKE_C_COMPILER_LOADED 1) 27 | set(CMAKE_C_COMPILER_WORKS TRUE) 28 | set(CMAKE_C_ABI_COMPILED TRUE) 29 | set(CMAKE_COMPILER_IS_MINGW ) 30 | set(CMAKE_COMPILER_IS_CYGWIN ) 31 | if(CMAKE_COMPILER_IS_CYGWIN) 32 | set(CYGWIN 1) 33 | set(UNIX 1) 34 | endif() 35 | 36 | set(CMAKE_C_COMPILER_ENV_VAR "CC") 37 | 38 | if(CMAKE_COMPILER_IS_MINGW) 39 | set(MINGW 1) 40 | endif() 41 | set(CMAKE_C_COMPILER_ID_RUN 1) 42 | set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) 43 | set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) 44 | set(CMAKE_C_LINKER_PREFERENCE 10) 45 | 46 | # Save compiler ABI information. 47 | set(CMAKE_C_SIZEOF_DATA_PTR "8") 48 | set(CMAKE_C_COMPILER_ABI "ELF") 49 | set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 50 | 51 | if(CMAKE_C_SIZEOF_DATA_PTR) 52 | set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") 53 | endif() 54 | 55 | if(CMAKE_C_COMPILER_ABI) 56 | set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") 57 | endif() 58 | 59 | if(CMAKE_C_LIBRARY_ARCHITECTURE) 60 | set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 61 | endif() 62 | 63 | set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") 64 | if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) 65 | set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") 66 | endif() 67 | 68 | 69 | 70 | 71 | 72 | set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/7/include;/usr/local/include;/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed;/usr/include/x86_64-linux-gnu;/usr/include") 73 | set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s") 74 | set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/7;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") 75 | set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") 76 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/3.14.5/CMakeDetermineCompilerABI_C.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/code/cmake-build-debug/CMakeFiles/3.14.5/CMakeDetermineCompilerABI_C.bin -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/3.14.5/CMakeSystem.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_HOST_SYSTEM "Linux-5.0.0-29-generic") 2 | set(CMAKE_HOST_SYSTEM_NAME "Linux") 3 | set(CMAKE_HOST_SYSTEM_VERSION "5.0.0-29-generic") 4 | set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") 5 | 6 | 7 | 8 | set(CMAKE_SYSTEM "Linux-5.0.0-29-generic") 9 | set(CMAKE_SYSTEM_NAME "Linux") 10 | set(CMAKE_SYSTEM_VERSION "5.0.0-29-generic") 11 | set(CMAKE_SYSTEM_PROCESSOR "x86_64") 12 | 13 | set(CMAKE_CROSSCOMPILING "FALSE") 14 | 15 | set(CMAKE_SYSTEM_LOADED 1) 16 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/3.14.5/CompilerIdC/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/code/cmake-build-debug/CMakeFiles/3.14.5/CompilerIdC/a.out -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/3.15.3/CMakeCCompiler.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_C_COMPILER "/usr/bin/cc") 2 | set(CMAKE_C_COMPILER_ARG1 "") 3 | set(CMAKE_C_COMPILER_ID "GNU") 4 | set(CMAKE_C_COMPILER_VERSION "7.4.0") 5 | set(CMAKE_C_COMPILER_VERSION_INTERNAL "") 6 | set(CMAKE_C_COMPILER_WRAPPER "") 7 | set(CMAKE_C_STANDARD_COMPUTED_DEFAULT "11") 8 | set(CMAKE_C_COMPILE_FEATURES "c_std_90;c_function_prototypes;c_std_99;c_restrict;c_variadic_macros;c_std_11;c_static_assert") 9 | set(CMAKE_C90_COMPILE_FEATURES "c_std_90;c_function_prototypes") 10 | set(CMAKE_C99_COMPILE_FEATURES "c_std_99;c_restrict;c_variadic_macros") 11 | set(CMAKE_C11_COMPILE_FEATURES "c_std_11;c_static_assert") 12 | 13 | set(CMAKE_C_PLATFORM_ID "Linux") 14 | set(CMAKE_C_SIMULATE_ID "") 15 | set(CMAKE_C_COMPILER_FRONTEND_VARIANT "") 16 | set(CMAKE_C_SIMULATE_VERSION "") 17 | 18 | 19 | 20 | set(CMAKE_AR "/usr/bin/ar") 21 | set(CMAKE_C_COMPILER_AR "/usr/bin/gcc-ar-7") 22 | set(CMAKE_RANLIB "/usr/bin/ranlib") 23 | set(CMAKE_C_COMPILER_RANLIB "/usr/bin/gcc-ranlib-7") 24 | set(CMAKE_LINKER "/usr/bin/ld") 25 | set(CMAKE_MT "") 26 | set(CMAKE_COMPILER_IS_GNUCC 1) 27 | set(CMAKE_C_COMPILER_LOADED 1) 28 | set(CMAKE_C_COMPILER_WORKS TRUE) 29 | set(CMAKE_C_ABI_COMPILED TRUE) 30 | set(CMAKE_COMPILER_IS_MINGW ) 31 | set(CMAKE_COMPILER_IS_CYGWIN ) 32 | if(CMAKE_COMPILER_IS_CYGWIN) 33 | set(CYGWIN 1) 34 | set(UNIX 1) 35 | endif() 36 | 37 | set(CMAKE_C_COMPILER_ENV_VAR "CC") 38 | 39 | if(CMAKE_COMPILER_IS_MINGW) 40 | set(MINGW 1) 41 | endif() 42 | set(CMAKE_C_COMPILER_ID_RUN 1) 43 | set(CMAKE_C_SOURCE_FILE_EXTENSIONS c;m) 44 | set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) 45 | set(CMAKE_C_LINKER_PREFERENCE 10) 46 | 47 | # Save compiler ABI information. 48 | set(CMAKE_C_SIZEOF_DATA_PTR "8") 49 | set(CMAKE_C_COMPILER_ABI "ELF") 50 | set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 51 | 52 | if(CMAKE_C_SIZEOF_DATA_PTR) 53 | set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") 54 | endif() 55 | 56 | if(CMAKE_C_COMPILER_ABI) 57 | set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") 58 | endif() 59 | 60 | if(CMAKE_C_LIBRARY_ARCHITECTURE) 61 | set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") 62 | endif() 63 | 64 | set(CMAKE_C_CL_SHOWINCLUDES_PREFIX "") 65 | if(CMAKE_C_CL_SHOWINCLUDES_PREFIX) 66 | set(CMAKE_CL_SHOWINCLUDES_PREFIX "${CMAKE_C_CL_SHOWINCLUDES_PREFIX}") 67 | endif() 68 | 69 | 70 | 71 | 72 | 73 | set(CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/7/include;/usr/local/include;/usr/lib/gcc/x86_64-linux-gnu/7/include-fixed;/usr/include/x86_64-linux-gnu;/usr/include") 74 | set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "gcc;gcc_s;c;gcc;gcc_s") 75 | set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/7;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") 76 | set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") 77 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/3.15.3/CMakeDetermineCompilerABI_C.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/code/cmake-build-debug/CMakeFiles/3.15.3/CMakeDetermineCompilerABI_C.bin -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/3.15.3/CMakeSystem.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_HOST_SYSTEM "Linux-5.0.0-29-generic") 2 | set(CMAKE_HOST_SYSTEM_NAME "Linux") 3 | set(CMAKE_HOST_SYSTEM_VERSION "5.0.0-29-generic") 4 | set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") 5 | 6 | 7 | 8 | set(CMAKE_SYSTEM "Linux-5.0.0-29-generic") 9 | set(CMAKE_SYSTEM_NAME "Linux") 10 | set(CMAKE_SYSTEM_VERSION "5.0.0-29-generic") 11 | set(CMAKE_SYSTEM_PROCESSOR "x86_64") 12 | 13 | set(CMAKE_CROSSCOMPILING "FALSE") 14 | 15 | set(CMAKE_SYSTEM_LOADED 1) 16 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/3.15.3/CompilerIdC/a.out: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/code/cmake-build-debug/CMakeFiles/3.15.3/CompilerIdC/a.out -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/CMakeDirectoryInformation.cmake: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.15 3 | 4 | # Relative path conversion top directories. 5 | set(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/quronghui/HustFiles/Embedded-written-reference/code") 6 | set(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug") 7 | 8 | # Force unix paths in dependencies. 9 | set(CMAKE_FORCE_UNIX_PATHS 1) 10 | 11 | 12 | # The C and CXX include file regular expressions for this directory. 13 | set(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") 14 | set(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") 15 | set(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) 16 | set(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) 17 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/TargetDirectories.txt: -------------------------------------------------------------------------------- 1 | /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/edit_cache.dir 2 | /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/one_array_transmit_paramter.dir 3 | /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/rebuild_cache.dir 4 | /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/funcation_array.dir 5 | /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/code.dir 6 | /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/double_array_tran_pram.dir 7 | /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/pointer_funcation.dir 8 | /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/sizeof_value.dir 9 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/array_transmit_paramter.dir/C.includecache: -------------------------------------------------------------------------------- 1 | #IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) 2 | 3 | #IncludeRegexScan: ^.*$ 4 | 5 | #IncludeRegexComplain: ^$ 6 | 7 | #IncludeRegexTransform: 8 | 9 | /home/quronghui/HustFiles/Embedded-written-reference/code/array_transmit_paramter.c 10 | stdio.h 11 | - 12 | string.h 13 | - 14 | 15 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/array_transmit_paramter.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | # The set of languages for which implicit dependencies are needed: 2 | set(CMAKE_DEPENDS_LANGUAGES 3 | "C" 4 | ) 5 | # The set of files for implicit dependencies of each language: 6 | set(CMAKE_DEPENDS_CHECK_C 7 | "/home/quronghui/HustFiles/Embedded-written-reference/code/one_array_transmit_paramter.c" "/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/array_transmit_paramter.dir/one_array_transmit_paramter.c.o" 8 | ) 9 | set(CMAKE_C_COMPILER_ID "GNU") 10 | 11 | # The include file search paths: 12 | set(CMAKE_C_TARGET_INCLUDE_PATH 13 | ) 14 | 15 | # Targets to which this target links. 16 | set(CMAKE_TARGET_LINKED_INFO_FILES 17 | ) 18 | 19 | # Fortran module output directory. 20 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 21 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/array_transmit_paramter.dir/array_transmit_paramter.c.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/code/cmake-build-debug/CMakeFiles/array_transmit_paramter.dir/array_transmit_paramter.c.o -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/array_transmit_paramter.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/array_transmit_paramter.dir/one_array_transmit_paramter.c.o" 3 | "array_transmit_paramter.pdb" 4 | "array_transmit_paramter" 5 | ) 6 | 7 | # Per-language clean rules from dependency scanning. 8 | foreach(lang C) 9 | include(CMakeFiles/array_transmit_paramter.dir/cmake_clean_${lang}.cmake OPTIONAL) 10 | endforeach() 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/array_transmit_paramter.dir/depend.internal: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.14 3 | 4 | CMakeFiles/array_transmit_paramter.dir/array_transmit_paramter.c.o 5 | /home/quronghui/HustFiles/Embedded-written-reference/code/array_transmit_paramter.c 6 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/array_transmit_paramter.dir/depend.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.14 3 | 4 | CMakeFiles/array_transmit_paramter.dir/array_transmit_paramter.c.o: ../array_transmit_paramter.c 5 | 6 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/array_transmit_paramter.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.14 3 | 4 | # compile C with /usr/bin/cc 5 | C_FLAGS = -g -std=gnu99 6 | 7 | C_DEFINES = 8 | 9 | C_INCLUDES = 10 | 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/array_transmit_paramter.dir/link.txt: -------------------------------------------------------------------------------- 1 | /usr/bin/cc -g CMakeFiles/array_transmit_paramter.dir/one_array_transmit_paramter.c.o -o array_transmit_paramter 2 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/array_transmit_paramter.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 1 2 | CMAKE_PROGRESS_2 = 2 3 | 4 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/clion-environment.txt: -------------------------------------------------------------------------------- 1 | ToolSet: 1.0 (local)Options: 2 | 3 | Options: -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/clion-log.txt: -------------------------------------------------------------------------------- 1 | /opt/clion/bin/cmake/linux/bin/cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" /home/quronghui/HustFiles/Embedded-written-reference/code 2 | -- The C compiler identification is GNU 7.4.0 3 | -- Check for working C compiler: /usr/bin/cc 4 | -- Check for working C compiler: /usr/bin/cc -- works 5 | -- Detecting C compiler ABI info 6 | -- Detecting C compiler ABI info - done 7 | -- Detecting C compile features 8 | -- Detecting C compile features - done 9 | -- Configuring done 10 | -- Generating done 11 | -- Build files have been written to: /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug 12 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/cmake.check_cache: -------------------------------------------------------------------------------- 1 | # This file is generated by cmake for dependency checking of the CMakeCache.txt file 2 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/code.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | # The set of languages for which implicit dependencies are needed: 2 | set(CMAKE_DEPENDS_LANGUAGES 3 | "C" 4 | ) 5 | # The set of files for implicit dependencies of each language: 6 | set(CMAKE_DEPENDS_CHECK_C 7 | "/home/quronghui/HustFiles/Embedded-written-reference/code/main.c" "/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/code.dir/main.c.o" 8 | ) 9 | set(CMAKE_C_COMPILER_ID "GNU") 10 | 11 | # The include file search paths: 12 | set(CMAKE_C_TARGET_INCLUDE_PATH 13 | ) 14 | 15 | # Targets to which this target links. 16 | set(CMAKE_TARGET_LINKED_INFO_FILES 17 | ) 18 | 19 | # Fortran module output directory. 20 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 21 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/code.dir/build.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.15 3 | 4 | # Delete rule output on recipe failure. 5 | .DELETE_ON_ERROR: 6 | 7 | 8 | #============================================================================= 9 | # Special targets provided by cmake. 10 | 11 | # Disable implicit rules so canonical targets will work. 12 | .SUFFIXES: 13 | 14 | 15 | # Remove some rules from gmake that .SUFFIXES does not remove. 16 | SUFFIXES = 17 | 18 | .SUFFIXES: .hpux_make_needs_suffix_list 19 | 20 | 21 | # Suppress display of executed commands. 22 | $(VERBOSE).SILENT: 23 | 24 | 25 | # A target that is always out of date. 26 | cmake_force: 27 | 28 | .PHONY : cmake_force 29 | 30 | #============================================================================= 31 | # Set environment variables for the build. 32 | 33 | # The shell in which to execute make rules. 34 | SHELL = /bin/sh 35 | 36 | # The CMake executable. 37 | CMAKE_COMMAND = /opt/clion/bin/cmake/linux/bin/cmake 38 | 39 | # The command to remove a file. 40 | RM = /opt/clion/bin/cmake/linux/bin/cmake -E remove -f 41 | 42 | # Escaping for special characters. 43 | EQUALS = = 44 | 45 | # The top-level source directory on which CMake was run. 46 | CMAKE_SOURCE_DIR = /home/quronghui/HustFiles/Embedded-written-reference/code 47 | 48 | # The top-level build directory on which CMake was run. 49 | CMAKE_BINARY_DIR = /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug 50 | 51 | # Include any dependencies generated for this target. 52 | include CMakeFiles/code.dir/depend.make 53 | 54 | # Include the progress variables for this target. 55 | include CMakeFiles/code.dir/progress.make 56 | 57 | # Include the compile flags for this target's objects. 58 | include CMakeFiles/code.dir/flags.make 59 | 60 | CMakeFiles/code.dir/main.c.o: CMakeFiles/code.dir/flags.make 61 | CMakeFiles/code.dir/main.c.o: ../main.c 62 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/code.dir/main.c.o" 63 | /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/code.dir/main.c.o -c /home/quronghui/HustFiles/Embedded-written-reference/code/main.c 64 | 65 | CMakeFiles/code.dir/main.c.i: cmake_force 66 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/code.dir/main.c.i" 67 | /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/quronghui/HustFiles/Embedded-written-reference/code/main.c > CMakeFiles/code.dir/main.c.i 68 | 69 | CMakeFiles/code.dir/main.c.s: cmake_force 70 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/code.dir/main.c.s" 71 | /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/quronghui/HustFiles/Embedded-written-reference/code/main.c -o CMakeFiles/code.dir/main.c.s 72 | 73 | # Object files for target code 74 | code_OBJECTS = \ 75 | "CMakeFiles/code.dir/main.c.o" 76 | 77 | # External object files for target code 78 | code_EXTERNAL_OBJECTS = 79 | 80 | code: CMakeFiles/code.dir/main.c.o 81 | code: CMakeFiles/code.dir/build.make 82 | code: CMakeFiles/code.dir/link.txt 83 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking C executable code" 84 | $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/code.dir/link.txt --verbose=$(VERBOSE) 85 | 86 | # Rule to build all files generated by this target. 87 | CMakeFiles/code.dir/build: code 88 | 89 | .PHONY : CMakeFiles/code.dir/build 90 | 91 | CMakeFiles/code.dir/clean: 92 | $(CMAKE_COMMAND) -P CMakeFiles/code.dir/cmake_clean.cmake 93 | .PHONY : CMakeFiles/code.dir/clean 94 | 95 | CMakeFiles/code.dir/depend: 96 | cd /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/quronghui/HustFiles/Embedded-written-reference/code /home/quronghui/HustFiles/Embedded-written-reference/code /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/code.dir/DependInfo.cmake --color=$(COLOR) 97 | .PHONY : CMakeFiles/code.dir/depend 98 | 99 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/code.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/code.dir/main.c.o" 3 | "code" 4 | "code.pdb" 5 | ) 6 | 7 | # Per-language clean rules from dependency scanning. 8 | foreach(lang C) 9 | include(CMakeFiles/code.dir/cmake_clean_${lang}.cmake OPTIONAL) 10 | endforeach() 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/code.dir/depend.make: -------------------------------------------------------------------------------- 1 | # Empty dependencies file for code. 2 | # This may be replaced when dependencies are built. 3 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/code.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.15 3 | 4 | # compile C with /usr/bin/cc 5 | C_FLAGS = -g -std=gnu99 6 | 7 | C_DEFINES = 8 | 9 | C_INCLUDES = 10 | 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/code.dir/link.txt: -------------------------------------------------------------------------------- 1 | /usr/bin/cc -g CMakeFiles/code.dir/main.c.o -o code 2 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/code.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 1 2 | CMAKE_PROGRESS_2 = 2 3 | 4 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/double_array_tran_pram.dir/C.includecache: -------------------------------------------------------------------------------- 1 | #IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) 2 | 3 | #IncludeRegexScan: ^.*$ 4 | 5 | #IncludeRegexComplain: ^$ 6 | 7 | #IncludeRegexTransform: 8 | 9 | /home/quronghui/HustFiles/Embedded-written-reference/code/double_array_tran_pram.c 10 | stdio.h 11 | - 12 | 13 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/double_array_tran_pram.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | # The set of languages for which implicit dependencies are needed: 2 | set(CMAKE_DEPENDS_LANGUAGES 3 | "C" 4 | ) 5 | # The set of files for implicit dependencies of each language: 6 | set(CMAKE_DEPENDS_CHECK_C 7 | "/home/quronghui/HustFiles/Embedded-written-reference/code/double_array_tran_pram.c" "/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/double_array_tran_pram.dir/double_array_tran_pram.c.o" 8 | ) 9 | set(CMAKE_C_COMPILER_ID "GNU") 10 | 11 | # The include file search paths: 12 | set(CMAKE_C_TARGET_INCLUDE_PATH 13 | ) 14 | 15 | # Targets to which this target links. 16 | set(CMAKE_TARGET_LINKED_INFO_FILES 17 | ) 18 | 19 | # Fortran module output directory. 20 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 21 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/double_array_tran_pram.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/double_array_tran_pram.dir/double_array_tran_pram.c.o" 3 | "double_array_tran_pram" 4 | "double_array_tran_pram.pdb" 5 | ) 6 | 7 | # Per-language clean rules from dependency scanning. 8 | foreach(lang C) 9 | include(CMakeFiles/double_array_tran_pram.dir/cmake_clean_${lang}.cmake OPTIONAL) 10 | endforeach() 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/double_array_tran_pram.dir/depend.internal: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.14 3 | 4 | CMakeFiles/double_array_tran_pram.dir/double_array_tran_pram.c.o 5 | /home/quronghui/HustFiles/Embedded-written-reference/code/double_array_tran_pram.c 6 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/double_array_tran_pram.dir/depend.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.14 3 | 4 | CMakeFiles/double_array_tran_pram.dir/double_array_tran_pram.c.o: ../double_array_tran_pram.c 5 | 6 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/double_array_tran_pram.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.15 3 | 4 | # compile C with /usr/bin/cc 5 | C_FLAGS = -g -std=gnu99 6 | 7 | C_DEFINES = 8 | 9 | C_INCLUDES = 10 | 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/double_array_tran_pram.dir/link.txt: -------------------------------------------------------------------------------- 1 | /usr/bin/cc -g CMakeFiles/double_array_tran_pram.dir/double_array_tran_pram.c.o -o double_array_tran_pram 2 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/double_array_tran_pram.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 3 2 | CMAKE_PROGRESS_2 = 4 3 | 4 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/feature_tests.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/code/cmake-build-debug/CMakeFiles/feature_tests.bin -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/feature_tests.c: -------------------------------------------------------------------------------- 1 | 2 | const char features[] = {"\n" 3 | "C_FEATURE:" 4 | #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 304 5 | "1" 6 | #else 7 | "0" 8 | #endif 9 | "c_function_prototypes\n" 10 | "C_FEATURE:" 11 | #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 12 | "1" 13 | #else 14 | "0" 15 | #endif 16 | "c_restrict\n" 17 | "C_FEATURE:" 18 | #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201000L 19 | "1" 20 | #else 21 | "0" 22 | #endif 23 | "c_static_assert\n" 24 | "C_FEATURE:" 25 | #if (__GNUC__ * 100 + __GNUC_MINOR__) >= 304 && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L 26 | "1" 27 | #else 28 | "0" 29 | #endif 30 | "c_variadic_macros\n" 31 | 32 | }; 33 | 34 | int main(int argc, char** argv) { (void)argv; return features[argc]; } 35 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/funcation_array.dir/C.includecache: -------------------------------------------------------------------------------- 1 | #IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) 2 | 3 | #IncludeRegexScan: ^.*$ 4 | 5 | #IncludeRegexComplain: ^$ 6 | 7 | #IncludeRegexTransform: 8 | 9 | /home/quronghui/HustFiles/Embedded-written-reference/code/funcation_array.c 10 | stdio.h 11 | - 12 | 13 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/funcation_array.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | # The set of languages for which implicit dependencies are needed: 2 | set(CMAKE_DEPENDS_LANGUAGES 3 | "C" 4 | ) 5 | # The set of files for implicit dependencies of each language: 6 | set(CMAKE_DEPENDS_CHECK_C 7 | "/home/quronghui/HustFiles/Embedded-written-reference/code/funcation_array.c" "/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/funcation_array.dir/funcation_array.c.o" 8 | ) 9 | set(CMAKE_C_COMPILER_ID "GNU") 10 | 11 | # The include file search paths: 12 | set(CMAKE_C_TARGET_INCLUDE_PATH 13 | ) 14 | 15 | # Targets to which this target links. 16 | set(CMAKE_TARGET_LINKED_INFO_FILES 17 | ) 18 | 19 | # Fortran module output directory. 20 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 21 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/funcation_array.dir/build.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.15 3 | 4 | # Delete rule output on recipe failure. 5 | .DELETE_ON_ERROR: 6 | 7 | 8 | #============================================================================= 9 | # Special targets provided by cmake. 10 | 11 | # Disable implicit rules so canonical targets will work. 12 | .SUFFIXES: 13 | 14 | 15 | # Remove some rules from gmake that .SUFFIXES does not remove. 16 | SUFFIXES = 17 | 18 | .SUFFIXES: .hpux_make_needs_suffix_list 19 | 20 | 21 | # Suppress display of executed commands. 22 | $(VERBOSE).SILENT: 23 | 24 | 25 | # A target that is always out of date. 26 | cmake_force: 27 | 28 | .PHONY : cmake_force 29 | 30 | #============================================================================= 31 | # Set environment variables for the build. 32 | 33 | # The shell in which to execute make rules. 34 | SHELL = /bin/sh 35 | 36 | # The CMake executable. 37 | CMAKE_COMMAND = /opt/clion/bin/cmake/linux/bin/cmake 38 | 39 | # The command to remove a file. 40 | RM = /opt/clion/bin/cmake/linux/bin/cmake -E remove -f 41 | 42 | # Escaping for special characters. 43 | EQUALS = = 44 | 45 | # The top-level source directory on which CMake was run. 46 | CMAKE_SOURCE_DIR = /home/quronghui/HustFiles/Embedded-written-reference/code 47 | 48 | # The top-level build directory on which CMake was run. 49 | CMAKE_BINARY_DIR = /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug 50 | 51 | # Include any dependencies generated for this target. 52 | include CMakeFiles/funcation_array.dir/depend.make 53 | 54 | # Include the progress variables for this target. 55 | include CMakeFiles/funcation_array.dir/progress.make 56 | 57 | # Include the compile flags for this target's objects. 58 | include CMakeFiles/funcation_array.dir/flags.make 59 | 60 | CMakeFiles/funcation_array.dir/funcation_array.c.o: CMakeFiles/funcation_array.dir/flags.make 61 | CMakeFiles/funcation_array.dir/funcation_array.c.o: ../funcation_array.c 62 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/funcation_array.dir/funcation_array.c.o" 63 | /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/funcation_array.dir/funcation_array.c.o -c /home/quronghui/HustFiles/Embedded-written-reference/code/funcation_array.c 64 | 65 | CMakeFiles/funcation_array.dir/funcation_array.c.i: cmake_force 66 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/funcation_array.dir/funcation_array.c.i" 67 | /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/quronghui/HustFiles/Embedded-written-reference/code/funcation_array.c > CMakeFiles/funcation_array.dir/funcation_array.c.i 68 | 69 | CMakeFiles/funcation_array.dir/funcation_array.c.s: cmake_force 70 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/funcation_array.dir/funcation_array.c.s" 71 | /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/quronghui/HustFiles/Embedded-written-reference/code/funcation_array.c -o CMakeFiles/funcation_array.dir/funcation_array.c.s 72 | 73 | # Object files for target funcation_array 74 | funcation_array_OBJECTS = \ 75 | "CMakeFiles/funcation_array.dir/funcation_array.c.o" 76 | 77 | # External object files for target funcation_array 78 | funcation_array_EXTERNAL_OBJECTS = 79 | 80 | funcation_array: CMakeFiles/funcation_array.dir/funcation_array.c.o 81 | funcation_array: CMakeFiles/funcation_array.dir/build.make 82 | funcation_array: CMakeFiles/funcation_array.dir/link.txt 83 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking C executable funcation_array" 84 | $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/funcation_array.dir/link.txt --verbose=$(VERBOSE) 85 | 86 | # Rule to build all files generated by this target. 87 | CMakeFiles/funcation_array.dir/build: funcation_array 88 | 89 | .PHONY : CMakeFiles/funcation_array.dir/build 90 | 91 | CMakeFiles/funcation_array.dir/clean: 92 | $(CMAKE_COMMAND) -P CMakeFiles/funcation_array.dir/cmake_clean.cmake 93 | .PHONY : CMakeFiles/funcation_array.dir/clean 94 | 95 | CMakeFiles/funcation_array.dir/depend: 96 | cd /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/quronghui/HustFiles/Embedded-written-reference/code /home/quronghui/HustFiles/Embedded-written-reference/code /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/funcation_array.dir/DependInfo.cmake --color=$(COLOR) 97 | .PHONY : CMakeFiles/funcation_array.dir/depend 98 | 99 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/funcation_array.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/funcation_array.dir/funcation_array.c.o" 3 | "funcation_array" 4 | "funcation_array.pdb" 5 | ) 6 | 7 | # Per-language clean rules from dependency scanning. 8 | foreach(lang C) 9 | include(CMakeFiles/funcation_array.dir/cmake_clean_${lang}.cmake OPTIONAL) 10 | endforeach() 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/funcation_array.dir/depend.internal: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.14 3 | 4 | CMakeFiles/funcation_array.dir/funcation_array.c.o 5 | /home/quronghui/HustFiles/Embedded-written-reference/code/funcation_array.c 6 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/funcation_array.dir/depend.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.14 3 | 4 | CMakeFiles/funcation_array.dir/funcation_array.c.o: ../funcation_array.c 5 | 6 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/funcation_array.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.15 3 | 4 | # compile C with /usr/bin/cc 5 | C_FLAGS = -g -std=gnu99 6 | 7 | C_DEFINES = 8 | 9 | C_INCLUDES = 10 | 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/funcation_array.dir/link.txt: -------------------------------------------------------------------------------- 1 | /usr/bin/cc -g CMakeFiles/funcation_array.dir/funcation_array.c.o -o funcation_array 2 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/funcation_array.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 5 2 | CMAKE_PROGRESS_2 = 6 3 | 4 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/one_array_transmit_paramter.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | # The set of languages for which implicit dependencies are needed: 2 | set(CMAKE_DEPENDS_LANGUAGES 3 | "C" 4 | ) 5 | # The set of files for implicit dependencies of each language: 6 | set(CMAKE_DEPENDS_CHECK_C 7 | "/home/quronghui/HustFiles/Embedded-written-reference/code/one_array_transmit_paramter.c" "/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/one_array_transmit_paramter.dir/one_array_transmit_paramter.c.o" 8 | ) 9 | set(CMAKE_C_COMPILER_ID "GNU") 10 | 11 | # The include file search paths: 12 | set(CMAKE_C_TARGET_INCLUDE_PATH 13 | ) 14 | 15 | # Targets to which this target links. 16 | set(CMAKE_TARGET_LINKED_INFO_FILES 17 | ) 18 | 19 | # Fortran module output directory. 20 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 21 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/one_array_transmit_paramter.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/one_array_transmit_paramter.dir/one_array_transmit_paramter.c.o" 3 | "one_array_transmit_paramter" 4 | "one_array_transmit_paramter.pdb" 5 | ) 6 | 7 | # Per-language clean rules from dependency scanning. 8 | foreach(lang C) 9 | include(CMakeFiles/one_array_transmit_paramter.dir/cmake_clean_${lang}.cmake OPTIONAL) 10 | endforeach() 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/one_array_transmit_paramter.dir/depend.make: -------------------------------------------------------------------------------- 1 | # Empty dependencies file for one_array_transmit_paramter. 2 | # This may be replaced when dependencies are built. 3 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/one_array_transmit_paramter.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.15 3 | 4 | # compile C with /usr/bin/cc 5 | C_FLAGS = -g -std=gnu99 6 | 7 | C_DEFINES = 8 | 9 | C_INCLUDES = 10 | 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/one_array_transmit_paramter.dir/link.txt: -------------------------------------------------------------------------------- 1 | /usr/bin/cc -g CMakeFiles/one_array_transmit_paramter.dir/one_array_transmit_paramter.c.o -o one_array_transmit_paramter 2 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/one_array_transmit_paramter.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 7 2 | CMAKE_PROGRESS_2 = 8 3 | 4 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/pointer_funcation.dir/C.includecache: -------------------------------------------------------------------------------- 1 | #IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) 2 | 3 | #IncludeRegexScan: ^.*$ 4 | 5 | #IncludeRegexComplain: ^$ 6 | 7 | #IncludeRegexTransform: 8 | 9 | /home/quronghui/HustFiles/Embedded-written-reference/code/pointer_funcation.c 10 | stdio.h 11 | - 12 | malloc.h 13 | - 14 | 15 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/pointer_funcation.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | # The set of languages for which implicit dependencies are needed: 2 | set(CMAKE_DEPENDS_LANGUAGES 3 | "C" 4 | ) 5 | # The set of files for implicit dependencies of each language: 6 | set(CMAKE_DEPENDS_CHECK_C 7 | "/home/quronghui/HustFiles/Embedded-written-reference/code/pointer_funcation.c" "/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/pointer_funcation.dir/pointer_funcation.c.o" 8 | ) 9 | set(CMAKE_C_COMPILER_ID "GNU") 10 | 11 | # The include file search paths: 12 | set(CMAKE_C_TARGET_INCLUDE_PATH 13 | ) 14 | 15 | # Targets to which this target links. 16 | set(CMAKE_TARGET_LINKED_INFO_FILES 17 | ) 18 | 19 | # Fortran module output directory. 20 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 21 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/pointer_funcation.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/pointer_funcation.dir/pointer_funcation.c.o" 3 | "pointer_funcation" 4 | "pointer_funcation.pdb" 5 | ) 6 | 7 | # Per-language clean rules from dependency scanning. 8 | foreach(lang C) 9 | include(CMakeFiles/pointer_funcation.dir/cmake_clean_${lang}.cmake OPTIONAL) 10 | endforeach() 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/pointer_funcation.dir/depend.internal: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.14 3 | 4 | CMakeFiles/pointer_funcation.dir/pointer_funcation.c.o 5 | /home/quronghui/HustFiles/Embedded-written-reference/code/pointer_funcation.c 6 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/pointer_funcation.dir/depend.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.14 3 | 4 | CMakeFiles/pointer_funcation.dir/pointer_funcation.c.o: ../pointer_funcation.c 5 | 6 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/pointer_funcation.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.15 3 | 4 | # compile C with /usr/bin/cc 5 | C_FLAGS = -g -std=gnu99 6 | 7 | C_DEFINES = 8 | 9 | C_INCLUDES = 10 | 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/pointer_funcation.dir/link.txt: -------------------------------------------------------------------------------- 1 | /usr/bin/cc -g CMakeFiles/pointer_funcation.dir/pointer_funcation.c.o -o pointer_funcation 2 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/pointer_funcation.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 9 2 | CMAKE_PROGRESS_2 = 10 3 | 4 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/progress.marks: -------------------------------------------------------------------------------- 1 | 12 2 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/sizeof_value.dir/C.includecache: -------------------------------------------------------------------------------- 1 | #IncludeRegexLine: ^[ ]*[#%][ ]*(include|import)[ ]*[<"]([^">]+)([">]) 2 | 3 | #IncludeRegexScan: ^.*$ 4 | 5 | #IncludeRegexComplain: ^$ 6 | 7 | #IncludeRegexTransform: 8 | 9 | /home/quronghui/HustFiles/Embedded-written-reference/code/sizeof_value.c 10 | stdio.h 11 | - 12 | string.h 13 | - 14 | 15 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/sizeof_value.dir/DependInfo.cmake: -------------------------------------------------------------------------------- 1 | # The set of languages for which implicit dependencies are needed: 2 | set(CMAKE_DEPENDS_LANGUAGES 3 | "C" 4 | ) 5 | # The set of files for implicit dependencies of each language: 6 | set(CMAKE_DEPENDS_CHECK_C 7 | "/home/quronghui/HustFiles/Embedded-written-reference/code/sizeof_value.c" "/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/sizeof_value.dir/sizeof_value.c.o" 8 | ) 9 | set(CMAKE_C_COMPILER_ID "GNU") 10 | 11 | # The include file search paths: 12 | set(CMAKE_C_TARGET_INCLUDE_PATH 13 | ) 14 | 15 | # Targets to which this target links. 16 | set(CMAKE_TARGET_LINKED_INFO_FILES 17 | ) 18 | 19 | # Fortran module output directory. 20 | set(CMAKE_Fortran_TARGET_MODULE_DIR "") 21 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/sizeof_value.dir/build.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.15 3 | 4 | # Delete rule output on recipe failure. 5 | .DELETE_ON_ERROR: 6 | 7 | 8 | #============================================================================= 9 | # Special targets provided by cmake. 10 | 11 | # Disable implicit rules so canonical targets will work. 12 | .SUFFIXES: 13 | 14 | 15 | # Remove some rules from gmake that .SUFFIXES does not remove. 16 | SUFFIXES = 17 | 18 | .SUFFIXES: .hpux_make_needs_suffix_list 19 | 20 | 21 | # Suppress display of executed commands. 22 | $(VERBOSE).SILENT: 23 | 24 | 25 | # A target that is always out of date. 26 | cmake_force: 27 | 28 | .PHONY : cmake_force 29 | 30 | #============================================================================= 31 | # Set environment variables for the build. 32 | 33 | # The shell in which to execute make rules. 34 | SHELL = /bin/sh 35 | 36 | # The CMake executable. 37 | CMAKE_COMMAND = /opt/clion/bin/cmake/linux/bin/cmake 38 | 39 | # The command to remove a file. 40 | RM = /opt/clion/bin/cmake/linux/bin/cmake -E remove -f 41 | 42 | # Escaping for special characters. 43 | EQUALS = = 44 | 45 | # The top-level source directory on which CMake was run. 46 | CMAKE_SOURCE_DIR = /home/quronghui/HustFiles/Embedded-written-reference/code 47 | 48 | # The top-level build directory on which CMake was run. 49 | CMAKE_BINARY_DIR = /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug 50 | 51 | # Include any dependencies generated for this target. 52 | include CMakeFiles/sizeof_value.dir/depend.make 53 | 54 | # Include the progress variables for this target. 55 | include CMakeFiles/sizeof_value.dir/progress.make 56 | 57 | # Include the compile flags for this target's objects. 58 | include CMakeFiles/sizeof_value.dir/flags.make 59 | 60 | CMakeFiles/sizeof_value.dir/sizeof_value.c.o: CMakeFiles/sizeof_value.dir/flags.make 61 | CMakeFiles/sizeof_value.dir/sizeof_value.c.o: ../sizeof_value.c 62 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --progress-dir=/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles --progress-num=$(CMAKE_PROGRESS_1) "Building C object CMakeFiles/sizeof_value.dir/sizeof_value.c.o" 63 | /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -o CMakeFiles/sizeof_value.dir/sizeof_value.c.o -c /home/quronghui/HustFiles/Embedded-written-reference/code/sizeof_value.c 64 | 65 | CMakeFiles/sizeof_value.dir/sizeof_value.c.i: cmake_force 66 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing C source to CMakeFiles/sizeof_value.dir/sizeof_value.c.i" 67 | /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -E /home/quronghui/HustFiles/Embedded-written-reference/code/sizeof_value.c > CMakeFiles/sizeof_value.dir/sizeof_value.c.i 68 | 69 | CMakeFiles/sizeof_value.dir/sizeof_value.c.s: cmake_force 70 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling C source to assembly CMakeFiles/sizeof_value.dir/sizeof_value.c.s" 71 | /usr/bin/cc $(C_DEFINES) $(C_INCLUDES) $(C_FLAGS) -S /home/quronghui/HustFiles/Embedded-written-reference/code/sizeof_value.c -o CMakeFiles/sizeof_value.dir/sizeof_value.c.s 72 | 73 | # Object files for target sizeof_value 74 | sizeof_value_OBJECTS = \ 75 | "CMakeFiles/sizeof_value.dir/sizeof_value.c.o" 76 | 77 | # External object files for target sizeof_value 78 | sizeof_value_EXTERNAL_OBJECTS = 79 | 80 | sizeof_value: CMakeFiles/sizeof_value.dir/sizeof_value.c.o 81 | sizeof_value: CMakeFiles/sizeof_value.dir/build.make 82 | sizeof_value: CMakeFiles/sizeof_value.dir/link.txt 83 | @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green --bold --progress-dir=/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles --progress-num=$(CMAKE_PROGRESS_2) "Linking C executable sizeof_value" 84 | $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/sizeof_value.dir/link.txt --verbose=$(VERBOSE) 85 | 86 | # Rule to build all files generated by this target. 87 | CMakeFiles/sizeof_value.dir/build: sizeof_value 88 | 89 | .PHONY : CMakeFiles/sizeof_value.dir/build 90 | 91 | CMakeFiles/sizeof_value.dir/clean: 92 | $(CMAKE_COMMAND) -P CMakeFiles/sizeof_value.dir/cmake_clean.cmake 93 | .PHONY : CMakeFiles/sizeof_value.dir/clean 94 | 95 | CMakeFiles/sizeof_value.dir/depend: 96 | cd /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/quronghui/HustFiles/Embedded-written-reference/code /home/quronghui/HustFiles/Embedded-written-reference/code /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug /home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/CMakeFiles/sizeof_value.dir/DependInfo.cmake --color=$(COLOR) 97 | .PHONY : CMakeFiles/sizeof_value.dir/depend 98 | 99 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/sizeof_value.dir/cmake_clean.cmake: -------------------------------------------------------------------------------- 1 | file(REMOVE_RECURSE 2 | "CMakeFiles/sizeof_value.dir/sizeof_value.c.o" 3 | "sizeof_value" 4 | "sizeof_value.pdb" 5 | ) 6 | 7 | # Per-language clean rules from dependency scanning. 8 | foreach(lang C) 9 | include(CMakeFiles/sizeof_value.dir/cmake_clean_${lang}.cmake OPTIONAL) 10 | endforeach() 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/sizeof_value.dir/depend.internal: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.15 3 | 4 | CMakeFiles/sizeof_value.dir/sizeof_value.c.o 5 | /home/quronghui/HustFiles/Embedded-written-reference/code/sizeof_value.c 6 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/sizeof_value.dir/depend.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.15 3 | 4 | CMakeFiles/sizeof_value.dir/sizeof_value.c.o: ../sizeof_value.c 5 | 6 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/sizeof_value.dir/flags.make: -------------------------------------------------------------------------------- 1 | # CMAKE generated file: DO NOT EDIT! 2 | # Generated by "Unix Makefiles" Generator, CMake Version 3.15 3 | 4 | # compile C with /usr/bin/cc 5 | C_FLAGS = -g -std=gnu99 6 | 7 | C_DEFINES = 8 | 9 | C_INCLUDES = 10 | 11 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/sizeof_value.dir/link.txt: -------------------------------------------------------------------------------- 1 | /usr/bin/cc -g CMakeFiles/sizeof_value.dir/sizeof_value.c.o -o sizeof_value 2 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/sizeof_value.dir/progress.make: -------------------------------------------------------------------------------- 1 | CMAKE_PROGRESS_1 = 11 2 | CMAKE_PROGRESS_2 = 12 3 | 4 | -------------------------------------------------------------------------------- /code/cmake-build-debug/CMakeFiles/sizeof_value.dir/sizeof_value.c.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/code/cmake-build-debug/CMakeFiles/sizeof_value.dir/sizeof_value.c.o -------------------------------------------------------------------------------- /code/cmake-build-debug/array_transmit_paramter: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/code/cmake-build-debug/array_transmit_paramter -------------------------------------------------------------------------------- /code/cmake-build-debug/cmake_install.cmake: -------------------------------------------------------------------------------- 1 | # Install script for directory: /home/quronghui/HustFiles/Embedded-written-reference/code 2 | 3 | # Set the install prefix 4 | if(NOT DEFINED CMAKE_INSTALL_PREFIX) 5 | set(CMAKE_INSTALL_PREFIX "/usr/local") 6 | endif() 7 | string(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") 8 | 9 | # Set the install configuration name. 10 | if(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) 11 | if(BUILD_TYPE) 12 | string(REGEX REPLACE "^[^A-Za-z0-9_]+" "" 13 | CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") 14 | else() 15 | set(CMAKE_INSTALL_CONFIG_NAME "Debug") 16 | endif() 17 | message(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") 18 | endif() 19 | 20 | # Set the component getting installed. 21 | if(NOT CMAKE_INSTALL_COMPONENT) 22 | if(COMPONENT) 23 | message(STATUS "Install component: \"${COMPONENT}\"") 24 | set(CMAKE_INSTALL_COMPONENT "${COMPONENT}") 25 | else() 26 | set(CMAKE_INSTALL_COMPONENT) 27 | endif() 28 | endif() 29 | 30 | # Install shared libraries without execute permission? 31 | if(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) 32 | set(CMAKE_INSTALL_SO_NO_EXE "1") 33 | endif() 34 | 35 | # Is this installation the result of a crosscompile? 36 | if(NOT DEFINED CMAKE_CROSSCOMPILING) 37 | set(CMAKE_CROSSCOMPILING "FALSE") 38 | endif() 39 | 40 | if(CMAKE_INSTALL_COMPONENT) 41 | set(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") 42 | else() 43 | set(CMAKE_INSTALL_MANIFEST "install_manifest.txt") 44 | endif() 45 | 46 | string(REPLACE ";" "\n" CMAKE_INSTALL_MANIFEST_CONTENT 47 | "${CMAKE_INSTALL_MANIFEST_FILES}") 48 | file(WRITE "/home/quronghui/HustFiles/Embedded-written-reference/code/cmake-build-debug/${CMAKE_INSTALL_MANIFEST}" 49 | "${CMAKE_INSTALL_MANIFEST_CONTENT}") 50 | -------------------------------------------------------------------------------- /code/cmake-build-debug/sizeof_value: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/code/cmake-build-debug/sizeof_value -------------------------------------------------------------------------------- /code/double_array_tran_pram.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by quronghui on 2019/9/27. 3 | // 4 | // 题目二:二维数组名的传参方式 5 | 6 | /* 7 | *(a)二维数组的传参:至少得包含列的个数,可以不包含行的个数 8 | * (b) 二维数组可以使用:数组指针进行传参;本质是一个指针 9 | * */ 10 | 11 | #include 12 | 13 | // (1)传递二维数组的大小; 14 | void test1(int arr[3][5]) 15 | { 16 | for (int i = 0; i < 3; ++i) { 17 | for (int j = 0; j < 5; ++j) { 18 | printf("%d ", arr[i][j]); 19 | } 20 | } 21 | } 22 | 23 | // (2) 二维数组按照一维数组存储,需要知道列 24 | void test2(int arr[][5]) 25 | { 26 | } 27 | 28 | // (3)通过数组指针进行传递:传过去的是二维数组的数组名,即数组首元素的地址 29 | // 也就是第一行的地址,第一行也是个数组,用一个数组指针接收 30 | void test6(int (*arr)[5]) 31 | { 32 | } 33 | 34 | // (3)不正确的传参方式 35 | //void test3(int arr[][]) 36 | // void test4(int *arr) //arr是一级指针,可以传给二维数组,但是不能正确读取 37 | //void test5(int *arr[5]) // 形参是指针数组,是一维的,可以传参,但是读取的数据不正确 38 | //void test7(int **arr) 39 | 40 | 41 | 42 | int main() 43 | { 44 | int arr[3][5] = {0}; 45 | 46 | test(arr); 47 | return 0; 48 | } -------------------------------------------------------------------------------- /code/funcation_array.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by quronghui on 2019/9/27. 3 | // 4 | // 题目三:函数指针,函数指针数组,函数指针数组的指针 5 | /* 6 | * (a)函数指针的形式:类型(*)(),例如:int (*p)( ).它可以存放函数的地址 7 | * (b)函数指针数组的定义 8 | * (c)函数指针数组的指针的定义 9 | * */ 10 | 11 | #include 12 | 13 | // (1)函数指针 14 | typedef void (*pfun)(); 15 | void test() 16 | { 17 | printf("hello,world.\n"); 18 | } 19 | 20 | //(2)函数指针数组的定义 21 | // parray是一个数组,每一个数组元素是一个void (*)()类型的函数指针; 函数指针数组在转换表中应用广泛? 22 | //typedef void (*parray[10])(); 23 | 24 | // (3)函数指针数组的指针 25 | //typedef void ((*pointer)[10])(); 26 | 27 | int main() 28 | { 29 | //(1)函数指针的定义和调用 30 | pfun fun = test; 31 | fun(); 32 | 33 | //(2)函数指针数组的定义 34 | void (*parray[10])(); 35 | parray[0] = test; 36 | // 指向函数指针数组parray的指针pparray 37 | void (*(*pparray)[10])() = &parray; 38 | 39 | return 0; 40 | } -------------------------------------------------------------------------------- /code/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("Hello, World!\n"); 5 | return 0; 6 | } -------------------------------------------------------------------------------- /code/memory_visit.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by quronghui on 2019/9/15. 3 | // 4 | // 题目:实现C语言实现程序跳转到绝对地址0x100000处执行 5 | 6 | #include 7 | 8 | typedef void(*convert)() ; // typedef定义了一个函数指针; 9 | 10 | 11 | void func(void) 12 | { 13 | printf("hello.\n"); 14 | } 15 | 16 | int main() 17 | { 18 | // (1) 他们的结果是一样的 19 | // func是函数的首地址,它的类型是void (); 20 | printf("func = %d\n",func); 21 | // &func表示一个指向函数void func(void)这个对象的地址,它的类型是void (*)() 22 | printf("&func = %d\n",&func); 23 | 24 | // (2)在调用一个函数的时候,也有两种方法 25 | void (*func_p)(void) = func; 26 | (*func_p)(); //调用函数时,加一个括号 27 | (func_p)(); //void * 参数可以是任何值 28 | func_p(); //后面两者也是对的,只是不那么用 29 | func(); 30 | 31 | //(3)实现程序跳转到绝对地址0x100000处执行 32 | /* void (*)(void); --> int * ; //void *:是一个数据类型,返回值为空,参数为空; 33 | * ( void (*)(void) ); --> ( int * ); //加了一个括号之后,代表强制类型转换 34 | * ( void (*)(void) )0x100000; //把0x100000强制转化为一个函数指针 35 | * ( *( void (*)(void) )0x100000 )(); // 第一种方式实现 36 | * ( ( void (*)(void) )0x100000 )(); // 第二种方式:就是调用这个函数,外层再加个括号,后面在加一对括号 37 | * 38 | */ 39 | // ( ( void (*)(void) )0x100000 )(); 40 | 41 | // (4) 能不能通过typedef来简化表达式 42 | puts("By typedef: "); 43 | convert func_pp = func; 44 | (func_pp)(); 45 | } 46 | -------------------------------------------------------------------------------- /code/one_array_transmit_paramter.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by quronghui on 2019/9/27. 3 | // 4 | // 题目一:一维数组的传参方式; 5 | 6 | #include 7 | #include 8 | 9 | /* 10 | * (一)题目一:一维数组的传参方式; 11 | * (a)数组名退化为指针传参,代表的是数组首元素的地址 12 | * (b)不能通过传递的参数名,计算数组的长度; 13 | * (c)如果是变量的值传递,那么形参就是实参的一份拷贝 14 | * (d)通过指针数组进行传参;本质是一个数组; 15 | * */ 16 | // (1)用数组的形式传递参数,不需要指定参数的大小; 17 | // 因为在一维数组传参时,形参不会真实的创建数组,传的只是数组首元素的地址; 18 | void test1(int arr[]) 19 | { 20 | printf("hello "); 21 | printf("sizeof(arr)/ sizeof(int) = %ld\n", sizeof(arr)/ sizeof(int)); // 值为2;传参数之后不能计算数组长度的; 22 | } 23 | 24 | void test2(int arr[10]) 25 | { 26 | printf("world. "); 27 | printf("sizeof(arr)/ sizeof(int) = %ld\n", sizeof(arr)/ sizeof(int)); // 值为2;传参数之后不能计算数组长度的,此时的arr表示首元素的首地址; 28 | 29 | } 30 | 31 | // (2)一维数组传参退化,用指针进行接收,传的是数组首元素的地址 32 | void test3(int *arr) 33 | { 34 | printf("pointer "); 35 | printf("sizeof(arr)/ sizeof(int) = %ld\n", sizeof(arr)/ sizeof(int)); // 值为2;传参数之后不能计算数组长度的,此时的arr表示首元素的首地址; 36 | } 37 | 38 | // (3) 传递的是指针数组,传过去的是数组名;也不能计算 39 | void test4(int *arr[20]) 40 | { 41 | printf("pointer array "); 42 | printf("sizeof(arr)/ sizeof(int) = %ld\n", sizeof(arr)/ sizeof(int)); // 值为2,不能计算 43 | } 44 | // (4)传过去是指针数组的数组名,代表首元素地址,首元素是个指针向数组的指针,再取地址,就表示二级指针,用二级指针接收 45 | void test5(int **arr) 46 | {} 47 | 48 | 49 | int main() 50 | { 51 | int arr[10] = {0}; 52 | int length = sizeof(arr)/ sizeof(int); 53 | int *arr1[20] = {0}; // 定义了一个指针数组 54 | test1(arr); 55 | test2(arr); 56 | test3(arr); 57 | test4(arr1); 58 | } 59 | -------------------------------------------------------------------------------- /code/pointer_funcation.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by quronghui on 2019/9/27. 3 | // 4 | // 题目四:指针函数和函数指针的用法 5 | 6 | #include 7 | #include 8 | 9 | /* 10 | * 一.指针函数的用法: 11 | * (a)接受指针函数的返回值:此时的返回值是一个指针 12 | * */ 13 | typedef struct _Data{ 14 | int a; 15 | int b; 16 | }Data; 17 | 18 | // (1)定义一个指针函数 19 | Data *f(int x, int y) 20 | { 21 | Data *data = (Data *)malloc(sizeof(Data)); 22 | data->a = x; 23 | data->b = y; 24 | return data; 25 | } 26 | // (2) 测试指针函数的用法 27 | void test_pointer_function() 28 | { 29 | Data *mydata = f(4,5); // 用于接收指针函数的返回值 30 | printf("mydata->a = %d, mydata->b = %d\n",mydata->a,mydata->b); 31 | } 32 | 33 | /* 34 | * (二)函数指针的用法 35 | * (a)本质是一个指针,指向了一个函数; 36 | * */ 37 | 38 | // (1)构造两个功能函数 39 | int add(int x, int y) 40 | { 41 | return x+y; 42 | } 43 | int sub(int x, int y) 44 | { 45 | return x-y; 46 | } 47 | // (2)定义函数指针: 可以通过typedef声明; 48 | //typedef int (*fun)(int x, int y); 49 | int (*fun)(int x, int y); 50 | 51 | // (3)测试函数指针 52 | void test_function_pointer() 53 | { 54 | // 第一种赋值的写法 55 | fun = add; 56 | printf("add_(*fun)(5,3) = %d \n", (*fun)(5,3)); 57 | // 第二种赋值的写法 58 | fun = ⊂ 59 | printf("sub_(*fun)(5,3) = %d \n", (*fun)(5,3)); 60 | 61 | } 62 | 63 | int main() 64 | { 65 | test_pointer_function(); 66 | test_function_pointer(); 67 | return 0; 68 | } 69 | -------------------------------------------------------------------------------- /code/sizeof_value.c: -------------------------------------------------------------------------------- 1 | // 2 | // Created by quronghui on 2019/9/21. 3 | // 4 | /* 5 | * 题目一:指针数组和数组指针的计算; 6 | * 题目二:数组名和指针名的计算 7 | * 题目三:指针数组和数组名; 8 | * */ 9 | #include 10 | #include 11 | 12 | // (1)指针数组和数组指针的计算; 13 | void sizeof_test() 14 | { 15 | int (*p1)[50]; // 数组指针;先指针后数组 16 | int *p2[50]; // 指针数组;先数组后指针 17 | int a[2][50]; 18 | 19 | for(int i = 0; i < 2; i++) 20 | for (int j = 0; j < 50; ++j) { 21 | a[i][j] = j + i * 100; // a[0][j] = 0-50; a[1][j] = 100-150; 22 | } 23 | p1 = (void *)&a; 24 | p2[0] = (void *)&a; 25 | 26 | printf("sizeof(a) = %d, sizeof(p1) = %d, sizeof(p2) = %d\n", sizeof(a), sizeof(p1), sizeof(p2)); 27 | printf("sizeof(*a) = %d, sizeof(*p1) = %d, sizeof(*p2) = %d\n", sizeof(*a), sizeof(*p1), sizeof(*p2)); 28 | printf("**(p1+1) = %d, *(*p1 + 1) = %d, **(p2 + 1) = %d\n", **(p1+1), *(*p1 + 1), **(p2 + 1)); 29 | } 30 | /* 31 | * sizeof(a) = 400, sizeof(p1) = 8, sizeof(p2) = 400 32 | sizeof(*a) = 200, sizeof(*p1) = 200, sizeof(*p2) = 8 33 | **(p1+1) = 100, *(*p1 + 1) = 1, **(p2 + 1) = 1651076143 34 | * */ 35 | 36 | // (2)数组名和指针名的计算 37 | void sizeof_array_pointer() 38 | { 39 | char *p = "abcde"; 40 | char q[] = {"abcde"}; 41 | printf("sizeof(p) = %d ", sizeof(p)); 42 | printf(" sizeof(q) = %d ", sizeof(q)); 43 | printf(" strlen(p) = %d ", strlen(p)); 44 | printf(" strlen(q) = %d\n", strlen(q)); 45 | } 46 | /* 47 | * sizeof(p) = 8 sizeof(q) = 8 strlen(p) = 7 strlen(q) = 7 48 | * */ 49 | 50 | // (3)指针数组和数组名; 51 | void array_name() 52 | { 53 | char *pa[4] = {"aaa","bbb","ccc","ddd"}; // 初始化的常量,放在data区; 54 | char pb[4] = {'a','b','c','d'}; 55 | 56 | // 指针数组:每一次加1,跳过4bytes 57 | for (int i = 0; i < 4; ++i) { 58 | printf("%s ",*(pa+i)); 59 | } //aaa bbb ccc ddd 60 | printf("\n"); 61 | 62 | // 数组中存放相同类型的元素:每一次加1,跳过1个字节 63 | for (int i = 0; i < 4; ++i) { 64 | printf("%c ",pb[i]); 65 | } //a b c d 66 | printf("\n"); 67 | 68 | // 如果直接进行赋值 69 | 70 | } 71 | 72 | 73 | int main() 74 | { 75 | sizeof_test(); 76 | sizeof_array_pointer(); 77 | array_name(); 78 | 79 | 80 | 81 | return 0; 82 | } 83 | 84 | -------------------------------------------------------------------------------- /dataStruct/n个元素的出栈顺序.md: -------------------------------------------------------------------------------- 1 | ## n个元素入栈后,出栈的次数? 2 | 3 | 1. 我们先通过画图的方式,得出n个元素入栈后的出栈次数? 4 | 5 | ``` 6 | n = 1; f(1) = 1; // 1 7 | n = 2 ; f(2) = 2; // 12; 21 8 | n = 3; f(3) = 5; // 123, 132; 213, 231; 321 9 | ``` 10 | 11 | + 将每一个元素作为第一个出栈元素:计算有多少次出栈次数; 12 | 13 | 2. 我们可以得出其具体每一步得到的公式? 14 | 15 | ``` 16 | f(0) = 1; //我们补充一个f(0),将其初始化为1 17 | f(1) = f(0) * f(0) = 1; 18 | f(2)= f(0) * f(1) + f(1) * f(0) = 2; 19 | f(3) = f(0) * f(2) + f(1) * f(1) + f(2) * f(0) = 5; 20 | ...... 21 | f(n) = f(0)*f(n-1) + f(1)*f(n-2) + ... + f(n-1)*f(0); 22 | ``` 23 | 24 | 3. 数学规律的总结 25 | 26 | ``` 27 | f(n) = C(2n, n) / (n+1); // 可以直接通过计算C(2n, n)的组合数,除以(n+1)就可以计算出来 28 | ``` 29 | 30 | 4. [c++的代码](https://blog.csdn.net/z88508468/article/details/45578893) 31 | 32 | -------------------------------------------------------------------------------- /dataStruct/photo/binary_tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/dataStruct/photo/binary_tree.png -------------------------------------------------------------------------------- /dataStruct/photo/dgree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/dataStruct/photo/dgree.png -------------------------------------------------------------------------------- /dataStruct/图的表示和存储.md: -------------------------------------------------------------------------------- 1 | ## [图的表示和存储](https://www.jianshu.com/p/1fd8d278bc2e) 2 | 3 | ### 图的表示 4 | 5 | 1. 无向图 6 | 2. 有向图 7 | 3. 带权重的图 8 | 4. 连通图 9 | 10 | ### 图的存储 11 | 12 | 1. 邻接矩阵表示法 13 | 2. 关联矩阵表示法 14 | 3. 弧表示法 15 | 4. 邻接表表示法 16 | 5. 星形表示法 17 | 18 | -------------------------------------------------------------------------------- /dataStruct/数据结构中堆、栈和队列的理区别.md: -------------------------------------------------------------------------------- 1 | ## 数据结构中堆、栈和队列的理解 2 | 3 | ### 数据结构中堆 4 | 5 | 1. 堆的数据结构: 指的是二叉树 6 | + 最大堆: 每一个节点值, 总是大于其左右子树的节点, 根节点值最大; 7 | + 最小堆: 每一个节点值, 总是小于其左右子树的节点, 根节点值最小 8 | + **问题一: **堆总是一棵完全二叉树? (这个性质, 有的说不对) 9 | 2. 堆常用来实现优先队列,堆的存取是随意的; 10 | + 如同我们在图书馆的**书架**上取书,虽然书的摆放是有顺序的,但是我们想取任意一本时不必像栈一样,先取出前面所有的书 11 | + 书架这种机制不同于**箱子**,我们可以直接取出我们想要的书。 12 | 13 | ### 内存分配 14 | 15 | 1. 栈是系统自动分配空间的,而堆则是程序员根据需要自己申请的空间。 16 | 17 | 2. **问题二** : 队列空间缓冲由进程申请? 18 | 19 | -------------------------------------------------------------------------------- /dataStruct/树的联系与区别.md: -------------------------------------------------------------------------------- 1 | ## [B, B-, B+树的定义,特性,联系与区别](https://blog.csdn.net/l1394049664/article/details/81463591) 2 | 3 | ### B树之间的区别 4 | 5 | | 树 | 性质 | 扩展 | 6 | | ---- | ------------------------------------------------------------ | ------------------------------------------------------------ | 7 | | B树 | 二叉搜索树, 每个结点只存储一个关键字;
等于则命中,小于走左结点,大于走右结点; | AVL树– 带有平衡条件的二叉查找树
伸展树–不带平衡条件的二叉查找树
红黑树-具有着色性质的二叉查找树 | 8 | | B-树 | 多路搜索树; | 平衡M-路树,很好的匹配磁盘 | 9 | | B+树 | B-树基础上,为叶子结点增加链表指针 | | 10 | | B*树 | 在B+树基础上,为非叶子结点也增加链表指针 | | 11 | | 堆 | **堆(heap)**不加任何修饰词使用时,就是完全二叉树(最大堆和最小堆) | | 12 | 13 | ### B树 14 | 15 | 1. 为什么使用B树? 16 | 17 | - 为了更快的查找, 通过一个分叉, 减少一半数据量的搜索; 18 | - **B树**也就是二叉搜索树, 二叉树的查找平均时间是log2 (N),是与二叉树的深度有关; 19 | 20 | 2. B树即是B-树 21 | 22 | - 如果还要增加搜索速度, 增加二叉树的**叉** 23 | 24 | ``` 25 | log 2(N) ; // 二叉搜索树, 两个叉 26 | log m(N) ; // 增加m个差, m > 2 27 | ``` 28 | 29 | ### 红黑树和AVL树的比较 30 | 31 | 1. 红黑树: 32 | + 并不追求“完全平衡”——它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能。 33 | + 红黑树能够以O(log2 n) 的时间复杂度进行搜索、插入、删除操作。 34 | + 由于它的设计,**任何不平衡都会在三次旋转之内解决**。红黑树能够给我们一个比较“便宜”的解决方案。红黑树的算法时间复杂度和AVL相同,但统计性能比AVL树更高。 35 | 2. AVL树 36 | + 它的左子树和右子树都是AVL树,左子树和右子树的高度差不能超过1; 37 | + 查找、插入和删除在平均和最坏情况下都是O(log n),增加和删除可能需要通过一次或多次树旋转来重新平衡这个树; 38 | 39 | ### 红黑树: 带有平衡性的二叉搜索树增强版 40 | 41 | 1. 红黑树是每个节点都带有**颜色属性**的二叉查找树,颜色或红色或黑色。 42 | + 性质1. 节点是红色或黑色。 43 | + 性质2. 根节点是**黑色**。 44 | + 性质3 每个叶节点是**黑色**的。 45 | + 性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点) 46 | + **性质5. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。** 47 | 2. 对于给定的黑色高度为n的红黑树,从根到叶结点的简单路径的最短长度为n-1,最大长度为2(n-1)。 48 | -------------------------------------------------------------------------------- /design_model/常用的设计模式.md: -------------------------------------------------------------------------------- 1 | ## 常用的设计模式 2 | 3 | ### 单例模式 4 | 5 | 1. 定义:保证**一个**类仅有一个实例,并提供一个访问它的全局访问点。 6 | 2. 实现方法:先判断实例存在与否,如果存在则直接返回,如果不存在就**创建**了再返回,这就确保了一个类只有一个实例对象。 7 | 3. 适用场景:一个单一对象。比如:弹窗,无论点击多少次,弹窗只应该被创建一次。 8 | 9 | ### 发布/订阅模式 10 | 11 | 1. 定义:又叫观察者模式,它定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知。 12 | 2. 场景:订阅感兴趣的专栏和公众号。 13 | 14 | ### 策略模式 15 | 16 | 1. 定义:将一个个算法(解决方案)封装在一个个策略类中。 17 | 18 | 2. 优点: 19 | + 策略模式可以避免代码中的多重判断条件。 20 | + 策略模式很好的体现了开放-封闭原则,将一个个算法(解决方案)封装在一个个策略类中。便于切换,理解,扩展。 21 | + 策略中的各种算法可以重复利用在系统的各个地方,避免复制粘贴。 22 | + 策略模式在程序中或多或少的增加了策略类。但比堆砌在业务逻辑中要清晰明了。 23 | + 违反最少知识原则,必须要了解各种策略类,才能更好的在业务中应用。 24 | 25 | 3. 应用场景:根据不同的员工绩效计算不同的奖金;表单验证中的多种校验规则。 26 | 27 | ### 代理模式 28 | 29 | 定义:为一个对象提供一个代用品或占位符,以便控制对它的访问。 30 | 31 | 应用场景:图片懒加载(先通过一张loading图占位,然后通过异步的方式加载图片,等图片加载好了再把完成的图片加载到img标签里面。) 32 | 33 | ### 中介者模式 34 | 35 | 定义:通过一个中介者对象,其他所有相关对象都通过该中介者对象来通信,而不是互相引用,当其中的一个对象发生改变时,只要通知中介者对象就可以。可以解除对象与对象之间的紧耦合关系。 36 | 37 | 应用场景: 例如购物车需求,存在商品选择表单、颜色选择表单、购买数量表单等等,都会触发change事件,那么可以通过中介者来转发处理这些事件,实现各个事件间的解耦,仅仅维护中介者对象即可。 38 | 39 | ### 装饰者模式 40 | 41 | 定义:在不改变对象自身的基础上,在程序运行期间给对象动态的添加方法。 42 | 43 | 应用场景: 有方法维持不变,在原有方法上再挂载其他方法来满足现有需求;函数的解耦,将函数拆分成多个可复用的函数,再将拆分出来的函数挂载到某个函数上,实现相同的效果但增强了复用性。 -------------------------------------------------------------------------------- /neuralNet/神经网络中引入非线性能力的是.md: -------------------------------------------------------------------------------- 1 | ## 神经网络中引入非线性能力的是? 2 | 3 | + 4 | 5 | -------------------------------------------------------------------------------- /process/Linux进程调度的算法.md: -------------------------------------------------------------------------------- 1 | ## Linux进程调度的算法 2 | 3 | ### 先来先服务(FCFS) 4 | 5 | 1. 调度算法: 6 | + 按照:作业到达的**先后次序**来进行调度 7 | + 队列:通过队列实现作业的阻塞和调度; 8 | 2. 优点和缺点 9 | + 优点:有利于**长作业**(进程)和CPU**繁忙型**作业(进程) 10 | + 缺点:不利于短作业(进程)和I/O繁忙型作业(进程);没有优先级 11 | 12 | ### 短进程优先(SPF) 13 | 14 | 1. 调度算法: 15 | + 从就绪队列中选择一个估计运行时间最短的进程 16 | + 将CPU分配给该进程; 17 | 2. 优缺点: 18 | + 优点:相比FCFS 算法,改善**平均周转时间**和平均带权周转时间,缩短进程的等待时间,提高系统的**吞吐量** 19 | + 缺点:长作业(进程)得不到响应,会饿死; 20 | 21 | ### 轮转法调度 22 | 23 | 1. 轮转法调度算法 24 | + 适用于分时系统 25 | + 系统将所有就绪进程按到达时间的先后次序排成一个队列,每个进程分配**时间片** 26 | 2. 时间片的大小? 27 | + 时间片足够大:时间片轮转调度算法就退化为**先来先服务**调度算法 28 | + 时间片很小:那么CPU将在进程间过于频繁切换,时的开销增大; 29 | 3. 时间片的决定因素? 30 | + 系统的响应时间、就绪队列中的进程数目和系统的处理能力 31 | 32 | ### 优先级调度 33 | 34 | 1. 优先级调度算法: 35 | + **优先权**调度算法,每次从就绪作业队列中选择优先级最髙的一个或几个作业; 36 | 37 | ### 多级反馈队列 38 | 39 | 1. 多级反馈队列算法(Round Robin with Multiple Feedback) 40 | + 是轮转算法和优先级算法的综合和发展 41 | + 设置多个就绪队列,分别赋予不同的优先级,如逐级降低,队列1的优先级最高 42 | + 每个队列执行时间片的长度也不同,规定优先级越低则时间片越长,如逐级加倍 -------------------------------------------------------------------------------- /process/schedule()的触发和执行时机.md: -------------------------------------------------------------------------------- 1 | ## 详解Linux内核进程调度函数schedule()的触发和执行时机 2 | 3 | 1. 内核进程的的调度操作? 4 | + 触发:**设置**一下当前进程的TIF_NEED_RESCHED标志 5 | + 执行:通过schedule()函数来完成进程的**选择和切换** 6 | 2. 具体的过程? -------------------------------------------------------------------------------- /shell/Linux磁盘整体情况.md: -------------------------------------------------------------------------------- 1 | ## 磁盘整体情况查询 2 | 3 | 1. 当前目录下所有文件的磁盘空间使用情况:不进行递归的 4 | 5 | ``` 6 | $ df -h 7 | $ df -h /usr/ // 查看指定目录 8 | ``` 9 | 10 | 2. 当前目录下主文件目录:递归多有文件的大小 11 | 12 | ``` 13 | $ du --max-depth=1 -h 14 | ``` 15 | 16 | 3. 计算当前目录整体占用大小 17 | 18 | ``` 19 | $ du -sh 20 | ``` 21 | 22 | 4. free:直接查询磁盘剩余的空间内存和使用内存; 23 | 24 | -------------------------------------------------------------------------------- /shell/Linux读取某个文件的某一行或者某几行.md: -------------------------------------------------------------------------------- 1 | ## Linux读取某个文件的某一行或者某几行 2 | 3 | 1. 查看文件a.txt的第190行到196行 4 | 5 | ``` 6 | $ sed -n '190,196p' a.txt 7 | ``` 8 | 9 | 2. 查找文件中的某一行 10 | 11 | ``` 12 | $ sed -n '190,1p' a.txt 13 | ``` 14 | 15 | 3. sed and awk 16 | 17 | + sed 以行为单位处理文件,awk 比sed强的地方在于不仅能以行为单位还能以列为单位处理文件。 18 | 19 | + awk缺省的行分隔符是换行,缺省的列分隔符是连续的空格和Tab 20 | 21 | -------------------------------------------------------------------------------- /shell/Makefile.md: -------------------------------------------------------------------------------- 1 | ## Makefile文件的编写 2 | 3 | ``` 4 | # 由于我的目标文件是单独的, 所以我每次得 编辑 SRCS 和 TARG 5 | 6 | # specify all source files here 7 | SRCS = print_link_form_tail_to_head.c one_list.c one_list.h 8 | 9 | # specify target here (name of executable) 10 | # TARG = one_list 11 | TARG = print_link_form_tail_to_head 12 | 13 | # specify compiler, compile flags, and needed libs 14 | CC = gcc 15 | CFLAGS = -g -Wall 16 | LIBS = -lm 17 | 18 | # this translates .c file in src list to .o's 19 | OBJS = $(SRCS: .c=.o) 20 | 21 | # all is not really needed , but is used to generate the target 22 | all: $(TARG) 23 | 24 | # this generates the target executable 25 | $(TARG): $(OBJS) 26 | $(CC) $(OBJS) -o $(TARG) 27 | 28 | # this is a generic rule for .o files 29 | %.o: %.c 30 | $(CC) $(CFLAGS) -c $< $@ 31 | 32 | 33 | #clean 34 | clean: 35 | @echo "cleaning project" 36 | -rm *.o $(TARG) 37 | @echo "cleaning complie" 38 | .PHONY: clean 39 | 40 | ``` 41 | 42 | -------------------------------------------------------------------------------- /shell/linux内核版本号.md: -------------------------------------------------------------------------------- 1 | ## linux内核版本号查询 2 | 3 | ``` 4 | $ cat /proc/version // 通过proc虚拟文件系统,查询内核中的信息 5 | ``` 6 | 7 | ``` 8 | Linux version 5.0.0-25-generic (buildd@lcy01-amd64-014) 9 | (gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)) 10 | ``` 11 | 12 | ## 查询编译器的版本号 13 | 14 | ``` 15 | $ gcc -v; 16 | 17 | Thread model: posix 18 | gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1) 19 | ``` 20 | 21 | -------------------------------------------------------------------------------- /shell/linux文件操作的五个命令.md: -------------------------------------------------------------------------------- 1 | ## linux文件操作的五个命令 2 | 3 | ![file_operation.png](https://github.com/quronghui/Embedded-written-reference/tree/master/shell/file_operation.png) 4 | 5 | -------------------------------------------------------------------------------- /shell/photo/file_operation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quronghui/Embedded-written-reference/2ccd840715868378809f74e552e63cfdaac1faa7/shell/photo/file_operation.png -------------------------------------------------------------------------------- /shell/如何理解三个标准文件.md: -------------------------------------------------------------------------------- 1 | ## 如何理解三个标准文件 2 | 3 | + stdin;stdout;stderr; 4 | + stdin 和 stdout :其得到字符或者输出字符,**都是先到内存缓冲区**,遇到回车('\n')和新行时才输入/输出 5 | + stderr:直接输出到屏幕; 6 | 7 | ### 先区分一下:printf,sprintf,fprintf 8 | 9 | 1. printf就是标准输出,在屏幕上打印出一段字符串来。 10 | 11 | 2. sprintf就是把格式化的数据写入到某个字符串中。返回值字符串的长度。 12 | 13 | ``` 14 | int sprintf(char *str, const char *format, ...); // 将大数转化为字符串 15 | ``` 16 | 17 | + format: 可以有多种类型的融合叠加,转化为字符串 18 | 19 | + [sprintf 的用法代码](https://github.com/quronghui/DataStructAndAlogrithmCode/blob/master/SwordOffer/Input_output/std_sprintf.c) 20 | 21 | 3. fprintf是用于文件操作 22 | 23 | ``` 24 | int fprintf(FILE *stream, char *format, [arguement]); 25 | ``` 26 | 27 | + 将指定的信息输出到文件流当中; 28 | + [code](https://github.com/quronghui/DataStructAndAlogrithmCode/blob/master/SwordOffer/Input_output/std_fprintf.c) 29 | 30 | ### stdout 和 stderr 31 | 32 | 1. stdout 和 stderr的区别:输出到屏幕 33 | 34 | ``` 35 | int main(){ 36 | fprintf(stdout,"Hello "); 37 | fprintf(stderr,"World!"); 38 | return0; 39 | } 40 | // 输出:World!Hello 41 | ``` 42 | 43 | + stdout是行缓冲的,他的输出会放在一个buffer里面,只有到换行的时候,才会输出到屏幕 44 | + 而stderr是无缓冲的,会直接输出到屏幕; 45 | 46 | 2. stdout 和 stderr的区别:输出到磁盘 47 | 48 | ``` 49 | void std_stderr() 50 | { 51 | fprintf(stdout, "open\n"); 52 | fprintf(stderr, "Can't\n"); 53 | printf("it.\n"); 54 | } 55 | // 输出: 56 | open 57 | Can't // Can't 和 it 出现的顺序有的时候还是不一样的; 58 | it 59 | ``` 60 | 61 | + 但如果用转向标准输出到磁盘文件,则可看出两者区别。 62 | + stdout输出到磁盘文件,stderr在屏幕 63 | 64 | 3. 用TYPE 看 tmp.txt的内容: 65 | 66 | ### stdin 标准输入 67 | 68 | + [code input](https://github.com/quronghui/DataStructAndAlogrithmCode/blob/master/SwordOffer/Input_output/std_input.c) 69 | 70 | 1. gets() -- 不适用,存在溢出的状况 71 | 72 | + char *gets( char *s ) 73 | + gets*从*stdin*中读入一行内容到*s*指定的*buffer*中,当遇到换行符或*EOF时读取结束 74 | + gets*会将行末尾的*'\n'*字符或*EOF*替换成*'\0' 75 | + gets*读取的内容中不包括*'\n'*字符。如果要获取读取字符串的长度,可以调用*strlen*函数获得* 76 | 77 | 2. fgets() -- 每次只读取(size-1), 解决输入溢出的现象(溢出会出现覆盖) 78 | 79 | + ``` 80 | fgets(buff,size,stdin); //从标准输入流中读入 81 | ``` 82 | 83 | 3. 因为gets,fgets等函数会自动从缓冲区中读取字符,一般情况,都会在缓冲区留下“\n”;可以使用getchar()将字符去除 84 | 85 | 4. stdin 标准输入 86 | 87 | + sscanf()与scanf()类似,都是用于输入的,只是scanf()以键盘(stdin)为输入源,sscanf()以固定字符串为输入源。 88 | 89 | + ``` 90 | scanf("%d %d %d",&a,&b,&c); 91 | ``` 92 | 93 | --------------------------------------------------------------------------------