Linux 网络编程笔记3 | 内存 系统调用

2023-05-16

七、内存

1、虚拟内存、物理内存、半导体内存和换页文件

虚拟内存:地址空间,虚拟的存储区域,应用程序所访问的都是虚拟内存。
物理内存:存储空间,实际的存储区域,只有系统内核可以访问物理内存。
虚拟内存和物理内存之间存在对应关系,当应用程序访问虚拟内存时,系统内核会依据这种对应关系找到与之相应的物理内存。上述对应关系存储在内核中的内存映射表中。
物理内存包括半导体内存和换页文件两部分。
当半导体内存不够用时,可以把一些长期闲置的代码和数据从半导体内存中缓存到换页文件中,这叫页面换出,一旦需要使用被换出的代码和数据,再把它们从换页文件恢复到半导体内存中,这叫页面换入。因此,系统中的虚拟内存比半导体内存大得多。

2、进程映射(Process Maps)

每个进程都拥有独立的4G字节的虚拟内存,分别被映射到不同的物理内存区域。
内存映射和换入换出都是以页为单位,1页=4096字节。
4G虚拟内存中高地址的1G被映射到内核的代码和数据区,这1个G在各个进程间共享。用户的应用程序只能直接访问低地址的3个G虚拟内存,因此该区域被称为用户空间,而高地址的1个G虚拟内存则被称为内核空间。用户空间中的代码只能直接访问用户空间的数据,如果要想访问内核空间中的代码和数据必须借助专门的系统调用完成。
用户空间的3G虚拟内存可以进一步被划分为如下区域:
------------------
系统内核(1G)
高地址------------------
命令行参数
和环境变量
------------------
栈区:非静态局部变量
- - - - - - - -
v
3G
^
- - - - - - - -
堆区:动态内存分配(malloc函数族)
-----------------
BSS区:无初值的全局和静态局部变量
-----------------
数据区:非const型有初值的全局和静态局部变量
-----------------
只读常量:字面值常量,const型有初值的全局
和静态局部变量
代码区(正文段):可执行指令
低地址-----------------
代码:maps.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
const int const_global = 10; // 常全局变量
int init_global = 10; // 初始化全局变量
int uninit_global; // 未初始化全局变量
int main(int argc, char* argv[]) {
    // 常静态变量
    const static int const_static = 10;
    // 初始化静态变量
    static int init_static = 10;
    // 未初始化静态变量
    static int uninit_static;
    // 常局部变量
    const int const_local = 10;
    int prev_local; // 前局部变量
    int next_local; // 后局部变量
    // 前堆变量
    int* prev_heap = malloc(sizeof(int));
    // 后堆变量
    int* next_heap = malloc(sizeof(int));
    // 字面值常量
    char const* literal = "literal";
    extern char** environ; // 环境变量
    printf("--------------高地址 ------------\n");
    printf("---- 命令行参数与环境变量 ----\n");
    printf("         环境变量:%p\n", environ);
    printf("       命令行参数:%p\n", argv);
    
    printf("-------------- 栈 ------------\n");
    printf("       后局部变量:%p\n",&next_local);
    printf("       前局部变量:%p\n", &prev_local);
    printf("       常局部变量:%p\n", &const_local);
    
    printf("-------------- 堆 ------------\n");
    printf("         后堆变量:%p\n", next_heap);
    printf("         前堆变量:%p\n", prev_heap);
    printf("------------- BSS ------------\n");
    
    printf(" 未初始化全局变量:%p\n",&uninit_global);
    printf(" 未初始化静态变量:%p\n",&uninit_static);
    
    printf("------------ 数据 ------------\n");
    printf("   初始化静态变量:%p\n", &init_static);
    printf("   初始化全局变量:%p\n", &init_global);
    
    printf("------------ 代码 ------------\n");
    printf("       常静态变量:%p\n",
        &const_static);
    printf("       字面值常量:%p\n", literal);
    printf("       常全局变量:%p\n",
        &const_global);
    printf("             函数:%p\n",
        main);
    printf("---------------低地址---------------\n");
    return 0;
}

命令:size
通过size命令查看一个可执行程序的代码区、数据区和BSS区的大小。
每个进程的用户空间都拥有独立的从虚拟内存到物理内存的映射,为之进程间的内存壁垒。
代码:vm.c

