Mr Dk.'s BlogMr Dk.'s Blog
  • 🦆 About Me
  • ⛏️ Technology Stack
  • 🔗 Links
  • 🗒️ About Blog
  • Algorithm
  • C++
  • Compiler
  • Cryptography
  • DevOps
  • Docker
  • Git
  • Java
  • Linux
  • MS Office
  • MySQL
  • Network
  • Operating System
  • Performance
  • PostgreSQL
  • Productivity
  • Solidity
  • Vue.js
  • Web
  • Wireless
  • 🐧 How Linux Works (notes)
  • 🐧 Linux Kernel Comments (notes)
  • 🐧 Linux Kernel Development (notes)
  • 🐤 μc/OS-II Source Code (notes)
  • ☕ Understanding the JVM (notes)
  • ⛸️ Redis Implementation (notes)
  • 🗜️ Understanding Nginx (notes)
  • ⚙️ Netty in Action (notes)
  • ☁️ Spring Microservices (notes)
  • ⚒️ The Annotated STL Sources (notes)
  • ☕ Java Development Kit 8
GitHub
  • 🦆 About Me
  • ⛏️ Technology Stack
  • 🔗 Links
  • 🗒️ About Blog
  • Algorithm
  • C++
  • Compiler
  • Cryptography
  • DevOps
  • Docker
  • Git
  • Java
  • Linux
  • MS Office
  • MySQL
  • Network
  • Operating System
  • Performance
  • PostgreSQL
  • Productivity
  • Solidity
  • Vue.js
  • Web
  • Wireless
  • 🐧 How Linux Works (notes)
  • 🐧 Linux Kernel Comments (notes)
  • 🐧 Linux Kernel Development (notes)
  • 🐤 μc/OS-II Source Code (notes)
  • ☕ Understanding the JVM (notes)
  • ⛸️ Redis Implementation (notes)
  • 🗜️ Understanding Nginx (notes)
  • ⚙️ Netty in Action (notes)
  • ☁️ Spring Microservices (notes)
  • ⚒️ The Annotated STL Sources (notes)
  • ☕ Java Development Kit 8
GitHub
  • 🐧 Linux Kernel Comments
    • Chapter 2 - 微型计算机组成结构

      • Chapter 2 - 微型计算机组成结构
    • Chapter 3 - 内核编程语言和环境

      • Chapter 3 - 内核编程语言和环境
    • Chapter 4 - 80X86 保护模式及其编程

      • Chapter 4.1-4.2 - 80X86 系统寄存器和系统指令 & 保护模式内存管理
      • Chapter 4.3 - 分段机制
      • Chapter 4.4 - 分页机制
      • Chapter 4.5 - 保护
      • Chapter 4.6 - 中断和异常处理
      • Chapter 4.7 - 任务管理
      • Chapter 4.8 - 保护模式编程初始化
      • Chapter 4.9 - 一个简单的多任务内核实例
    • Chapter 5 - Linux 内核体系结构

      • Chapter 5.1-5.2 - Linux 内核模式 & 体系结构
      • Chapter 5.3 - Linux 内核对内存的管理和使用
      • Chapter 5.4-5.6 - 中断机制 & 系统调用 & 系统时间和定时
      • Chapter 5.7-5.9 - Linux 进程控制 & 堆栈使用 & 文件系统
    • Chapter 6 - 引导启动程序 (boot)

      • Chapter 6 - 引导启动程序 (boot)
    • Chapter 7 - 初始化程序 (init)

      • Chapter 7 - 初始化程序 (init)
    • Chapter 8 - 内核代码

      • Chapter 8.1 - 内核代码总体功能
      • Chapter 8.2 - asm.s 程序
      • Chapter 8.3 - traps.c 程序
      • Chapter 8.4 - sys_call.s 程序
      • Chapter 8.5 - mktime.c 程序
      • Chapter 8.6 - sched.c 程序
      • Chapter 8.7 - signal.c 程序
      • Chapter 8.8 - exit.c 程序
      • Chapter 8.9 - fork.c 程序
      • Chapter 8.10 - sys.c 程序
    • Chapter 9 - 块设备驱动程序

      • Chapter 9.1 - 块设备驱动程序 总体功能
      • Chapter 9.2 - blk.h 文件
      • Chapter 9.3 - hd.c 程序
      • Chapter 9.4 - ll_rw_blk.c 程序
      • Chapter 9.5 - ramdisk.c 程序
    • Chapter 10 - 字符设备驱动程序

      • Chapter 10.1 - 字符设备驱动程序 总体功能
      • Chapter 10.2 - keyboard.S 程序
      • Chapter 10.3 - console.c 程序
      • Chapter 10.4 - serial.c 程序
      • Chapter 10.5 - rs_io.s 程序
      • Chapter 10.6 - tty_io.c 程序
      • Chapter 10.7 - tty_ioctl.c 程序
    • Chapter 12 - 文件系统

      • Chapter 12.1 - 文件系统 总体功能
      • Chapter 12.2 - buffer.c 程序
      • Chapter 12.3 - bitmap.c 程序
      • Chapter 12.4 - truncate.c 程序
      • Chapter 12.5 - inode.c 程序
      • Chapter 12.6 - super.c 程序
      • Chapter 12.7 - namei.c 程序
      • Chapter 12.9 - block_dev.c 程序
      • Chapter 12.10 - file_dev.c 程序
      • Chapter 12.11 - pipe.c 程序
      • Chapter 12.12 - char_dev.c 程序
      • Chapter 12.13 - read_write.c 程序
      • Chapter 12.14 - open.c 程序
      • Chapter 12.15 - exec.c 程序
      • Chapter 12.16 - stat.c 程序
      • Chapter 12.17 - fcntl.c 程序
      • Chapter 12.18 - ioctl.c 程序
      • Chapter 12.19 - select.c 程序

