跟我一起写makefile_Linux学习:Makefile和系统IO函数

随着对Linux的认识越来越深入,除了基本的操作命令之外,程序员或者Linux开发爱好者来说,对于大型文件系统的编译工作,不可避免的要用到makefile操作。makefile的作用和含义以及它的使用方法,通过本篇简短的总结,带你领悟它的魅力。

makefile的简介:

Makefile是和make命令一起配合使用的。很多大型项目的编译都是通过 Makefile 来组织的, 如果没有 Makefile, 那很多项目中各种库和代码之间的依赖关系不知会多复杂。Makefile的组织流程的能力如此之强, 不仅可以用来编译项目, 还可以用来组织我们平时的一些日常操作. 这个需要大家发挥自己的想象力.

2dec4a4e3adc12d804d3804aefa78ed6.png

1 Makefile 基础知识:

 前面也介绍了,Makefile主要用于项目编译的管理,节省编译项目的时间,并且一次编写,可以一直使用,在程序员做工程的时候,是不可多得的工具,并且可以自己定义规则

3c9f9f4d6e7859222d6a28aa2f4a3314.png

000bf6d2c5ca2811df0a4689a726ba7e.png

f7cd415fc1f6596e9c8006d0e063fbb0.png

786f9dd6bc0e53542bad03ea74f81f82.png

具体的深入学习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函数

fe814893873cde996d8d3c0c5004fe66.png

2.1 一些概念
  文件描述符
     PCB
     C库函的IO缓冲区

     1) 文件描述符
            int 类型
            一个进程最多可打开多少文件
     2) pcb
           进程控制块
           在其中有一个文件描述符表 -- 数组[1024]

C语言库函数工作流程的简单简单示意

d42db95b4c38fb28d500cfbca98e88ec.png

pcb和文件描述符:

a5bec4620921d4bd3c0b28e656032e7a.png

2.2虚拟地址空间

定义:虚拟地址空间就是程序启动起来之后从硬盘上会有一块虚拟内存分配出来。

    cpu 为什么要使用虚拟地址空间与物理地址空间映射?解决了什么样的问题?

    1)方便编译器和操作系统安排程序的地址分布。

         程序可以使用一系列相邻的虚拟地址来访问物理内存中不相邻的大内存缓冲区。通过虚拟地址空间与物理地址空间映射解决不连续的缓冲区的问题。

    2)方便进程之间隔离

        不同进程使用的虚拟地址彼此隔离。一个进程中的代码无法更改正在由另一进程使用的物理内存。 

    3)方便OS使用你那可怜的内存。

        程序可以使用一系列虚拟地址来访问大于可用物理内存的内存缓冲区。当物理内存的供应量变小时,
        内存管理器会将物理内存页(通常大小为 4 KB)保存到磁盘文件。数据或代码页会根据需要在物理内存与磁盘之间移动。

    虚拟地址空间的布局如下:

    0-3G是用户空间        3-4G是内核空间

       用户区                        内核区
       代码段
       已经初始化的全局变量
       未被初始化的全局变量
       堆 -- 从下往上
       共享库
       栈 - 从上往下
       环境变量
       内核区

2cf2a6eaca1fc90b81fa5b6c5a649579.png

2.3 C库函数与系统函数的关系 

    FD:文件描述符        FP_POS:文件指针    BUFFER:缓冲区
    write对0-3G的用户空间进行操作        sys_write()对3-4G的内核空间进行操作

84aca746a42cba7885d8a8e362b0377b.png

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:

09ff2b0985c0756e3394eb0531ab53e7.png

   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返回值不同

赠言:学习是永无止境的,一个人要想强大起来,必须具备坚定的信仰,拼搏的精神,顽强的斗志,一往无前,日积月累,方能成就自己。对任何事情都是如此,这也是自己写公众号很重要的原因。后面会分享一些学习的电子书籍和视频,一起共同成长。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值