#include <stdio.h>
int g_vm = 0;
int main(void) {
    printf("虚拟内存地址:%p\n", &g_vm);
    printf("输入一个整数:");
    scanf("%d%*c", &g_vm);//%*c的意思是清理丢弃回车
    printf("启动另一个进程,输入不同数据,"
        "按<回车>键继续...");
    getchar();
    printf("虚拟内存数据:%d\n", g_vm);
    return 0;
}

代码:vm2.c

#include <stdio.h>
int g_vm = 0;
int main(void) {
    printf("虚拟内存地址:%p\n", &g_vm);
    printf("输入一个整数:");
    scanf("%d%*c", &g_vm);//%*c的意思是清理丢弃回车
    printf("启动另一个进程,输入不同数据,"
        "按<回车>键继续...");
    getchar();
    printf("虚拟内存数据:%d\n", g_vm);
    return 0;
}

3、内存的分配与释放

malloc/calloc/realloc/free
|
v
brk/sbrk
|
v
mmap/munmap
|
v
kmalloc/kfree
以增加方式分配或释放虚拟内存
分配:映射+占有
| ____________
在地址空间(虚拟内存)和
存储空间(物理内存)之间 指定内存空
建立映射关系 间的归属性
释放:放弃占有+解除映射
| |
解除对内存空 消除地址空间(虚拟内存)和存储
间的归属约束 空间(物理内存)之间的映射关系
#include <unistd.h>
void* sbrk(intptr_t increment);
堆顶->- - - - - - - -
堆区
-----------------
sbrk(10)
堆顶->- - - - - - - -
10字节
- - - - - - - -<-返回值
堆区
-----------------
sbrk(-10)
- - - - - - - -<-返回值
10字节
堆顶->- - - - - - - -
堆区
-----------------
成功返回调用该函数之前的堆顶指针,失败返回-1。
increment
>0 - 堆顶指针上移,增大堆空间,分配虚拟内存
<0 - 堆顶指针下移,缩小堆空间,释放虚拟内存
=0 - 不分配也不释放虚拟内存,仅仅返回当前堆顶指针
系统内核维护一个指针,指向堆内存的顶端,即有效堆内存中最后一个字节的下一个位置。sbrk函数根据增量参数increment调整该指针的位置,同时返回该指针原来的位置,期间若发生内存耗尽或空闲,则自动追加或取消相应内存页的映射。
123____~~~~~~~~…
^ ^ ^ ^
堆顶
代码:sbrk.c

#include <stdio.h>
#include <unistd.h>
int main(void) {
    setbuf(stdout, NULL);
    int* p1 = (int*)sbrk(sizeof(int));
    if (p1 == (int*)-1) {
        perror("sbrk");
        return -1;
    }
    *p1 = 0;
    printf("%d\n", *p1);
    double* p2 = (double*)sbrk(sizeof(double));
    if (p2 == (double*)-1) {
        perror("sbrk");
        return -1;
    }
    *p2 = 1.2;
    printf("%g\n", *p2);
    char* p3 = (char*)sbrk(256 * sizeof(char));
    if (p3 == (char*)-1) {
        perror("sbrk");
        return -1;
    }
    sprintf(p3, "Hello, World!");
    printf("%s\n", p3);
    /*
    if (sbrk(-(256 * sizeof(char) +
        sizeof(double) +
        sizeof(int))) == (void*)-1) {
        perror("sbrk");
        return -1;
    }
    */
    if (brk(p1) == -1) {
        perror("brk");
        return -1;
    }
    return 0;

以绝对地址的方式分配或释放虚拟内存
int brk(void* end_data_segment);
成功返回0,失败返回-1。
end_data_segment
>当前堆顶,分配虚拟内存
<当前堆顶,释放虚拟内存
=当前堆顶,空操作
堆顶->- - - - - - - -<-void* p = sbrk(0);
堆区
-----------------
brk(p+10)
- - - - - - - -<-p+10
10字节
堆顶->- - - - - - - -
堆区
-----------------
brk§
堆顶->- - - - - - - -<-p
堆区
-----------------
系统内核维护一个指针,指向当前堆顶,brk函数根据指针参数end_data_segment设置堆顶的新位置,期间若发生内存耗尽或空闲,则自动追加或取消相应内存页的映射。
代码:brk.c

#include <stdio.h>
#include <unistd.h>
/*
 * xxxIIIIDDDDDDDDCC...C
 *    ^   ^       ^     ^
 *    p1  p2      p3
 */
int main(void) {
    setbuf(stdout, NULL);//setbuf函数用于打开和关闭缓冲机制,因为没遇到换行也
                         //没有填满缓冲区,所以会导致printf()打印不出来,
                         //将标准输出设置为不带缓冲的.printf()也有缓冲区,
                         //它的缓冲区也在堆内分布。
    int* p1 = (int*)sbrk(0);
    if (p1 == (int*)-1) {
        perror("sbrk");
        return -1;
    }
    double* p2 = (double*)(p1 + 1);
    if (brk(p2) == -1) {
        perror("brk");
        return -1;
    }
    *p1 = 0;
    printf("%d\n", *p1);
    char* p3 = (char*)(p2 + 1);
    if (brk(p3) == -1) {
        perror("brk");
        return -1;
    }
    *p2 = 1.2;
    printf("%g\n", *p2);
    void* p4 = p3 + 256;
    if (brk(p4) == -1) {
        perror("brk");
        return -1;
    }
    sprintf(p3, "Hello, World!");
    printf("%s\n", p3);
    if (brk(p1) == -1) {
        perror("brk");
        return -1;
    }
    return 0;
}

void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset);

建立虚拟内存到物理内存或文件的映射
#include <sys/mman.h>
void* mmap(void* start, size_t length, int prot, int flags, int fd, off_t offset);
成功返回映射区虚拟内存的起始地址,失败返回MAP_FAILED(void类型的-1)。
start - 映射区虚拟内存的起始地址,NULL表示自动选择
length - 映射区的字节数,自动按页取整
prot - 访问权限,可取以下值:
PROT_READ - 可读
PROT_WRITE - 可写
PROT_EXEC - 可执行
PROT_NONE - 不可访问
flags - 映射标志,可取以下值:
MAP_ANONYMOUS - 匿名映射,将虚拟内存映射到物理内存,函数的最后两个参数fd和offset被忽略
MAP_PRIVATE - 私有映射,将虚拟内存映射到文件的内存缓冲区中而非磁盘文件
MAP_SHARED - 共享映射,将虚拟内存映射到磁盘文件中
MAP_DENYWRITE - 拒写映射,文件中被映射区域不能存在其它写入操作
MAP_FIXED - 固定映射,若在start上无法创建映射,则失败(无此标志系统会自动调整)
MAP_LOCKED - 锁定映射,禁止被换出到换页文件
fd - 文件描述符
offset - 文件偏移量,自动按页对齐
解除虚拟内存到物理内存或文件的映射
int munmap(void
start, size_t length);
成功返回0,失败返回-1。
start - 映射区的起始地址
length - 映射区的字节数
代码:mmap.c