Chapter 12.4 - truncate.c 程序

Created by : Mr Dk.

2019 / 09 / 03 17:29

Nanjing, Jiangsu, China


12.4 truncate.c 程序

12.4.1 功能描述

释放指定 inode 在设备上占用的所有逻辑块:

  • 直接块
  • 一次间接块
  • 二次间接块

12-6

效果是将文件的长度截为 0,释放设备空间。

12.4.2 代码注释

free_ind() - 释放所有的一次间接块 (内部函数)

static int free_ind(int dev, int block)
{
    struct buffer_head * bh;
    unsigned short * p;
    int i;
    int block_busy; // 有逻辑块没有被释放的标志
    
    // 逻辑块号不能为 0
    if (!block)
        return 1;
    
    block_busy = 0;
    if (bh = bread(dev, block)) {
        // bh 指向一次间接块的缓冲块
        p = (unsigned short *) bh->b_data; // 指向缓冲块数据区
        for (i = 0; i < 512; i++, p++)
            if (*p)
                if (free_block(dev, *p)) {
                    // 释放编号为 *p 的 inode 对应的逻辑块
                    *p = 0;
                    bh->b_dirt = 1;
                } else
                    block_busy = 1; // 该逻辑块没有被释放
        brelse(bh); // 释放一次间接块占用的缓冲块
    }
    
    if (block_busy)
        return 0;
    else
        return free_block(dev, block); // 释放设备上的一次间接块
}

free_dind() - 释放所有的二次间接块 (内部函数)

static int free_dind(int dev, int block)
{
    struct buffer_head * bh;
    unsigned short * p;
    int i;
    int block_busy;
    
    // 逻辑块号不能为 0
    if (!block)
        return 1;
    block_busy = 0;
    if (bh = bread(dev, block)) {
        p = (unsigned short *) bh->b_data; // 二次间接块缓冲块数据区
        for (i = 0; i < 512; i++, p++)
            // 每一个一次间接块
            if (*p)
                if (free_ind(dev, *p)) {
                    *p = 0;
                    bh->b_dirt = 1;
                } else
                    block_busy = 1;
        brelse(bh); // 释放二次间接块占用的缓冲块
    }
    if (block_busy)
        return 0;
    else
        return free_block(dev, block); // 释放设备上的二次间接块
}

truncate() - 截断文件数据函数

void truncate(struct m_inode * inode)
{
    int i;
    int block_busy;
    
    // 判断 inode 的有效性
    // 必须是常规文件 | 目录文件 | 链接
    if (!(S_ISREG(inode->i_mode) ||
          S_ISDIR(inode->i_mode) ||
          S_ISLNK(inode->i_mode)))
        return;
repeat:
    block_busy = 0;
    for (i = 0; i < 7; i++)
        // 直接块
        // 逻辑块号不为 0
        if (inode->i_zone[i]) {
            if (free_block(inode->i_dev, inode->i_zone[i]))
                inode->i_zone[i] = 0;
            else
                block_busy = 1;
        }
    // 释放一次间接块
    if (free_ind(inode->i_dev, inode->i_zone[7]))
        inode->i_zone[7] = 0;
    else
        block_busy = 1;
    // 释放二次间接块
    if (free_dind(inode->i_dev, inode->i_zone[8]))
        inode->i_zone[8] = 0;
    else
        block_busy = 1;
    
    inode->i_dirt = 1; // inode 已被修改
    if (block_busy) {
        // 先切换到其它进程运行
        // 过会儿再重新执行释放操作
        current->counter = 0;
        schedule();
        goto repeat;
    }
    
    // 修改 inode 的大小和时间
    inode->i_size = 0;
    inode->i_mtime = inode->i_ctime = CURRENT_TIME;
}

Summary

收回逻辑块时,不仅要收回设备上的逻辑块,还需要收回内存高速缓冲区中,逻辑块的映像。

Edit this page on GitHub
Prev
Chapter 12.3 - bitmap.c 程序
Next
Chapter 12.5 - inode.c 程序