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.17 - fcntl.c 程序

Created by : Mr Dk.

2019 / 09 / 21 22:42

Nanjing, Jiangsu, China


12.17 fcntl.c 程序

12.17.1 功能描述

实现了文件控制系统调用 fcntl() 和两个文件句柄 (描述符) 复制系统调用 dup() 和 dup2()。

  • dup2() 指定了新句柄的最小数值
  • dup() 指定了当前值最小的未用句柄
  • fcntl() 用于修改已打开的文件的状态或复制句柄

dup() 和 dup2() 返回的文件句柄与被复制句柄将 共用同一个文件表项。

12-35

对于使用 dup() 和 dup2() 函数新建的句柄,close_on_exec 标志会被清除。运行 exec() 类系统调用不会关闭 dup() 建立的文件句柄。

关于文件控制,有如下命令:

  • F_DUPFD - 复制文件句柄,等效于 dup()
  • F_GETFD / F_SETFD - 读取或设置文件句柄的 close_on_exec 标志
  • F_GETFL / F_SETFL - 读取或设置文件操作和访问标志
    • RDONLY
    • O_WRONLY
    • O_RDWR
    • O_APPEND
    • O_NONBLOCK
  • F_GETLK / F_SETLK / F_SETLKW - 读取或设置文件上锁标志 (Linux 0.12 暂未实现)

12.17.2 代码注释

dupfd() - 复制文件句柄 (描述符)

arg 指定了新文件句柄的最小值。

static int dupfd(unsigned int fd, unsigned int arg)
{
    if (fd >= NR_OPEN || !current->filp[fd])
        return -EBADF;
    if (arg >= NR_OPEN)
        return -EINVAL;
    
    // 寻找 ≥ arg 的空闲文件描述符
    while (arg < NR_OPEN)
        if (current->filp[arg])
            arg++;
        else
            break;
    
    if (arg >= NR_OPEN)
        return -EMFILE;
    
    current->close_on_exec &= ~(1 << arg); // 复位 close_on_exec 标志
    // 复制文件描述符 (文件描述符指向同一个文件表项)
    // 文件项引用次数加 1
    (current->filp[arg] = current->filp[fd])->f_count++;
    return arg; // 返回新的文件描述符
}

sys_dup2() - 复制文件句柄系统调用

复制指定的 oldfd,新文件句柄的值为 newfd。如果 newfd 已打开,则先关闭。

int sys_dup2(unsigned int oldfd, unsigned int newfd)
{
    sys_close(newfd);
    return dupfd(oldfd, newfd);
}

sys_dup() - 复制文件句柄系统调用

返回的新句柄是当前最小的未用句柄。

int sys_dup(unsigned int fildes)
{
    return dupfd(fildes, 0);
}

sys_fcntl() - 文件控制系统调用

int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{
    struct file * filp;
    
    // filp 指向文件描述符对应的文件表项
    if (fd >= NR_OPEN || !(filp = current->filp[fd]))
        // 文件句柄无效
        return -EBADF;
    
    switch(cmd) {
        case F_DUPFD: // 复制文件句柄
            return dupfd(fd, arg);
        case F_GETFD: // 取文件的 close_on_exec 标志
            return (current->close_on_exec >> fd) & 1;
        case F_SETFD: // 设置文件的 close_on_exec 标志
            if (arg & 1)
                // 置位
                current->close_on_exec |= (1 << fd);
            else
                // 复位
                current->close_on_exec &= ~(1 << fd);
            return 0;
        case F_GETFL: // 取文件状态标志和访问模式
            return filp->f_flags;
        case F_SETFL: // 设置文件状态和访问模式
            filp->f_flags &= ~(O_APPEND | O_NONBLOCK);
            filp->f_flags |= arg & (O_APPEND | O_NONBLOCK);
            return 0;
        case F_GETLK:
        case F_SETLK:
        case F_SETLKW:
            // 未实现
            return -1;
        default:
            return -1;
    }
}
Edit this page on GitHub
Prev
Chapter 12.16 - stat.c 程序
Next
Chapter 12.18 - ioctl.c 程序