day9嵌入式(2022.1.15)

简介: day9嵌入式(2022.1.15)

1.程序文件分析


ELF:Linux系统下,可执行程序文件。(可重定位文件)


(类似于Windows中的exe)


程序文件中,需要特别关注的文件段:



备注:


  1. file 指令,查看系统中某个文件类型。


file 文件名


  1. readelf指令,列举程序文件中文件段。


readelf -S 程序名


2.进程内存布局



浏览一下书本 《2.4 内存管理》章节


尝试找出以下问题的答案:


  1. 虚拟内存是如何分配的呢,由什么内容组成?


内核、栈、堆、数据段、代码段、不可访问区。


  1. 上面提到的特殊关注的文件段是什么东西?中文名是啥?


.init 系统初始化代码段


.text 用户代码段


.rodata 常量数据段(只读数据段)


.data 已初始化静态数据段


.bss 未初始化静态数据段


  1. 哪些段是静态不变的,哪些段是动态变化的?


不变:数据段、代码段


变化:


  1. 我们以前的代码,操作过哪些段落?


用户代码、常量区、栈。


备注:


  1. 局部变量和全局变量


函数内部定义的变量,称为局部变量,位于栈空间


函数外部定义的变量,称为全局变量,位于静态数据段


  1. 静态数据分为 .data和.bss


int g_a=100;    // .data    已初始化,则不做任何处理
char g_b;       // .bss     未初始化,这块内存会被自动清零


(栈空间中的局部变量,如果未初始化,则为乱码数据(随机值)。)


尽量不要滥用静态数据。


静态数据生命周期与进程相当,会一直占用内存。


多线程编程中,可能导致共享资源出现问题。


函数内部定义的局部变量,在函数结束后,会被自动释放。


static修饰符的用法:


修饰局部变量:将该局部变量置于静态数据段。


修饰全局变量、函数:将该变量或函数链接类型由外部链接类型修改为内部链接类型。


(如果全局变量、函数只在单个文件中使用,可以使用static修饰,避免出现重名冲突)



demo1_内存分布


#include<stdio.h>
// 函数外部定义的变量,称为全局变量,位于静态数据段
int g_a=100;  // .data  不做任何处理
char g_b;   // .bss   这块内存会被自动清零
// 子函数存储在.text用户代码
unsigned char func_sum(char a, float b) // 形参位于栈空间
{
  //  168=65+3.5+100+0
  return a+b+g_a+g_b;   // 函数返回后,会将当前函数所有栈空间数据释放。(a, b)
}
// main主函数存储在.text用户代码
int main()
{
  // 函数内部定义的变量,称为局部变量,位于栈空间
  int n1=100;   // n1位于栈空间,整型常量100位于常量区(只读区)
  float n2=3.5; // n2位于栈空间,浮点型常量3.5位于常量区
  char n3='A';  // n3位于栈空间,字符常量'A'位于常量区
  char *str = "hello";  // str位于栈空间,字符串常量"hello"位于常量区
  // str[0] = 'a';  // 尝试对常量区写入会导致出现段错误
  printf("%c\n", *str); // 对常量区读取是允许。
  printf("%ld %ld\n", sizeof('A'), sizeof(100));
  // sum位于栈空间,跳转到用户代码中的func_sum的入口地址
  unsigned char sum = func_sum(n3, n2);
  printf("sum: %c(%d)\n", sum, sum);
  return 0;
}


demo2_static


#include<stdio.h>
// 如需使用其他文件的函数,需要添加外部声明
extern void func_2(void);
// static:静态的
// int g_a = 200; // 未添加static,是外部链接类型
static int g_a = 200; // 添加static,修改为内部链接类型
void func_1(void)
{
  // int a=100; // 局部变量
  static int a=100; // static修饰的局部变量(只能被初始化1次)
  a++;
  printf("a(%p): %d\n", &a, a);
}
int main()
{
  func_1();
  func_1();
  func_1();
  func_1();
  func_1();
  func_2();
  return 0;
}


demo3_另一个文件


#include<stdio.h>
// 如需要使用其他文件的变量,需添加外部声明
extern int g_a;
void func_2(void)
{
  printf("g_a: %d\n", g_a);
}


demo4_堆空间使用


#include <stdio.h>
#include <stdlib.h>
// 申请堆空间
// #include <stdlib.h>
// void *malloc(size_t size);   // 申请 size 字节的堆空间
// void *calloc(size_t nmemb, size_t size); // 申请 nmemb*size 字节的堆空间
// void *realloc(void *ptr, size_t size); // 重新申请一块size字节堆空间
  // 释放堆空间
// void free(void *ptr);    // 但不需要使用到该块内存时,释放空间。
// 使用场景:需要使用的内存较大,需要自行决定内存释放时机。
int main()
{
  // 1M字节 = 1024K字节 = 1024*1024 字节
  // char arr1[7*1024*1024] = {0};    
// 位于栈空间,可使用指令(ulimit -a)查看,最大是8M
  // 申请10M堆空间
  // char *arr1 = malloc(10*1024*1024);
  char *arr1 = calloc(10, 1024*1024);
  // arr1[0] = 'A';
  *(arr1+0) = 'A';
  printf("%c\n", arr1[0]);
  // 释放堆空间(当程序结束时,所有内存也会被释放。)
  free(arr1);
  return 0;
}
相关文章
|
2月前
|
Linux C语言 C++
嵌入式
嵌入式
19 0
|
10月前
|
传感器 人工智能 安全
有什么是嵌入式不能满足的?
从20世纪60年代开始,嵌入式系统就已经开始出现,当时主要应用于航空航天、国防、工业自动化等领域
|
11月前
嵌入式day1(2022.1.6)
嵌入式day1(2022.1.6)
52 0
|
11月前
嵌入式day6(2022.1.12)
嵌入式day6(2022.1.12)
58 0
|
11月前
|
存储 编译器
day8嵌入式(2022.1.14)
day8嵌入式(2022.1.14)
51 0
|
11月前
|
机器学习/深度学习 C语言
嵌入式day5(2022.1.11)
嵌入式day5(2022.1.11)
97 0
|
11月前
|
存储
day7嵌入式(2022.1.13)
day7嵌入式(2022.1.13)
52 0
|
11月前
嵌入式day2(2022.1.7)
嵌入式day2(2022.1.7)
59 0
|
11月前
|
自然语言处理 编译器 C语言
day11嵌入式(2022.1.17)
day11嵌入式(2022.1.17)
67 0
嵌入式C++(二)(下)
嵌入式C++(二)(下)
嵌入式C++(二)(下)