当前位置: 首页 > news >正文

Linux0.11内核源码解析-fcntl.c/iotcl.c/stat.c

fcntl

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

dup返回当前值最小的未用句柄,dup2返回指定新句柄的数值,句柄的复制操作主要用在文件的标准输入、输出重定向和管道方面。

dupfd

复制文件句柄,参数fd是要复制的文件句柄,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;//查找空闲的文件句柄while (arg < NR_OPEN)if (current->filp[arg])arg++;elsebreak;if (arg >= NR_OPEN)return -EMFILE;
//清除进程的 close_on_exec 位图中的特定位。close_on_exec 是一个位图,用于记录在执行 exec 系统调用时是否关闭相应的文件描述符。current->close_on_exec &= ~(1<<arg);(current->filp[arg] = current->filp[fd])->f_count++;return arg;
}

dup2和dup的实现

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

sys_fcntl 的函数

实现了 fcntl 系统调用的功能。fcntl 系统调用用于对打开文件描述符进行操作和控制,通过传递不同的命令(cmd)来实现不同的操作。

下面是该函数的作用和代码实现的解释:

  1. 首先,它检查给定的文件描述符(fd)是否有效,即必须小于已打开文件描述符的最大数目(NR_OPEN),并且与当前进程的文件描述符表中的相应条目(current->filp[fd])关联。

  2. 如果文件描述符无效,函数返回错误码 -EBADF(-9:无效的文件描述符)。

  3. 根据传递的命令(cmd)参数,执行不同的操作:

    • F_DUPFD:如果命令是 F_DUPFD,则调用 dupfd 函数来复制给定的文件描述符(fd)到最小的可用文件描述符号(arg)。
    • F_GETFD:如果命令是 F_GETFD,则返回当前进程的 close_on_exec 位图中对应文件描述符的状态(即该文件描述符在 exec 执行时是否会被关闭)。
    • F_SETFD:如果命令是 F_SETFD,则根据参数 arg 将当前进程的 close_on_exec 位图中对应文件描述符的状态进行设置,即设置或清除该文件描述符在 exec 执行时是否会被关闭的标志位。
    • F_GETFL:如果命令是 F_GETFL,则返回与给定文件描述符关联的文件状态标志。
    • F_SETFL:如果命令是 F_SETFL,则根据参数 arg 对给定文件描述符关联的文件状态标志进行设置,例如设置或清除非阻塞(O_NONBLOCK)和追加(O_APPEND)等标志位。
    • 其他命令(F_GETLKF_SETLKF_SETLKW):该函数返回 -1,表示不支持给定的命令。

int sys_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
{	struct file * filp;if (fd >= NR_OPEN || !(filp = current->filp[fd]))return -EBADF;switch (cmd) {case F_DUPFD:return dupfd(fd,arg);case F_GETFD:return (current->close_on_exec>>fd)&1;case F_SETFD:if (arg&1)current->close_on_exec |= (1<<fd);elsecurrent->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;}
}

ioctl

ioctl.c文件实现了输入、输出控制系统调用ioctl,主要调用tty_ioctl函数,对终端IO进行控制

extern int tty_ioctl(int dev, int cmd, int arg);typedef int (*ioctl_ptr)(int dev,int cmd,int arg);#define NRDEVS ((sizeof (ioctl_table))/(sizeof (ioctl_ptr)))static ioctl_ptr ioctl_table[]={NULL,		/* nodev */NULL,		/* /dev/mem */NULL,		/* /dev/fd */NULL,		/* /dev/hd */tty_ioctl,	/* /dev/ttyx */tty_ioctl,	/* /dev/tty */NULL,		/* /dev/lp */NULL};		/* named pipes */int sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
{	struct file * filp;int dev,mode;if (fd >= NR_OPEN || !(filp = current->filp[fd]))return -EBADF;//判断文件类型mode=filp->f_inode->i_mode;if (!S_ISCHR(mode) && !S_ISBLK(mode))return -EINVAL;//获取设备号dev = filp->f_inode->i_zone[0];if (MAJOR(dev) >= NRDEVS)return -ENODEV;if (!ioctl_table[MAJOR(dev)])return -ENOTTY;//对应ioctl_table函数指针表中没有对应函数,则返回出错码return ioctl_table[MAJOR(dev)](dev,cmd,arg);
}

stat

实现了取文件信息状态系统调用stat和fstat,并将信息存放用户的文件状态结果缓冲区中

cp_stat复制文件状态信息

static void cp_stat(struct m_inode * inode, struct stat * statbuf)
{struct stat tmp;int i;//验证存放数据的内存空间verify_area(statbuf,sizeof (* statbuf));tmp.st_dev = inode->i_dev;tmp.st_ino = inode->i_num;tmp.st_mode = inode->i_mode;tmp.st_nlink = inode->i_nlinks;tmp.st_uid = inode->i_uid;tmp.st_gid = inode->i_gid;tmp.st_rdev = inode->i_zone[0];tmp.st_size = inode->i_size;tmp.st_atime = inode->i_atime;tmp.st_mtime = inode->i_mtime;tmp.st_ctime = inode->i_ctime;//复制状态信息到用户缓冲区for (i=0 ; i<sizeof (tmp) ; i++)put_fs_byte(((char *) &tmp)[i],&((char *) statbuf)[i]);
}

sys_stat根据文件名获取文件状态信息

int sys_stat(char * filename, struct stat * statbuf)
{struct m_inode * inode;//根据文件名找出对应的i节点if (!(inode=namei(filename)))return -ENOENT;cp_stat(inode,statbuf);iput(inode);return 0;
}

sys_fstat根据文件描述符获取文件状态信息


int sys_fstat(unsigned int fd, struct stat * statbuf)
{struct file * f;struct m_inode * inode;if (fd >= NR_OPEN || !(f=current->filp[fd]) || !(inode=f->f_inode))return -EBADF;cp_stat(inode,statbuf);return 0;
}

http://www.lryc.cn/news/116834.html

相关文章:

  • OpenStack简介
  • 二分法的应用
  • ChatGPT在大规模数据处理和信息管理中的应用如何?
  • 【算法篇C++实现】五大常规算法
  • MySQL和钉钉单据接口对接
  • layui的基本使用-日期控件的业务场景使用入门实战案例一
  • 【2.1】Java微服务:详解Hystrix
  • Apache2.4源码安装与配置
  • Flume原理剖析
  • 【leetcode】202. 快乐数(easy)
  • 如何用瀑布图分析公司年报
  • Asynq: 基于Redis实现的Go生态分布式任务队列和异步处理库
  • 保证率计算公式 正态分布
  • docker容器监控:Cadvisor+InfluxDB+Grafana的安装部署
  • 论文讲解——TPU-MLIR: A Compiler For TPU Using MLIR
  • 基于最新导则下生态环评报告编制技术暨报告篇、制图篇、指数篇、综合应用篇系统性实践技能提升
  • NGZORRO:动态表单/模型驱动 的相关问题
  • 第十七次CCF计算机软件能力认证
  • ApplicationContext在Spring Boot中是如何创建的?
  • 后端开发7.轮播图模块【mongdb开发】
  • Linux常用命令(一):创建文件目录
  • 如何创建一个Vue组件?如何在父组件和子组件之间传递数据?如何在子组件中向父组件发送消息?
  • 设计模式之适配器模式
  • 让ChatGPT介绍一下ChatGPT(ChatGPT的自我介绍)
  • CentOS 7 构建 LVS-DR 群集
  • MySQL8.0.33二进制包安装与部署
  • RocketMQ发送消息失败:error CODE: 14 DESC: service not available now, maybe disk full
  • 1.Fay-UE5数字人工程导入(UE数字人系统教程)
  • Linux 终端操作命令(2)内部命令分类
  • 【数据结构与算法】十大经典排序算法-插入排序