⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 file_dev.c

📁 带中文注释的 linux 0.11 源代码0.11,很好的
💻 C
字号:
/** linux/fs/file_dev.c** (C) 1991 Linus Torvalds*/#include <errno.h>		// 错误号头文件。包含系统中各种出错号。(Linus 从minix 中引进的)#include <fcntl.h>		// 文件控制头文件。用于文件及其描述符的操作控制常数符号的定义。#include <linux/sched.h>	// 调度程序头文件,定义了任务结构task_struct、初始任务0 的数据,// 还有一些有关描述符参数设置和获取的嵌入式汇编函数宏语句。#include <linux/kernel.h>	// 内核头文件。含有一些内核常用函数的原形定义。#include <asm/segment.h>	// 段操作头文件。定义了有关段寄存器操作的嵌入式汇编函数。#define MIN(a,b) (((a)<(b))?(a):(b))	// 取a,b 中的最小值。#define MAX(a,b) (((a)>(b))?(a):(b))	// 取a,b 中的最大值。//// 文件读函数 - 根据i 节点和文件结构,读设备数据。// 由i 节点可以知道设备号,由filp 结构可以知道文件中当前读写指针位置。buf 指定用户态中// 缓冲区的位置,count 为需要读取的字节数。返回值是实际读取的字节数,或出错号(小于0)。intfile_read (struct m_inode *inode, struct file *filp, char *buf, int count){  int left, chars, nr;  struct buffer_head *bh;// 若需要读取的字节计数值小于等于零,则返回。  if ((left = count) <= 0)    return 0;// 若还需要读取的字节数不等于0,就循环执行以下操作,直到全部读出。  while (left)    {// 根据i 节点和文件表结构信息,取数据块文件当前读写位置在设备上对应的逻辑块号nr。若nr 不// 为0,则从i 节点指定的设备上读取该逻辑块,如果读操作失败则退出循环。若nr 为0,表示指定// 的数据块不存在,置缓冲块指针为NULL。      if (nr = bmap (inode, (filp->f_pos) / BLOCK_SIZE))	{	  if (!(bh = bread (inode->i_dev, nr)))	    break;	}      else	bh = NULL;// 计算文件读写指针在数据块中的偏移值nr,则该块中可读字节数为(BLOCK_SIZE-nr),然后与还需// 读取的字节数left 作比较,其中小值即为本次需读的字节数chars。若(BLOCK_SIZE-nr)大则说明// 该块是需要读取的最后一块数据,反之则还需要读取一块数据。      nr = filp->f_pos % BLOCK_SIZE;      chars = MIN (BLOCK_SIZE - nr, left);// 调整读写文件指针。指针前移此次将读取的字节数chars。剩余字节计数相应减去chars。      filp->f_pos += chars;      left -= chars;// 若从设备上读到了数据,则将p 指向读出数据块缓冲区中开始读取的位置,并且复制chars 字节// 到用户缓冲区buf 中。否则往用户缓冲区中填入chars 个0 值字节。      if (bh)	{	  char *p = nr + bh->b_data;	  while (chars-- > 0)	    put_fs_byte (*(p++), buf++);	  brelse (bh);	}      else	{	  while (chars-- > 0)	    put_fs_byte (0, buf++);	}    }// 修改该i 节点的访问时间为当前时间。返回读取的字节数,若读取字节数为0,则返回出错号。  inode->i_atime = CURRENT_TIME;  return (count - left) ? (count - left) : -ERROR;}//// 文件写函数 - 根据i 节点和文件结构信息,将用户数据写入指定设备。// 由i 节点可以知道设备号,由filp 结构可以知道文件中当前读写指针位置。buf 指定用户态中// 缓冲区的位置,count 为需要写入的字节数。返回值是实际写入的字节数,或出错号(小于0)。intfile_write (struct m_inode *inode, struct file *filp, char *buf, int count){  off_t pos;  int block, c;  struct buffer_head *bh;  char *p;  int i = 0;/** ok, append may not work when many processes are writing at the same time* but so what. That way leads to madness anyway.*//** ok,当许多进程同时写时,append 操作可能不行,但那又怎样。不管怎样那样做会* 导致混乱一团。*/// 如果是要向文件后添加数据,则将文件读写指针移到文件尾部。否则就将在文件读写指针处写入。  if (filp->f_flags & O_APPEND)    pos = inode->i_size;  else    pos = filp->f_pos;// 若已写入字节数i 小于需要写入的字节数count,则循环执行以下操作。  while (i < count)    {// 创建数据块号(pos/BLOCK_SIZE)在设备上对应的逻辑块,并返回在设备上的逻辑块号。如果逻辑// 块号=0,则表示创建失败,退出循环。      if (!(block = create_block (inode, pos / BLOCK_SIZE)))	break;// 根据该逻辑块号读取设备上的相应数据块,若出错则退出循环。      if (!(bh = bread (inode->i_dev, block)))	break;// 求出文件读写指针在数据块中的偏移值c,将p 指向读出数据块缓冲区中开始读取的位置。置该// 缓冲区已修改标志。      c = pos % BLOCK_SIZE;      p = c + bh->b_data;      bh->b_dirt = 1;// 从开始读写位置到块末共可写入c=(BLOCK_SIZE-c)个字节。若c 大于剩余还需写入的字节数// (count-i),则此次只需再写入c=(count-i)即可。      c = BLOCK_SIZE - c;      if (c > count - i)	c = count - i;// 文件读写指针前移此次需写入的字节数。如果当前文件读写指针位置值超过了文件的大小,则// 修改i 节点中文件大小字段,并置i 节点已修改标志。      pos += c;      if (pos > inode->i_size)	{	  inode->i_size = pos;	  inode->i_dirt = 1;	}// 已写入字节计数累加此次写入的字节数c。从用户缓冲区buf 中复制c 个字节到高速缓冲区中p// 指向开始的位置处。然后释放该缓冲区。      i += c;      while (c-- > 0)	*(p++) = get_fs_byte (buf++);      brelse (bh);    }// 更改文件修改时间为当前时间。  inode->i_mtime = CURRENT_TIME;// 如果此次操作不是在文件尾添加数据,则把文件读写指针调整到当前读写位置,并更改i 节点修改// 时间为当前时间。  if (!(filp->f_flags & O_APPEND))    {      filp->f_pos = pos;      inode->i_ctime = CURRENT_TIME;    }// 返回写入的字节数,若写入字节数为0,则返回出错号-1。  return (i ? i : -1);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -