精华内容
下载资源
问答
  • ????动态分区分配算法 ????基本分页储存管理的脚本概念 学习资源来源: 王道考研 操作系统

    📖动态分区分配算法

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    📖基本分页储存管理的脚本概念

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    学习资源来源:
    王道考研 操作系统

    展开全文
  • 磁盘储存管理概念 机械硬盘 HDD 固态硬盘 SSD SSD的优势:读取速度快,闪存芯片、防震抗摔,数据丢失性可能小,重量轻。 物理硬盘: /dev/sd[a-z] KVM虚拟化: /dev/vd[a-z] 从存储连接方式 本地存储 例如DellR730...

    第七章:储存管理

    主要知识点:
    基本分区、逻辑卷LVM、EXT3/4/XFS文件系统、RAID


    一.磁盘储存管理概念

    机械硬盘 HDD 固态硬盘 SSD

    SSD的优势:读取速度快,闪存芯片、防震抗摔,数据丢失性可能小,重量轻。

    物理硬盘: /dev/sd[a-z]

    KVM虚拟化: /dev/vd[a-z]

    从存储连接方式

    本地存储 例如DellR730本地磁盘

    外部存储 scsi线 sata线 sas线 FC线

    网络存储 以太网络(iscsi, glusterFS,ceph) FC网络**

    从分区方式区分

    MBR <2TB fdisk 14个分区 (4个主分区,扩展分区,逻辑分区) 例如: 3主 + 1扩展(n逻辑)
    GPT >2TB gdisk(parted) 128个主分区 注意:从MBR转到GPT,或从GPT转换到MBR会导致数据全部丢失!
    MBR: 磁盘引导 //分完区之后不可直接使用,需要先格式化
    在这里插入图片描述

    在这里插入图片描述

    =====================================================================

    二.磁盘基本分区

    基本分区(MBR|GPT) ----> Filesystem ----> mount

    实战条件:首先在虚拟机添加一块虚拟磁盘

    [root@lxw2 ~]# ll /dev/sd*        //长格式查看系统上所有的磁盘
    [root@lxw2 ~]#  lsblk             //查看磁盘信息
    
    1.fdisk  命令   【创建分区】
    MBR   14个分区(4个主分区,扩展分区,逻辑分区)
    [root@lxw2 ~]# fdisk /dev/sdc     //对sdc盘进行分区
    欢迎使用 fdisk (util-linux 2.23.2)。
    
    更改将停留在内存中,直到您决定将更改写入磁盘。
    使用写入命令前请三思。
    
    Device does not contain a recognized partition table
    使用磁盘标识符 0xe666fc31 创建新的 DOS 磁盘标签。
    
    命令(输入 m 获取帮助):m    //输入'm' 可查询帮助命令
    命令操作
       a   toggle a bootable flag
       b   edit bsd disklabel
       c   toggle the dos compatibility flag
       d   delete a partition       //删除一个已有的分区
       g   create a new empty GPT partition table    //创建一个空的GPT格式分区表,默认为dos  
       G   create an IRIX (SGI) partition table
       l   list known partition types         //列出分区类型
       m   print this menu                   //打印帮助信息
       n   add a new partition                //添加一个新的分区
       o   create a new empty DOS partition table      // 创建一个空的DOS格式分区表,默认为dos  
       p   print the partition table               //打印当前的分区表
       q   quit without saving changes            //  不保存退出
       s   create a new empty Sun disklabel
       t   change a partition's system id         //改变分区的系统ID
       u   change display/entry units
       v   verify the partition table
       w   write table to disk and exit           //保存分区变更
       x   extra functionality (experts only)
    命令(输入 m 获取帮助):n   // 按n创建分区  常用命令有以上备注中文翻译的,其他的如若后续需要可以自己去查找翻译。
    ommand (m for help): p     //选择p,打印当前分区表
    分区号 (1-4,默认 1):      //回车键,选择默认即可
    起始 扇区 (2048-20971519,默认为 2048):    //继续回车默认
    Last 扇区, +扇区 or +size{K,M,G} (2048-20971519,默认为 20971519):+2G     //这里选择配置磁盘大小,可自定义。
    命令(输入 m 获取帮助):n   // 按n创建分区  常用命令有以上备注中文翻译的,其他的如若后续需要可以自己去查找翻译。
    ommand (m for help): p     //选择p,打印当前分区表
    分区号 (1-4,默认 1):      //回车键,选择默认即可
    起始 扇区 (2048-20971519,默认为 2048):    //继续回车默认
    Last 扇区, +扇区 or +size{K,M,G} (2048-20971519,默认为 20971519):+2G     //这里选择配置磁盘大小,可自定义。
    命令(输入 m 获取帮助):n   // 按n创建分区  常用命令有以上备注中文翻译的,其他的如若后续需要可以自己去查找翻译。
    ommand (m for help): p     //选择p,打印当前分区表
    分区号 (1-4,默认 1):      //回车键,选择默认即可
    起始 扇区 (2048-20971519,默认为 2048):    //继续回车默认
    Last 扇区, +扇区 or +size{K,M,G} (2048-20971519,默认为 20971519):+2G     //这里选择配置磁盘大小,可自定义。
    
    命令(输入 m 获取帮助):n     //注意这边已经创建三个磁盘了所以第四个就要选择扩展分区,下面选择e
    Partition type:
       p   primary (3 primary, 0 extended, 1 free)
       e   extended
    Select (default e): e         
    起始 扇区 (12584960-20971519,默认为 12584960):     //回车默认
    Last 扇区, +扇区 or +size{K,M,G} (12584960-20971519,默认为 20971519):    //注意这里是创建扩展,所以剩余的储存全部给予扩展分区,当然也可自定义
    命令(输入 m 获取帮助):n       //选择n创建逻辑分区
    起始 扇区 (12587008-20971519,默认为 12587008):      //选择默认
    Last 扇区, +扇区 or +size{K,M,G} (12587008-20971519,默认为 20971519):+1G              //注意,这里需要添加内存了,如果回车那就全部内存给予这一个逻辑分区 
    命令(输入 m 获取帮助):n      //选择n
    起始 扇区 (14686208-20971519,默认为 14686208):      //回车默认
    Last 扇区, +扇区 or +size{K,M,G} (14686208-20971519,默认为 20971519):+1G     //增加储存
    命令(输入 m 获取帮助):n      //选择n
    起始 扇区 (14686208-20971519,默认为 14686208):      //回车默认
    Last 扇区, +扇区 or +size{K,M,G} (14686208-20971519,默认为 20971519):       //回车默认,这里默认是把所有内存都放至最后一个逻辑分区。
    
    命令(输入 m 获取帮助):p          //按p查看当前磁盘分区信息
    
    磁盘 /dev/sdc:10.7 GB, 10737418240 字节,20971520 个扇区
    Units = 扇区 of 1 * 512 = 512 bytes
    扇区大小(逻辑/物理):512 字节 / 512 字节
    I/O 大小(最小/最佳):512 字节 / 512 字节
    磁盘标签类型:dos
    磁盘标识符:0x8ae6b12c
    
       设备 Boot      Start         End      Blocks   Id  System
    /dev/sdc1            2048     4196351     2097152   83  Linux
    /dev/sdc2         4196352     8390655     2097152   83  Linux
    /dev/sdc3         8390656    12584959     2097152   83  Linux
    /dev/sdc4        12584960    20971519     4193280    5  Extended
    /dev/sdc5        12587008    14684159     1048576   83  Linux
    /dev/sdc6        14686208    16783359     1048576   83  Linux
    /dev/sdc7        16785408    20971519     2093056   83  Linux
    
    命令(输入 m 获取帮助):w        //保存分区并退出
    ps:如果添加储存失败了,^c 退出重来即可。
    [root@lxw2 ~]# lsblk            //查看磁盘分区信息
    NAME            MAJ:MIN RM  SIZE RO TYPE  MOUNTPOINT
    sda               8:0    0   20G  0 disk  
    ├─sda1            8:1    0    1G  0 part  /boot
    └─sda2            8:2    0   19G  0 part  
      ├─centos-root 253:0    0   17G  0 lvm   /
      └─centos-swap 253:1    0    2G  0 lvm   [SWAP]
    sdb               8:16   0   10G  0 disk  
    sdc               8:32   0   10G  0 disk  
    ├─sdc1            8:33   0    2G  0 part  
    ├─sdc2            8:34   0    2G  0 part  
    ├─sdc3            8:35   0    2G  0 part  
    ├─sdc4            8:36   0    1K  0 part  
    ├─sdc5            8:37   0    1G  0 part  
    ├─sdc6            8:38   0    1G  0 part  
    └─sdc7            8:39   0    2G  0 part 
    
    2 gdisk   
    GPT  128个主分区
    这里操作和以上操作类似,这里就不过多讲解了。
    
    3.创建文件系统(格式化)centos7 默认使用xfs  //系统必须格式化才可使用和window原理相同
    [root@lxw2 ~]# mkfs.xfs /dev/sdc1       //注意每个磁盘分区完之后必须要进行格式化才能正常使用
    [root@lxw2 ~]# mkfs.ext4 /dev/sdc2      //使用ext4格式化磁盘分区
    
    4.挂载
    [root@lxw2 ~]# mkdir /mnt/disk1       //创建挂载目录,名称自定义
    [root@lxw2 ~]# mkdir /mnt/disk1       //创建挂载目录
    [root@lxw2 ~]# mount -t xfs /dev/sdc1 /mnt/disk1    //临时挂载,重启后会失效
    [root@lxw2 ~]# umount /mnt/disk1       //取消挂载 
    [root@lxw2 ~]# vim /etc/fstab          //永久挂载配置文件
    UUID="9bf6b9f7-92ad-441b-848e-0257cbb883d1"  /mnt/disk1   auto    defaults    0 0         
    UUID="4d26172c-7aff-4388-baa5-c6756c014d52"  /mnt/disk2    ext4    ro    0 0            //格式如下,先要执行blkid查询需要挂载的UUID
    [root@lxw2 ~]# mount -a              //重新加载挂载信息
    [root@lxw2 ~]# df -Th                //查看挂载信息
    
    
    如果挂载失败,导致机器无法启动:
    1.开机界面按e进入grub系统界面:
    2.在linux16行末尾输入 rd.break console=tty1
    3.ctrl + x  重新加载启动
    4.mount -o remount,rw /sysroot    
    5.chroot /sysroot
    6.passwd                               #输入2次密码
    7.touch /.autorelabel
    8.exit
    9.reboot      //重新系统然后输入密码即可正常使用
    
    
    

    =====================================================================

    三.逻辑卷LVM

    1.LVM 管理

    在线扩容 online
    数据迁移 online

    创建LVM VG扩展/缩小 LV扩容 文件系统扩容 //主要学习目标

    基本分区(MBR|GPT) ----> Filesystem ----> mount
    逻辑卷LVM ----> Filesystem ----> mount
    PE: Physical extent 物理扩展 4M 8M 16M 32M 64M 创建VG时指定 -s 8M
    LE: Logical extent 逻辑扩展

    实战需要准备环境可以使:/dev/sdc1

    实战演示:
    [root@lxw2 ~]# ll /dev/sdb                    //查看sdc磁盘
    
    1.创建pv
    [root@lxw2 ~]# pvcreate /dev/sdb3        //创建pv
      Physical volume "/dev/sdb3" successfully created.
    [root@lxw2 ~]# pvs        //查看pv    pvscan   pvdisplay   //都可以查看pv,三种查看方式
      PV         VG     Fmt  Attr PSize    PFree   
      /dev/sda2  centos lvm2 a--   <19.00g      0 
      /dev/sdb3         lvm2 ---     2.00g   2.00g
    
    
    2.创建vg
    [root@lxw2 ~]# vgcreate vg3 /dev/sdb3           //创建vg3
      Volume group "vg3" successfully created       //则显示成功
    [root@lxw2 ~]# vgs                //查看vg信息   vgscan    vgdispay   //都可查看vg信息
    
    
    3.创建lv
    [root@lxw2 ~]# lvcreate -l 20 -n lv3 vg3        //创建lv3
     Logical volume "lv3" created.                 //显示此信息表示成功
    [root@lxw2 ~]# lvcreate -L 200M -n lv3 vg3    //创建lv3 方法二 -L 后加上lv内存大小  -l 20代表PE,1PE等于4M,也就是80M大小
    [root@lxw2 ~]# lvs      //查看lv信息  lvscan   lvmdiskscan  //都可查看lv信息
    
    4.创建文件系统并挂载
    [root@lxw2 ~]# mkfs.xfs /dev/vg3/lv3            //创建文件系统xfs格式,并格式化
    [root@lxw2 ~]# mkdir -pv /mnt/disk3             //创建准备挂载的目录
    [root@lxw2 ~]# mount -t xfs /dev/vg3/lv3 /mnt/disk3    //进行挂载
    
    [root@lxw2 ~]# mkfs.ext4 /dev/vg1/lv2          //创建系统文件ext4格式,并格式化
    [root@lxw2 ~]# mkdir /mnt/lv1 /mnt/lv2         //创建lv1 lv2挂载目录 
    [root@lxw2 ~]#  vim /etc/fstab                //进入永久挂载系统配置文件      ,先查询blkid ,查询UUID信息。
    /dev/vg1/lv1    /mnt/lv1        xfs     defaults 0 0
    /dev/vg1/lv2    /mnt/lv2        ext4    defaults 0 0
    [root@lxw2 ~]# mount -a           //重新加载系统信息
    [root@lxw2 ~]# df -Th             //显示所有磁盘挂载信息
    
    
    
    5.VG管理
    5.1 .扩大VG vgextend
    1.pv
    [root@lxw2 ~]# pvcreate /dev/sdd
    2.vgextend
    [root@lxw2 ~]# vgextend vg1 /dev/sdd      //vg1卷组名字,将/dev/vde扩展到vg1中
    3.vgs                                //查看vg扩展信息
     VG     #PV #LV #SN Attr   VSize   VFree 
      centos   1   2   0 wz--n- <29.00g  4.00m
      vg1      2   2   0 wz--n-   1.99g <1.76g
    
    5.2 减小VG      //企业中坚决先备份在使用,一般不建议使用
    [root@lxw4 ~]# pvs
      PV         VG     Fmt  Attr PSize    PFree   
      /dev/sda2  centos lvm2 a--   <29.00g    4.00m
      /dev/sdb   vg1    lvm2 a--  1020.00m  780.00m
      /dev/sdc   vg1    lvm2 a--  1020.00m 1020.00m
    [root@lxw4 ~]# vgs
      VG     #PV #LV #SN Attr   VSize   VFree 
      centos   1   2   0 wz--n- <29.00g  4.00m
      vg1      2   2   0 wz--n-   1.99g <1.76g
    [root@lxw4 ~]# vgreduce vg1 /dev/sdc
      Removed "/dev/sdc" from volume group "vg1"
    [root@lxw4 ~]# vgs
      VG     #PV #LV #SN Attr   VSize    VFree  
      centos   1   2   0 wz--n-  <29.00g   4.00m
      vg1      1   2   0 wz--n- 1020.00m 780.00m
    [root@lxw4 ~]# pvs
      PV         VG     Fmt  Attr PSize    PFree  
      /dev/sda2  centos lvm2 a--   <29.00g   4.00m
      /dev/sdb   vg1    lvm2 a--  1020.00m 780.00m
      /dev/sdc          lvm2 ---     1.00g   1.00g
    
    5.3.pvmove数据到其它PV
    首先要保证有备用pv(要属于一个vg)
    可以先在/dev/vdd创建出一个逻辑卷之后,进行测试
    [root@lxw4 ~]# pvs               //查看pvs
      PV         VG     Fmt  Attr PSize    PFree   
      /dev/sdc5  vg3    lvm2 a--  1020.00m  940.00m
      /dev/sdc6  vg3    lvm2 a--  1020.00m 1020.00m
    [root@lxw2 ~]# pvmove /dev/sd5 /dev/sdc6       //将sdc5 数据迁移至sdc6
      /dev/sdc5: Moved: 25.00%
      /dev/sdc5: Moved: 100.00%
    [root@lxw2 ~]# lsblk             //查看 磁盘信息
     ├─sdc5            8:37   0    1G  0 part  
     ├─sdc6            8:38   0    1G  0 part  
     │ └─vg3-lv3     253:4    0   80M  0 lvm   
     └─sdc7            8:39   0    2G  0 part  
     
    
    5.4LV扩容
    [root@lxw2 ~]# vgs               //查看vgs信息
      VG     #PV #LV #SN Attr   VSize    VFree  
      centos   1   2   0 wz--n-  <19.00g      0 
      vg3      2   1   0 wz--n-    1.99g   1.91g
      vg4      1   0   0 wz--n-   <2.00g  <2.00g
    [root@lxw2 ~]# lvextend -L 800M /dev/vg3/lv3      //扩展到800M
      Size of logical volume vg3/lv3 changed from 80.00 MiB (20 extents) to 800.00 MiB (200 extents).
      Logical volume vg3/lv3 successfully resized.
    [root@lxw2 ~]# lvs
      LV   VG     Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
      root centos -wi-ao---- <17.00g                                                    
      swap centos -wi-ao----   2.00g                                                                                                
      lv3  vg3    -wi-a----- 800.00m        
    [root@lxw2 ~]# lvextend -L +800M /dev/vg3/lv3     //在原有基础上加800M
      Size of logical volume vg3/lv3 changed from 800.00 MiB (200                  extents) to 1.56 GiB (400 extents).
      Logical volume vg3/lv3 successfully resized.
    [root@lxw2 ~]# lvs           //查看lv信息
      LV   VG     Attr       LSize   Pool Origin Data%  Meta%  Move Log Cpy%Sync Convert
      root centos -wi-ao---- <17.00g                                                    
      swap centos -wi-ao----   2.00g                                                                                                  
      lv3  vg3    -wi-a-----   1.56g                                                    
    
    
    

    =====================================================================

    四.交换分区

    交换分区管理 Swap
    作用: ‘提升‘ 内存的容量,防止OOM(Out Of Memory)

    实战:

    1.查看当前的交换分区
    [root@lxw2 ~]# free -m         //查看内存信息
                  total        used        free      shared  buff/cache   available
    Mem:           1819         210         986           9         623        1388
    Swap:          2047           0        2047
    
    [root@lxw2 ~]# swapon -s                //查看挂载信息
    文件名                          类型            大小    已用    权限
    /dev/dm-1                               partition       2097148 0       -2
    
    
    2.增加交换分区 可以是基本分区,LVM,File
    [root@lxw2 ~]# fdisk /dev/sdb    (t转换分区的ID 82)
    [root@lxw2 ~]# partprobe /dev/sdb   通知系统分区表的变化
    [root@lxw2 ~]# ll /dev/sdb*        //查看
    
    [root@lxw2 ~]# mkswap /dev/sdb1        //初始化
    [root@lxw2 ~]# blkid /dev/sdb1         //查找sdb1 UUID
    [root@lxw2 ~]# vim /etc/fstab           //进入永久挂载配置文件
    UUID="ea5b1c77-e540-463c-9644-0d75450f8b4c" swap    swap default 0 0
    [root@lxw2 ~]# swapon -a	(读取/etc/fstab)
    [root@lxw2 ~]# swapon -s
    [root@lxw2 ~]#  df -Th         //查看挂载信息
    
    
    
    
    
    
    展开全文
  • linux储存管理

    2020-11-01 19:02:45
    linux系统使用的是地址空间的概念管理内存数据。如果把物理地址暴露给进程会带来几个问题: 1.非法程序可能会破坏操作系统。 2.很难实现并发。 所以引入了地址空间的概念:地址空间是一个进程可用于寻址内存的一套...

    linux系统使用的是地址空间的概念来管理内存数据。如果把物理地址暴露给进程会带来几个问题:
    1.非法程序可能会破坏操作系统。
    2.很难实现并发。
    所以引入了地址空间的概念:地址空间是一个进程可用于寻址内存的一套地址集合。
    简单来说,地址空间为进程创造了一种抽象的内存。每个进程都有自己的地址空间,并且这个地址空间独立于其他进程的寻址空间。
    要保证多个应用程序同时处于内存中并且互相不影响,需要解决两个问题:保护和重定位。

    解决内存超载

    有两种处理内存超载的方法:
    1.最简单的测略就是交换技术:一个进程先在内存中运行,等到空闲的时候运行在磁盘中,则休眠的时候就不会占用内存。在交换的时候,把空闲进程从磁盘交换到内存的时候,在内存上的位置会和交换到磁盘前的内存位置不同。所以要对地址进行重定位。为了避免进程在运行的时候因为内存增长而导致内存不够的情况,我们在申请内存的时候都会额外分配一些额外的内存来预留给内存。

    2.虚拟内存: 每个程序都拥有自己的地址空间,这个空间被分割成许多块,每块都被称作一页。每一页是连续的地址范围。这些页被映射到物理内存。当程序引用到一部分在物理内存中地址空间时,通过硬件执行必要的映射。当程序应用到一部分不在物理内存的地址空间的时候,通过操作系统负责将缺失的部分装入物理内存并重新执行失败的指令。
    虚拟内存技术解决了程序大小比物理内存大小还大的问题,节省了计算机的资源。在这里插入图片描述
    虚拟内存主要提供了三个能力:
    1.把主存看成是一个储存在磁盘上的地址空间的高速缓存,在主存中只保存活动活动于,并根据需要在磁盘和主存之间来回传送数据,是得能够运行比内存大得多的程序。
    2.为进程提供了一致的地址空间,简化了存储器管理。
    3.保护每个进程的地址空间不被其他进程破坏。

    虚拟地址空间是由若干个页面组成。操作系统会给每一个进程维护一个页表,页表中存储的是进程的页到内存的页帧的映射。在这里插入图片描述
    在不同的进程中,如果两个变量的逻辑地址相同,但是由于每个进程的页表不同,所以映射后的结果也不同。所以物理地址完全不同。

    加速分页过程

    对大而快速的页映射的需求成为了构建计算机的重要约束。所以有如下两种方法加速映射:
    1.转换检测缓冲区(TLB):是一种硬件设备。
    2.软件TLB管理;

    针对大内存的页表

    1.多级页表:避免把全部页表一直保存在内存中。一级页表中包好二级页表。
    2.倒排页表:每一个页框有一个表项,而不是每一个虚拟页面有一个表项。

    展开全文
  • C语言提供了多种储存类别供我们使用,并且对应的有对应的内存管理策略,在了解C中的储存类型前,我们先了解一下与储存类型相关的一些概念。 1. 基础概念 对象:不同于面向对象编程中的对象的含义,C语言是面向过程...

    C语言中储存类别和内存管理

    储存类别

    C语言提供了多种储存类别供我们使用,并且对应的有对应的内存管理策略,在了解C中的储存类型前,我们先了解一下与储存类型相关的一些概念。

    1. 基础概念

    对象:不同于面向对象编程中的对象的含义,C语言是面向过程编程,不存在这样对象的概念,这个对象指的是值储存所占据物理内存空间。

    左值:左值是可以指定对象的表达式,它的最简单形式即为标识符,复杂的可以为为指针之类。一个表达式成为左值的前提是它确实指定了一块作为对象的储存空间,例如:

    int a = 1;//a作为标识符,也作基础表达式,指定了一个对象,是左值
    int *pa = &a;//pa同a也指示了一个储存地址对象,是一个左值;*pa是一个表示式,指示了a相同的对象也是一个左值
    int arr[5] = {0};
    arr+a*3;// 这段表达式就不是一个标识符,也不是一个左值了,因为它没有指定内存上的任意位置
    *(arr + a * 3);// 不同于上面的,这也是一个左值,因为它确实指定了内存上的位置
    

    ​ 左值分为可修改左值和不可修改左值。

    我们通常用储存期来描述对象,表明对象在内存中留存的时间。用标识符指定对象时,使用作用域链接来描述标识符,其中作用域表明标识符可以可以被程序使用的范围,链接表明程序的哪些其他文件也可以使用它。

    不同的储存类别之间的区别即在于它们的储存期作用域连接形式的不相同。我们来分别了解他们一下。

    储存期:储存期分为静态储存期,自动储存期,线程储存期和动态分配储存期(线程储存期暂时不多赘述),它们分别对应不同的在内存中的储存位置,也有不同的特点。

    静态储存期:对应静态存储位置,它在程序开始运行时就被分配,这段空间不可增加和减少,所以从程序开始运行到停止运行,静态储存期的数据一直存在。通常在函数外的变量和static表示的变量具有静态储存期。

    自动储存期:对应栈空间,它随着程序的运行可以自动进行分配,增加或减少。程序进入到一个块为其中的变量分配栈空间,退出一个块后则会释放相应的空间。一般的创建的变量都具有自动储存期。

    动态分配储存期:对应堆空间,它需要通过特殊的语法进行申请,申请后也需要主动进行销毁,存在时间为从申请内存开始到主动释放内存为止。需要通过专门的语句来获得具有动态分配储存期的变量。

    作用域:一个变量能被使用的范围称为作用域,作用域分为 块作用域函数作用域函数原型作用域文件作用域

    块作用域:由一个花括号开始到与之对应的花括号为止,其中的变量都具有块作用域,一般情况下任何在块内的定义的变量可以在块内任何位置使用,但是不可以在块外进行使用。(特例后面会举出),而且对于内部块也可以定义与外部块同名的变量,这时候内部块将隐去向内隐去外部块的同名变量,在内部使用自己定义的该变量。

    函数作用域:针对的是goto语句标签,一个标签首次出现在含糊内层,它的作用域将会延伸至整个函数,这表示我们不能使用同名的标签。

    函数原型作用域:对于函数的声明,该作用域开始与形参定义处知道函数函数原型结束。编译器只注重形式参数的类型而不会注意具体的变量名,甚至可以不使用变量名。

    文件作用域:声明在函数外的变量具有文件作用域,他们可以在同一源文件下的任何块和函数中使用,具有文件作用域的变量也被称为全局变量。

    对于分别属于同类型作用域但是不同一个作用域的变量它们可以任意重名,例如不同块的函数中变量属于不同块他们可以重名。对于具有文件作用域的变量它们对于所属的文件块都有作用,所以不建议块中变量与全局变量重名,但是在重名后块使用对应名称变量时将以块中自身定义的变量为准。

    #include <stdio.h>
    
    void showA(int a, int type) {
    switch (type) {
      case 1:
          printf("outer : ");
          break;
      case 2:
          printf("inter : ");
          break;
      case 3:
          printf("circle : ");
      default:
          ;
    }
    printf("a = %d\n", a);
    }
    
    int main (void) {
    int a = 1;
    showA(a, 1);
    {
      int a = 2;
      showA(a, 2);
    }
    showA(a, 1);
    while (a++ < 5) {
      int a = 5;
      showA(a, 3);
    }
    showA(a, 1);
    return 0;
    }
    
    
    /**
    outer : a = 1
    inter : a = 2
    outer : a = 1
    circle : a = 5
    circle : a = 5
    circle : a = 5
    circle : a = 5
    outer : a = 6
     * **/
    

    我们发现在在外部a为在外部定义的值,a输出为1;第一块内部,a读取的是内部的a的值,这一点没有任何问题;然后我们到外部,我们再让程序输出a值,仍然为2,没有问题;但是进入循环后,我们发现很奇怪的现象,通过输出我们发现循环执行了4次,很明显这是基于外部的a,但是内部的a在输出时却总是显示内部的a,这一点是因为:内部循环定义的a作用域只在块内,并不会作用于循环条件判断的部分,所以在进行循环条件判断时始终使用外部的a。注意递增条件一定要在循环判断条件中,否则循环将变成死循环。但是,没有必要使用同名变量。

    链接:链接是程序中变量可以被其他文件使用的描述,有三种类型的链接:外部链接内部链接无链接

    如果一个变量具有文件作用域它才可能具有外部链接和内部链接,其他变量都是无链接的。在具体了解内部链接和外部链接之前,我们先理解下 翻译单元的概念。

    翻译单元:我们经常使用#include指令来包含头文件,C通过预处理将对应头文件内容直接替换掉该条命令,他们虽然表面上看起来不是一个文件但是被编译器看做了一个文件,这个文件就被称为一个翻译单元,一个具有文件作用域的变量它的实际可见范围就是整个翻译单元。一个翻译单元由一个源文件和多个它所包含的文件组成。

    *所以外部链接可以在多文件程序中使用,而内部链接只可以在一个翻译单元使用。*区别二者在于是否使用了储存类别说明符static,使用了static则为内部链接,反之则为外部链接。

    //main.c 文件
    #include <stdio.h>
    
    int main (void) {
     extern int a;// 声明,让编译器在别处查找a的定义
    //    extern int b;
    //    printf("b = %d", b);这一段不可使用,因为b只具有内部链接,不可在其他源文件访问,运行
    //    报错
     printf("a = %d", a);
     return 0;
    }
    
    /**
     a = 5
     * **/
    
    // 和它一同编译的another.c文件
    int a = 5;// 具有外部链接,可以在多个源文件之间进行共享
    static int b = 2;// 具有内部链接,只能在一个源文件内共享
    

    在这里我们使用了外部链接变量a,在两个翻译单元之间实现了变量的传递。其中main.c文件为了调用变量a必须有extern声明语句,这段语句声明了一个int型变量a但是并不会为它分配内存,使用它只是为了告诉编译器在别处寻找变量a的定义,这是必不可少的,否则程序将会报错。

    // main.c文件
    #include <stdio.h>
    #include "main.h"
    
    int main (void) {
        extern int a;
        printf("a = %d", a);
        return 0;
    }
    
    /**
        a = 7
     * **/
    
    // main.h文件
    static int a = 7;
    

    不同于源文件,对于头文件,通过#include指令包含头文件,编译器将自动将对应文件内容替代到对应位置,它们属于同一个翻译单元,所以及时具有内部链接的变量仍可以使用。

    2. 储存类别分类

    介绍了一些基础概念后我们来根据这些基础概念对于储存类别进行分类:

    储存类别 储存期 作用域 链接 声明方式
    自动 自动 块内声明
    寄存器 自动 块内声明,加入关键字register
    静态外部链接 静态 文件 外部 函数外
    静态内部链接 静态 文件 内部 函数外,加入关键字static
    静态无链接 静态 块内声明,计入关键字static

    下面我呢来分别具体对于每种类型所对应的变量进行说明。

    3. 自动变量

    自动变量具有自动储存期,块作用域,无链接,在块内进行声明即可。自动储存期意味着它在开始执行块时被创建,在对应块到结尾时被销毁,不能再被通过任何途径访问;块作用域表明只能在块中使用变量名对于变量进行访问,但是在处于变量可使用的储存期内(这点必要,因为我们无法控制编译器的回收机制),我们也可以通过指针传递地址的方式来继续使用;无链接表明不能再其他文件中对于该变量进行访问。

    对于自动变量,默认情况下声明的变量都具有这样的储存类别,但是有时候为了更明显的表现意图,并且在外部具有同名变量时,为了更好覆盖它,表明自己变量的自动储存类型,可以使用关键字auto,例如:

    #include <stdio.h>
    
    int a = 1;
    
    int main (void) {
     auto int a;// int a;也是等价
     printf("a = %d", a);
     return 0;
    }
    

    在外部有同名变量时,使用auto关键字还是用来标识a作为块内的自动变量,覆盖外部的a,即使不加auto也是可以的,但是使用后可以起到更好的标识性。

    4. 寄存器变量

    寄存器变量在多个方面与自动变量相同,不同在于自动变量通常储存在计算机内存中,而寄存器变量储存在计算机CPU的寄存器中,因此它具有高效的运算率,而且因为它在寄存器中所以无法获得其地址。通过在变量定义中使用register修饰既可以声明寄存器变量:register int a;

    但是,值得注意的是,使用register企图创建寄存器变量是一种请求而不是命令,编译器很可能不会通过你的请求,而且寄存器也有可能没有足够大空间储存double类型变量,所以可以声明register的数据类型也是有限的。即使失败,也能够创建相应的自动变量,但是我们仍然不能获得其地址。

    5. 具有块作用域的静态变量

    具有块作用域的静态变量,对应的储存类别为静态无链接,其具有静态储存期,块作用域和无链接。它在程序开始运行时被创建,程序结束后被销毁。只在它被定义的块内调用,无法被其他文件访问。

    相较于自动变量,它只是拥有了静态储存期,所以我们使用static类别修饰符获得该类型变量static int a;。值得注意的是,由于该变量具有静态储存期,所以它始终储存在系统中的某一段内存空间中,我们可以利用指针在块外的区域对于该变量进行访问。

    #include <stdio.h>
    
    int* fun();
    
    int main (void) {
     int *p = fun();
     *p += 2;
     fun();
     return 0;
    }
    
    int *fun() {
     static int a = 1;
     printf("a = %d\n", a);
     return &a;
    }
    
    /**
     a = 1
     a = 3
     * **/
    

    通过上面的运行结果我们发现通过函数返回指向静态变量的指针,我们可以对静态变量进行访问和修改,这使得我们在块外对块内无链接的静态变量进行访问。

    6. 内部链接的静态变量

    内部链接的静态变量对应储存类别为静态内部链接。它具有静态作用期,文件作用域和内部链接。它在程序开始被创建,在同一个翻译单元内可以任意访问。在前面已经有它的用例。

    7. 外部链接的静态变量

    外部链接的静态变量对应储存类别为静态外部链接。它具有静态作用器,文件作用域和外部链接。大体上与内部链接的静态变量相同,但是它可以在多个翻译单元(多个源文件之间)进行共享。

    但是仍有一些事项注意:

    1. 声明时可以显示初始化,但是必须使用常量进行初始化(对于sizeof表达式也是常量),如果未进行初始化,无论如何它将被初始化为0。

      #include <stdio.h>
      
      int a;
      int b = 3;
      int c = 3 * sizeof b;
      // int d = 3 * a;非常量无法初始化
      char d;
      
      int main (void ) {
          printf("a = %d\n", a);
          printf("b = %d\n", b);
          printf("c = %d\n", c);
          printf("d = %d d = %c\n", d, d);
          return 0;
      }
      
      /**
          a = 0
          b = 3
          c = 12
          d = 0 d =
       * **/
      
    2. 如何跨文件使用具有外部链接的变量?正常情况下直接使用将会报错,我们需要通过引用性声明来使用,通过extern关键字来实现,在变量声明前加上关键字,编译器就会明白根据指示在其他源文件中查找变量的声明,这样的声明不会申请新的内存,也不可以进行赋值。

      // main.c
      #include <stdio.h>
      
      int main (void ) {
          // extern int a = 1;是不能赋值的
          extern int a;
          printf("a = %d\n", a);
          return 0;
      }
      
      /**
          a = 5
       * **/
      
      // anothor.c
      int a = 5;
      

    8. 储存类别说明符小结

    C中储存类别说明符有多个,并且不同说明符在不同位置也有不同意义。一共有一下说明符:autoexternregisterstatic_Thread_localtypedef。最后者被归为此类属于一些语法上的原因。它们大多都是单独使用,但是_Thread_local可以和staticextern一起使用。

    auto表明变量具有自动储存期,在块内的变量默认具有自动储存期,使用auto只是明确表示要使用与外部变量重名的局部变量的意图。

    register表明希望将变量储存在寄存器中,希望以最快的速度读取变量,同时不希望获得该变量的地址。

    static表明变量具有静态储存期,它并不改变块内变量的链接类型,但是对于快外的变量,将会限制它的链接类型为内部链接。

    extern表明该变量定义在别处,希望编译器在别处查找,包含extern的声明具有文件作用域,那么变量的定义一定有外部链接;如果只是具有块作用域,那么变量的定义可以有内部链接,也可以外部链接。

    9. 储存类别的选用

    到最后了,我们来考虑下储存类比的选用,一般情况下我们只建议使用自动储存类别,使用外部变量在程序间通信是方便的但同时也是危险的,所以我们希望尽力避免使用,同时我们要明白保护性程序设计的“按需知道”法则,尽量在函数内部解决该函数的任务,只共享哪些必须共享的变量。

    动态内存管理

    C语言除了自身建立了自动储存类型和静态储存类型来进行自主的内存管理来方便我们编程,同时也给我提供了一些工具是的我们能够进行灵活的内存使用和管理,我们通过了解使用C语言的内存分配来具体了解。

    1. 内存分配之malloc

    malloc函数声明在头文件stdlib.h中,其函数原型为

    void* malloc(size_t size);

    我们通过参数size(单位字节)来获得指定大小的一段空间同时返回指向该空间的空指针,我们可以通过强制类型转换来获得我们需要类型的指针,如果申请内存失败,它就会返回空指针NULL。我们通过具体的用例来了解它的使用:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main (void) {
        int *a = (int *)malloc(sizeof(int));// 创建一个int
        int *b = (int *)malloc(sizeof(int)*5);// 创建长度为5的数组
        *a = 4;
        for (int i = 0; i < 5; ++i)
            b[i] = i*i;
        printf("*a = %d\n", *a);
        for (int i = 0; i < 5; ++i)
            printf("b[%d] = %d\n", i, b[i]);
        free(a);
        free(b);
        return 0;
    }
    
    /**
        *a = 4
        b[0] = 0
        b[1] = 1
        b[2] = 4
        b[3] = 9
        b[4] = 16
     * **/
    

    我们发现可以通过内存申请可以灵活的创建变量和数组,然后对他们进行访问和修改,但是千万不要忘记调用free函数接受被分配空间的指针,来释放对应空间。不然大量的空间将无法被再利用造成内存的浪费,同时一些操作系统在程序运行结束后可能不会自动释放这些被分配的内存,甚至可能耗尽内存,产生可怕的 内存泄漏

    同时通过动态分配内存也有更加灵活的用途,例如创建变长数组:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main (void) {
        int len;
        scanf("input the len: %d", &len);
        int *arr = (int *)malloc(sizeof(int) * len);
        return 0;
    }
    

    通过这样一段程序我们就实现了,创建用户输入数字大小的整形数组。

    2. 内存分配值calloc

    calloc函数与malloc函数功能大体相同,它的函数原型:

    void *calloc(size_t num, size_t size);

    接受两个参数,第一个为希望分配的该大小的内存块数,第二个为希望一个空间大小(单位字节)。同样的我们要求在每次使用过后通过free函数将对应指针指向的分配的空间进行释放。

    储存类别和动态内存分配

    储存类别和内存分配有着密切可分的关系,我们来讲述一个理想中的模型:

    程序将它的内存分为三个部分,一部分给静态变量使用;一部分给自动变量使用,最后一部分提供给动态内存分配。为什么这样分配呢?

    静态变量使用的内存在程序编译时确定,在程序运行的整个周期都可以别访问,最后在程序结束时被销毁,所以我们可以单独使用一块区域对于其进行管理。

    自动变量在进入对应变量定义的块时被分配空间,在离开块后被销毁。伴随着函数的调用和结束,自动变量使用的内存数量也对应的增加和减少,这部分内存通常使用栈来管理,新建的变量将按顺序入栈,销毁时按照相反的方向进行销毁。

    使用动态分配内存的内容,他们创建于malloc或者calloc函数被调用的时候,在调用free函数被销毁,这些内存完全依赖于程序员自身的管理,我们可以在一个函数中创建它然后在另一个函数中销毁它。这样就使得这样的一部分内存被分配的支离破碎,有可能未分配的内存处于分配的内存之间,使用这样的内存往往是比使用栈来的更慢的。

    我们通过一个程序来更好了解变量处于的空间:

    #include <stdio.h>
    #include <stdlib.h>
    
    static int a = 1;
    static int b = 2;
    
    int main (void) {
        static int c = 3;
        int d = 4;
        int e = 5;
        int f = 6;
        int *p1 = (int *)malloc(sizeof(int));
        int *p2 = (int *)malloc(sizeof(int));
        int *p3 = (int *)malloc(sizeof(int));
        printf("static: %p\n", &a);
        printf("static: %p\n", &b);
        printf("static: %p\n", &c);
        printf("auto: %p\n", &d);
        printf("auto: %p\n", &e);
        printf("auto: %p\n", &f);
        printf("dynasty: %p\n", p1);
        printf("dynasty: %p\n", p2);
        printf("dynasty: %p\n", p3);
        return 0;
    }
    
    /**
        static: 00405004
        static: 00405008
        static: 0040500C
        auto: 0061FF10
        auto: 0061FF0C
        auto: 0061FF08
        dynasty: 00791930
        dynasty: 007918B8
        dynasty: 007918C8
     * **/
    

    可以发现不同类型的变量储存在不同地址附近。

    总结

    对于C中的变量我们可以通过类型和储存类别来描述,除此之外C新的标准也更新了一些特殊的修饰符const之类来修饰,灵活的使用他们能让程序运行的更有效率,实现更多的功能。

    展开全文
  • 3. 储存管理3.1 无储存器抽象早期计算机没有内存抽象,都采用物理地址,多道程序设计都采用多线程的方式。 也可以采用静态重定位的方式:为每个程序加上一个固定的常数。速度比较慢且容易出错3.2一种储存器抽象:...
  • 操作系统5——储存管理 ——2018.12.12 目标: 存储器的层次结构 连续分配方式 基本分页存储管理方式 基本分段存储管理方式 虚拟存储器的基本概念 页面置换算法 1、多级存储器结构:Cpu寄存器,高速缓存,主...
  • C语言提供了多种储存类别供我们使用,并且对应的有对应的内存管理策略,在了解C中的储存类型前,我们先了解一下与储存类型相关的一些概念。 1. 基础概念 对象:不同于面向对象编程中的对象的含义,C语言是面向过程...
  • 这里的概念非常多,那么我们来理一下这里的概念吧 知识点 首先分为两部分用户进程 和 内存 区域 内存: 将内存空间分为大小相等的块,每一块称之为页框(内存块),把每一块的编号称之为页框号(内存块号) 用户...
  • 小时候,对粮食的概念是母亲端在手里的一端香喷喷米饭,后来看影视剧《天下粮仓》,看到因自然灾害而引发的一场围绕粮食的惊心动魄...只不过,笔者今天想要讲述的,是通过信息化来储存管理粮食的方法与手段,这是...
  • 概念数据库· 数据库模型· 数据库储存结构中文维基百科未有数据库储存结构页面,可参考英语维基百科的对应页面Database storage structures。· 关系模型· 分布式数据库· ACID· NULL值关系数据库· 关系代数· ...
  • 第一章 项目时间管理的基本概念

    千次阅读 2015-11-10 00:16:46
    第一章 项目时间管理的基本概念 1.1 时间和时间guan管理概念 1.1.1 时间的概念 不能把时间、空间、物质三者分开解释 时,是对物质运动过程的描述; 间,是指认为的划分。 时间是 人的思维对物质运动过程的分割、...
  • 虚拟地址空间和虚拟内存是2个不同的概念:虚拟地址空间是一个地址的范围,比如0x00000000~0xFFFFFFFF(具有32位地址总线的cpu),就好比一个刚学数字的小孩,他只能认识0~~1023间的数字,A选了一个85,叫这个小孩去认...
  • 分页存储管理方式 页面的概念 内存划分成多个小单元,每个单元K大小,称(物理)块。作业也按K单位大小划分成片,称为页面。 ① 物理划分块的大小 = 逻辑划分的页的大小 ②页面大小要适中。 太大,(最后一页)内...
  • 由此产生了段的概念。通用的解决方案是在机器上提供多个互相独立的称为段(segment)的地址空间。每个段由一个从0到最大的线性地址序列构成。各个段的长度可以是0-某个运行的最大值之间的任何值。不同的段长度一般都...
  • 摘要 其实安卓文件的操作和Java在pc环境下的操作并无二致,之所以需要单独讲解是因为安卓系统提供了不同于pc的访问文件系统根路径的api,同时对一个应用的私有文件做了统一的管理。根据我的经验,初学者在这部分感到...
  • 知识管理——概念和案例(摘录)

    千次阅读 2008-02-09 19:15:00
    知识管理是对企业知识的创造、获取、加工、储存、传播和应用的管理,同时还包括对与知识有关的各种资源和无形资产的管理,涉及知识组织、知识设施、知识资产、知识活动、知识人员、知识交流和使用场所的全方位、全...
  • 数据、数据库、数据库管理系统、数据库系统的概念 1. 数据 数据是数据库中的基本对象。我们传统的理解为数据就是数字,但是从狭义的方面去看的话,数据的种类确是很多的,就如文本、图像、图形、音频、视频、货物的...
  • 解析在现代计算机系统中数据的概念是广义的。早期的计算机系统用于科学计算,处理的数据是正数、实数、浮点数等传统数学中的数据。 (2)数据库(DataBase,简称DB):数据库是长期储存在计算机内的、有组织的、可共享...
  • 数据 1.数据(Data)是数据库中存储的基本对象 ...数据库(Database,简称DB)是长期储存在计算机内、有组织的、可共享的大量数据的集合。 2.数据库的基本特征 (1)数据按一定的数据模型组织、描述和储存 (2)...
  • 第十章·云储存技术

    2019-12-01 13:18:56
    10.1储存概念 什么是云存储?它是一个远程平台,通过高度虚拟化的多租户基础设施为企业供应可扩展的存储资源,可根据组织的要求动态配置。传统管理容量的数据中心的IT部门会“解决问题”,不过需要不断增加物理存储...
  • 数据库基本概念

    2020-12-14 18:44:58
    基本概念 1.数据:描述事物的符号,是数据库储存的基本对象。 2.数据库:长期储存在计算机内,大量的*,有组织的*,可共享的数据集合。 3.数据库管理系统:用户和操作系统之间的数据管理软件。 4.数据库系统:由...
  • 虚拟内存的思路是当进程使用CPU时,并不立刻将所有进程使用的空间都调度入物理内存,而是挑选一些最可能使用的帧进入物理内存,其他帧保存在磁盘等外部储存环境中,如果进程需要使用位于外部储存
  • 数据库的基本概念

    2020-12-14 19:35:02
    1.试述数据、数据库、数据库管理系统、数据库系统的概念。 **数据(Data)**是数据库中存储的的基本对象,即数据库要存储的信息。 **数据库(DataBase,DB)**是长期储存在计算机内、有组织的、可共享的大量数据的...
  • MySQL基本概念

    2019-11-26 17:33:35
    一、数据库的基本概念 1:数据库:管理数据的工具 针对mySQL 数据库由表(tables) 记录(records. 行)字段(属性、列)组成 2.库:文件夹 把数据存储进数据库=》数据储存进某个文件夹 3.表:类比文件 数据库的分类 关系型:...
  • 本课介绍 Cookie 和 Session 的概念以及这两者的区别。 Cookie,有时也用其复数形式Cookies,指某些网站为了 辨别用户身份、进行session跟踪而储存在用户本地终端 上的数据(通常经过加密)。Session是指一个终端...
  • 第五章虚拟储存

    2018-11-23 20:58:40
    1.虚拟储存器的基本概念 分析常规存储器管理不足的原因: 1)常规存储器管理方式的特征 一次性:作业在运行前一次性地全部装入内存 驻留性:作业装入内存后,便一直驻留在内存中,直至作业运行结束。 :一次性及...
  • 数据库相关概念

    2017-04-01 20:48:00
    第一节一、相关概念1. Data:数据,是数据库中存储的基本对象,是描述事物的符号记录。2. Database:数据库,是长期储存在计算机内、有组织的、可共享的大量数据的集合。3. DBMS:数据库管理系统,是位于用户与操作...
  • nfs文件的储存

    千次阅读 2017-12-12 17:46:55
    NFS概念 网络文件系统(NFS)是Unix系统和网络附加存储文件管理器常用的网络文件系统,允许多个客户端通过共享文件访问。它可用于提供对共享二进制目录的访问,也可用于允许用户在同一工作组中从不同客户端访问其...
  • 简单的说,数据库(Database)就是一种存放数据的仓库,只是这个厂库比较特别,这个厂库是按照一定的数据结构来组织储存的,我们可以通过数据库提供的多种方法来管理数据库里的数据.2.数据库的分类:数据库按照早期的数据...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 907
精华内容 362
关键字:

储存管理概念