Make学习

Make

Make 功能简介

通过比较对应文件(目标,规则的依赖)的最后修改时间,来决定哪些文件需要更新。只更改修改的源文件。

  • 没有被编译过的源文件,进行编译并且进行链接
  • 在上次执行 make 之后修改过的 C 源代码文件,会重新编译
  • 头文件在上一次执行 make 之后被修改,那么所有包含此头文件的 C 源文件会被重新编译

Makefile 规则介绍

target :prerequisites
command

target:目标。可以是目标文件,也可以是动作的名称(比如 clean),称之为伪目标。
prerequisites:规则的依赖。就是需要的文件列表(多个)。太长用反斜杠,后面不能有空格。
command:规则的命令行。

Make 的工作方式

默认情况下执行第一个规则,第一个目标称为最终目的。当修改了任何的源文件和头文件后,执行 make 会重建终极目标。(这里 make 决定哪些需要更新,只要依赖更新,自己也要更新)
注意,.o 文件之所以更新,是因为它出现在了终极目标的依赖列表里面,如果某个规则不是终极目标所依赖的,那么它就不会被执行,除非明确指出需要执行这个规则。
处理 edit 的三种情况:

  • edit 不存在,执行规则创建 edit
  • 存在,依赖文件比他更新,根据规则重新链接生成 edit
  • 它比任何一个依赖文件都更新,那么什么也不做

从最终目的的第一个依赖文件寻找规则(main.o,kbd.o…),如果第一个依赖其他的,同样为它寻找规则。。。通常源文件和头文件已经存在,不需要重建他们的规则,所有都找到之后,从最好一个开始回退执行,最终完成 edit 的第一个依赖文件的创建和更新,然后是第二个,第三个。
整个过程 make 只是负责执行规则,对依赖关系的正确性和规则所定义的命令的正确性不做任何判断 。就是说,make 不做错误检查。
我们需要在提供给 make 程序的 Makefile 中保证其依赖关系的正确性,和执行命令的正确性。

有变量,基本的元素,规则,rules 可以有 if,else,也可以有 shell 语言。
任何文件都可以有依赖,
第一层:main;第二层:.o;第三层:.c,.h 文件。需要分开编译,效率问题。
makefile 描述编译的层次结构,可以分析修改的时间。
makefile 自动更新,自更新指令,目标 makefile(git pull),自己本身的命令出现变化。在运行 make 的时候,首先自动扫描 makefile 进行更新。直到没有 makefile 更新才停止。
make 后来加了 if,变量的东西。也有 function,还有自动匹配的功能。
ant,build(java),another neat tool,吐槽 make,解决 tab 的问题,用 xml 来描述规则,默认的是 build.xml,可以 import 一些包,可以进行扩展。
make 的问题,移植性的问题。
vc++微软的 c++和一般的不同,windows 用 vc++写的。

shell 的 build in

首先判断是否为内建,会更快。
命令行;为占位,相当于 nop。
.用来执行文件,相当于 source。bash 会新打开一个 shell,source 相当于 include。子 shell 相当于子进程,用 source 会得到子 shell 的改变。
break 和 continue。break 可以带 1、2、3 等,也就是打破几层的循环。
evol echo “$$n”,也就是替换两次。指令强大,但是不安全。
exec,执行跳转到另外一个再也不回来。
export,调整当前 shell 的环境变量,新增环境变量。变量和环境变量不同,环境变量,export 会将普通变量变为环境变量。
hash 表相对于 shell 临时。
getoptions,带:一定要读参数,否则要报错。是对命令行的一个抽象。

多线程

背景

以前一个 cpu 一个核,一个核一个线程。
单核时代的多线和单线,有一点区别。
js 只能单线程(同一个页面),代码是异步的,很容易。但是 C 里面不容易用异步。

单核时代:单线程时代异步特别复杂的问题,代码难写;写成多进程,分时。单核多线程,利用分时技术,将时间分配给不同的任务,相当于线程的切换。

多核时代:可以提高计算效率。分时系统出现了进程的概念,没有数据共享。

进程、线程竞争

又出现了多线程的问题,线程之间的关系和同步等的问题。

  • 线程调度的问题,死锁。
  • state,状态。竞争,数据竞争。

都可以归结为竞争条件,risk condition,情况与执行的先后顺序有关。解决办法,同步,一段操作原子化。由于 data conruption。

cache,两个 cpu,cache 不共享,但是内存共享。数据没有写到内存中,还在 cache 中。Java 中的关键字 GuardedBy,要求原子化和数据同步,但是很慢,将 cache 中的数据既回去。
一个 cpu,一个核 1,2 级缓存,多核 3 级缓存共享。开始是多读数据,后来用 signal。

对线程来说,堆是共享的,栈私有。statelist,只有操作,没有数据,也就没有 risk condition。
重入锁以线程为单位;pthread 是互斥锁;Java 中是重入锁。