随着对Linux的认识越来越深入,除了基本的操作命令之外,程序员或者Linux开发爱好者来说,对于大型文件系统的编译工作,不可避免的要用到makefile操作。makefile的作用和含义以及它的使用方法,通过本篇简短的总结,带你领悟它的魅力。
makefile的简介:
Makefile是和make命令一起配合使用的。很多大型项目的编译都是通过 Makefile 来组织的, 如果没有 Makefile, 那很多项目中各种库和代码之间的依赖关系不知会多复杂。Makefile的组织流程的能力如此之强, 不仅可以用来编译项目, 还可以用来组织我们平时的一些日常操作. 这个需要大家发挥自己的想象力.
1 Makefile 基础知识:
前面也介绍了,Makefile主要用于项目编译的管理,节省编译项目的时间,并且一次编写,可以一直使用,在程序员做工程的时候,是不可多得的工具,并且可以自己定义规则
具体的深入学习Linux Makefile的编写,后面我会推出一些学习的电子书籍,可以下载学习。另外CSDN的公众号https://blog.csdn.net/haoel/article/details/2886大神介绍的也相当详细,但这篇文章内容简单,通过思维导图可以快速的理解每个Linux工具或者模块的使用方法,帮助我们快速记忆。
总结:思维导图中,我们通过对基本规则的总结,工作原理的简单介绍,执行make的方式,以及文件编译里面的变量的使用函数的调用等。梳理了整个makrfile文件的基础知识。
总的来说:makefile的编写需要下面四个步骤:
1. makefile的命名
2. makefile的规则:
规则中的三要素: 目标, 依赖, 命令
目标:依赖条件
命令
子目标和终极目标的关系:
更新目标的原则:
3. makefile的两个函数
wildcard
patsubst
4. makefile的三个自动变量
$<
$@
$^
2 系统的IO函数
2.1 一些概念
文件描述符
PCB
C库函的IO缓冲区
1) 文件描述符
int 类型
一个进程最多可打开多少文件
2) pcb
进程控制块
在其中有一个文件描述符表 -- 数组[1024]
C语言库函数工作流程的简单简单示意
pcb和文件描述符:
2.2虚拟地址空间
定义:虚拟地址空间就是程序启动起来之后从硬盘上会有一块虚拟内存分配出来。
cpu 为什么要使用虚拟地址空间与物理地址空间映射?解决了什么样的问题?
1)方便编译器和操作系统安排程序的地址分布。
程序可以使用一系列相邻的虚拟地址来访问物理内存中不相邻的大内存缓冲区。通过虚拟地址空间与物理地址空间映射解决不连续的缓冲区的问题。
2)方便进程之间隔离
不同进程使用的虚拟地址彼此隔离。一个进程中的代码无法更改正在由另一进程使用的物理内存。
3)方便OS使用你那可怜的内存。
程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。当物理内存的供应量变小时,
内存管理器会将物理内存页(通常大小为 4 KB)保存到磁盘文件。数据或代码页会根据需要在物理内存与磁盘之间移动。
虚拟地址空间的布局如下:
0-3G是用户空间 3-4G是内核空间
用户区 内核区
代码段
已经初始化的全局变量
未被初始化的全局变量
堆 -- 从下往上
共享库
栈 - 从上往下
环境变量
内核区
2.3 C库函数与系统函数的关系
FD:文件描述符 FP_POS:文件指针 BUFFER:缓冲区
write对0-3G的用户空间进行操作 sys_write()对3-4G的内核空间进行操作
2.4 IO函数介绍
1)open
查看 man 2 open
头文件:
#include
#include
#include
函数原型:
int open(const char *pathname, int flags);int open(const char *pathname, int flags, mode_t mode);
参数说明
pathname 文件名
flags
必选项:
O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读写
可选项:
O_APPEND 追加
O_CREAT 创建文件
O_EXCL和O_CREATE一起使用,如果文件存在则报错
O_NONBLOCK 非阻塞
Mode 权限位,最终(mode&~umask)
返回值:
成功:返回最小的可用文件描述符
失败:返回-1,并且设置errno
open函数中的errno:
2)close
作用:关闭文件描述符
头文件:
#include
函数原型:
int close(int fd);
参数说明:
fd文件描述符
返回值:
成功:返回0
失败:返回-1,并且设置errno
3)read读
头文件
#include
函数原型
ssize_t read(int fd, void *buf, size_t count);
参数说明
fd 文件描述符
buf缓冲区
count缓冲区大小
返回值
失败:返回-1,设置errno
成功:返回读到的字节数
0代表读到文件末尾
非阻塞的情况下read返回-1,但是此时需要判断error的值。
4)write写
头文件
#include
函数原型
ssize_t write(int fd, const void *buf, size_t count);
参数说明:
fd文件描述符
buf缓冲区
count缓冲区大小
返回值
失败:返回-1,设置errno
成功:返回写入的字节数
0代表未写入
5)lseek写
头文件
#include
#include
函数原型
off_t lseek(int fd, off_t offset, int whence);
参数说明
fd文件描述符
offset偏移量
whence:
SEEK_SET 文件开始位置
SEEK_CUR 文件当前位置
SEEK_END 文件结尾
返回值
失败:返回-1,设置errno
成功:返回当前位置到文件开头的长度
lseek作用
移动文件读写位置
计算文件大小
拓展文件
6)fcntl
头文件
#include
#include
函数原型
int fcntl(int fd, int cmd, ... /* arg */ );
参数说明:
fd文件描述符
cmd 命令
返回值
不同的cmd返回值不同
赠言:学习是永无止境的,一个人要想强大起来,必须具备坚定的信仰,拼搏的精神,顽强的斗志,一往无前,日积月累,方能成就自己。对任何事情都是如此,这也是自己写公众号很重要的原因。后面会分享一些学习的电子书籍和视频,一起共同成长。