#include <stdio.h>
#include <unistd.h>
#include <sys/mman.h>
int main(void) {
    char* psz = mmap(NULL, 8192,
        PROT_READ | PROT_WRITE,
        MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
    if (psz == MAP_FAILED) {
        perror("mmap");
        return -1;
    }
    sprintf(psz, "第一页");
    sprintf(psz + 4096, "第二页");
    printf("%s\n", psz);
    printf("%s\n", psz + 4096);
    if (munmap(psz, 4096) == -1) {
        perror("munmap");
        return -1;
    }
    //printf("%s\n", psz);
    printf("%s\n", psz + 4096);
    if (munmap(psz + 4096, 4096) == -1) {
        perror("munmap");
        return -1;
    }
    return 0;
}

八、系统调用

应用程序--------------+
vi/emacs/gftp/firefox |
| |
标准库、第三方库 |
C/C++/Qt/X11 |
| |
系统调用<------------+
brk/sbrk/mmap/munmap
1.Linux系统内核提供了一套用于实现各种系统功能的子程序,谓之系统调用。程序编写者可以象调用普通C语言函数一样调用这些系统调用函数,以访问系统内核提供的各种服务。
2.系统调用函数在形式上与普通C语言函数并无差别。二者的不同之处在于,前者工作在内核态,而后者工作在用户态。
3.在Intel的CPU上运行代码分为四个安全级别:Ring0、Ring1、Ring2和Ring3。Linux系统只使用了Ring0和Ring3。用户代码工作在Ring3级,而内核代码工作在Ring0级。一般而言用户代码无法访问Ring0级的资源,除非借助系统调用,使用户代码得以进入Ring0级,使用系统内核提供的功能。
4.系统内核内部维护一张全局表sys_call_table,表中的每个条目记录着每个系统调用在内核代码中的实现入口地址。
5.当用户代码调用某个系统调用函数时,该函数会先将参数压入堆栈,将系统调用标识存入eax寄存器,然后通过int 80h指令触发80h中断。
6.这时程序便从用户态(Ring3)进入内核态(Ring0)。
7.工作系统内核中的中断处理函数被调用,80h中断的处理函数名为system_call,该函数先从堆栈中取出参数,再从eax寄存器中取出系统调用标识,然后再从sys_call_table表中找到与该系统调用标识相对应的实现代码入口地址,挈其参数调用该实现,并将处理结果逐层返回到用户代码中。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Linux 网络编程笔记3 | 内存 系统调用 的相关文章

  • 【计算机网络】第二章:物理层

    各个章节的知识点总结传送门如下 xff0c 欢迎自取 xff1a 计算机网络 第一章 xff1a 计算机网络概述https blog csdn net iwanderu article details 103795715 计算机网络 第二章
  • 【计算机网络】第四章:网络层

    各个章节的知识点总结传送门如下 xff0c 欢迎自取 xff1a 计算机网络 第一章 xff1a 计算机网络概述https blog csdn net iwanderu article details 103795715 计算机网络 第二章
  • ASCII码与16进制的互相转换(表)

    所谓的ASCII和16进制都只是概念上的东西 xff0c 在计算机中通通是二进制 转换应该是输出的转换 xff0c 同样是一个数 xff0c 在计算机内存中表示是一样的 xff0c 只是输出不一样 ASCII是针对字符的编码 xff0c 几
  • 【操作系统】 Operation System 第一章:概述

    各部分总结知识点如下 xff1a 操作系统 Operation System 第一章 xff1a 概述 操作系统 Operation System 第二章 xff1a 操作系统基础操作 操作系统 Operation System 第三章 x
  • 【openCV踩坑日记】人工数据集Synthetic Shapes dataset的生成方法

    1 为什么要介绍这个方法 xff1f 2018年的时候 xff0c D DeTone等人发表了Self Supervised Interest Point Detection and Description xff0c 提出了一种特征提取S
  • 【SLAM】ORB-SLAM3解析——综述(1)

    之前学习VINS和LIO SAM的时候都是代码流 xff0c 不是很重视看论文 xff0c 现在有空学ORB SLAM3了 xff0c 这一次 xff0c 先看一下论文 考虑到边上班边学 xff0c 更新的会比较慢 看完论文之后 xff0c
  • 【SLAM】LVI-SAM解析——综述

    LVI SAM可以认为是LIO SAM和VINS MONO的合体 xff0c 在此基础上的修改不大 github xff1a https github com TixiaoShan LVI SAM paper LVI SAM Tightly
  • 【SLAM】DM-VIO(ros版)安装和论文解读

    1 dm vio的安装 进入官方链接 xff0c 基本上就是按照readme的操作来 xff1a 下载代码 xff1a git clone https github com lukasvst dm vio git 安装gtsam xff1a
  • 【SLAM】SVO2.0编译运行和论文代码解读

    SVO2是我遇到的最难编译的代码了 xff0c 毕竟公开版本怎么能放最好的代码呢 xff0c 搞了快一个星期 xff0c 终于跑起来了 github xff1a GitHub uzh rpg rpg svo pro open 论文 xff1
  • 【工具篇】postman的完全使用,全是干货

    目录 一 x1f347 GET请求 二 x1f348 POST请求 三 x1f349 PUT请求 四 x1f34a DELETE请求 五 x1f34b Headers 六 x1f34c 认证 xff08 1 xff09 基本认证 xff1a
  • GPS全球定位系统构成及原理

    GPS全球定位系统构成及原理 全球定位系统 GPS 是本世纪70年代由美国陆海空三军联合研制的新一代空间卫星导航定位系统 其主要目的是为陆 海 空三大领域提供实时 全天候和全球性的导航服务 xff0c 并用于情报收集 核爆监测和应急通讯等一
  • Visual C++设计UDP协议通讯示例

    下载本文源代码 一 绪言 UDP是一种面向非连接 xff0c 不可靠的通讯协议 xff0c 相对于 TCP来说 xff0c 虽然可靠性不及 xff0c 但传输效率较高 所以在网络上仍有很大的用途 这几日需要了解下udp通讯的过程 xff0c
  • 树莓派控制舵机云台

    文章目录 学习记录舵机代码分析 学习记录 手上有一套电赛时候买的舵机云台 扭矩15KG 型号为LD 1501MG 舵机 两个LD 1501MG舵机角度范围都是180度 控制的PWM波周期为20ms 角度与正脉冲宽度映射如下所示 0 5ms
  • jetson nano 编译pyrealsense2 运行t265

    在win10 的环境下 xff0c 安装pyrealsense2 xff0c 只需要简单的pip就可以了 xff0c 没想到在jetson nano下却花了那么多时间和精力 其实解决方案网上都有 xff0c 但是比较零碎 xff0c 只能遇
  • openmv探索_4_AprilTag标记追踪

    原理及代码 AprilTag标记追踪 空间坐标系的建立 以镜头中心为坐标系原点 xff0c 建立空间坐标系 图2 1 空间坐标系 旋转角度 xff08 参考系是上图中的坐标系 xff09 1 初始状态 图3 1 物体摆放的初始位置 上图的
  • Xsens MTi传感器 ROS下配置

    Xsens MTi传感器 ROS 1 概述2 MTI设置 MTmanager3 ROS下信息发布 MTSDK4 找不到设备 xff15 参考链接 xff16 延伸阅读传感器配置节点程序分析经典SLAM 1 概述 主要介绍Ubuntu下对Xs
  • 雷达点云 PointCloud2 格式转换

    雷达点云 sensor msgs PointCloud2 pcl PointCloud 数据格式转换参考代码 官方对点云格式的介绍 xff0c 主要有四种 xff0c sensor msgs PointCloud已经弃用 参考 sensor
  • Gmapping 之安装与配置

    Gmapping 之安装与配置 1 概述2 安装2 1 github仓库 3 运行3 1 运行截图3 2 重采样时的提示信息3 3 tf树 96 rosrun rqt tf tree rqt tf tree 96 3 4 所有的坐标变换信息
  • Gmapping Dropped 100.00% of messages so far 解决办法

    Dropped 100 00 of messages so far解决办法 概述显示tf树正常情况报错情况参考链接Gmapping 概述 运行Gmappping时出现错误提示 xff0c 其他参数 xff1a 话题等都设置正确了 xff0c
  • LOAM SLAM安装与配置

    LOAM SLAM安装与配置 1 概述2 安装3 运行4 结果5 其他6 参考链接 1 概述 简单介绍LOAM SLAM的安装与配置 xff0c 希望能帮助大家 xff0c 同时供自己以后参考 2 安装 运行LOAM需要PCL等库支持 xf

随机推荐

  • 什么是MSB、LSB,什么是大端、小端,区别是什么?

    MSB是Most Significant Bit的缩写 xff0c 最高有效位 在二进制数中 xff0c MSB是最高加权位 与十进制数字中最左边的一位类似 通常 xff0c MSB位于二进制数的最左侧 xff0c LSB位于二进制数的最右
  • ROS报错 cant locate node 解决办法

    ROS报错 can 39 t locate node 解决办法 1 概述2 原因3 解决办法4 其他 1 概述 ROS突然出现不能运行节点的问题 xff0c 这里简单介绍一下自己的解决办法 这个方法还是有缺陷 xff0c 更新方法在ROS编
  • ubuntu 开机后 按键 鼠标不能用

    ubuntu 开机后 按键 鼠标不能用 1 现象2 解决办法3 参考链接 1 现象 版本ubuntu 1804安装bumblebee后 xff0c 重启机器出现不能使用鼠标 键盘的现象 xff0c 具体点就是 xff0c 只有开机后的桌面显
  • 相机标定之使用ROS节点程序

    相机标定之使用ROS节点程序 1 概述2 准备3 步骤4 相关链接 1 概述 简单介绍如何使用ROS节点程序进行针孔模型相机标定的步骤 xff0c 供自己以后参考 xff0c 同时希望给大家带来帮助 2 准备 提前准备好棋盘格并打印出来 x
  • 相机标定之使用Matlab工具箱

    相机标定之使用Matlab工具箱 1 概述2 准备3 步骤4 相关链接 1 概述 简单介绍如何使用Matlab进行针孔模型相机标定的步骤 xff0c 供自己以后参考 xff0c 同时希望给大家带来帮助 2 准备 提前准备好棋盘格并打印出来
  • QT安装教程

    QT安装教程 1 概述2 下载安装2 1 下载2 2 安装2 3 安装配置其他环境2 4 安装成功2 5 问题及解决 3 参考链接 1 概述 简单介绍如何在Ubuntu下安装QT xff0c 希望能够帮助大家 xff0c 同时给自己一个参考
  • C++面向过程

    参考文档 xff1a C 43 43 教程 C 43 43 简介 概述 C 43 43 是一种静态类型的 编译式的 通用的 大小写敏感的 不规则的编程语言 xff0c 支持过程化编程 面向对象编程和泛型编程 C 43 43 是 C 的一个超
  • vector 指针 的指针

    vector 不能用指针 xff0c 用指针 xff0c push back会报错 xff0c size 也不对 vector本身用对象 xff0c 内容 简化为A 可以用指针 xff0c 当指针对象中还有指针B时 xff0c 就要用new
  • cmake find_package opencv 找不到

    目录 cmakelist设置方法ok 环境变量设置方法ok linux写法 cmakelists txt完整示例 find opencv lib find package OpenCV REQUIRED NO MODULE should b
  • liveplayer

    npm i 64 liveqing liveplayer S lt template gt lt div class 61 34 live player 34 gt lt div style 61 34 width 640px height
  • DLT algorithm needs at least 6 points for pose estimation from 3D-2D point correspondences. (expecte

    DLT algorithm needs at least 6 points for pose estimation from 3D 2D point correspondences expected 39 count gt 61 6 39
  • 关于OSD

    OSD的主要实现方法和类型 目前有两种主要的OSD实现方法 xff1a 外部OSD发生器与视频处理器间的叠加合成 xff1b 视频处理器内部 支持OSD xff0c 直接在视频缓存内部叠加OSD信息 外部OSD发生器与视频处理器间的叠加合成
  • RTK使用笔记-千寻CORS模式

    一 千寻CORS模式 与基站 43 接收机1对1相比 xff0c 优点为携带方便 xff0c 也不用考虑10公里移动基站问题 xff1b 缺点为第一千寻CORS模式有自己基站涵盖范围 xff0c 所以需要提前确定好范围 xff08 下文有介
  • c/c++语言实现登陆界面

    C C 43 43 语言实现登陆界面 整体功能介绍 实现一个登陆界面 1 输出一个登陆界面 2 用户名能够实现邮箱验证 xff0c regex库 xff0c 密码要不可见 3 进度条的模拟实现 4 音乐播放 分步实现 1 输出一个登陆界面
  • _getch()函数的介绍

    getch 函数的介绍及实例演示 我们一般所使用的 getchar 函数在读入一个字符时必须按一下 Enter 键 xff0c 该代码才会继续运行 但是 getch 函数读入一个字符时 不用 enter 代码会继续跑 xff1b 最简单使用
  • 嵌入式常见面试题

    嵌入式LINUX常见面试问题总结 声明 xff1a 本文是将常见的面试问题进行汇总 xff0c 但大多数问题也是开发中较为常见的技术盲区 xff01 在此进行了汇总 xff0c 以便后续进行参考 xff01 所有的答案部分是自己编写 xff
  • LINUX基础试题大全(1)

    说明 xff1a 此文章由于题数庞大 xff0c 为方便阅读本人将其分为四篇文章为大家分享 xff01 答案会今后不断进行更新 xff01 LINUX基础试题大全 xff08 1 xff09 填空题题 LINUX基础试题大全 xff08 2
  • C语言 | 深入学习数组

    说明 xff1a 本文主要讨论一维数组 xff0c 适宜程度 xff1a 对C语言初步认识及想深入学习者 1 从编译器角度理解数组 从编译器角度理解来讲 xff0c 数组也是一个变量 xff0c 和普通的变量没有本质的区别 变量的本质指的是
  • C语言 结构体 联合体 | 嵌套使用

    一 简单的实例分析 题目 xff1a 获取0x12345678各个字节 答案 xff1a span class token comment 方法一 span span class token macro property span clas
  • Linux 网络编程笔记3 | 内存 系统调用

    七 内存 1 虚拟内存 物理内存 半导体内存和换页文件 虚拟内存 xff1a 地址空间 xff0c 虚拟的存储区域 xff0c 应用程序所访问的都是虚拟内存 物理内存 xff1a 存储空间 xff0c 实际的存储区域 xff0c 只有系统内