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

📄 read.c

📁 Minix3.11的源码。[MINIX 3是一个为高可靠性应用而设计的自由且简洁的类UNIX系统。]
💻 C
📖 第 1 页 / 共 2 页
字号:
/* This file contains the heart of the mechanism used to read (and write) * files.  Read and write requests are split up into chunks that do not cross * block boundaries.  Each chunk is then processed in turn.  Reads on special * files are also detected and handled. * * The entry points into this file are *   do_read:	 perform the READ system call by calling read_write *   read_write: actually do the work of READ and WRITE *   read_map:	 given an inode and file position, look up its zone number *   rd_indir:	 read an entry in an indirect block  *   read_ahead: manage the block read ahead business */#include "fs.h"#include <fcntl.h>#include <minix/com.h>#include "buf.h"#include "file.h"#include "fproc.h"#include "inode.h"#include "param.h"#include "super.h"FORWARD _PROTOTYPE( int rw_chunk, (struct inode *rip, off_t position,	unsigned off, int chunk, unsigned left, int rw_flag,	char *buff, int seg, int usr, int block_size, int *completed));/*===========================================================================* *				do_read					     * *===========================================================================*/PUBLIC int do_read(){  return(read_write(READING));}/*===========================================================================* *				read_write				     * *===========================================================================*/PUBLIC int read_write(rw_flag)int rw_flag;			/* READING or WRITING */{/* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */  register struct inode *rip;  register struct filp *f;  off_t bytes_left, f_size, position;  unsigned int off, cum_io;  int op, oflags, r, chunk, usr, seg, block_spec, char_spec;  int regular, partial_pipe = 0, partial_cnt = 0;  mode_t mode_word;  struct filp *wf;  int block_size;  int completed, r2 = OK;  phys_bytes p;  /* left unfinished rw_chunk()s from previous call! this can't happen.   * it means something has gone wrong we can't repair now.   */  if (bufs_in_use < 0) {  	panic(__FILE__,"start - bufs_in_use negative", bufs_in_use);  }  /* MM loads segments by putting funny things in upper 10 bits of 'fd'. */  if (who == PM_PROC_NR && (m_in.fd & (~BYTE)) ) {	usr = m_in.fd >> 7;	seg = (m_in.fd >> 5) & 03;	m_in.fd &= 037;		/* get rid of user and segment bits */  } else {	usr = who;		/* normal case */	seg = D;  }  /* If the file descriptor is valid, get the inode, size and mode. */  if (m_in.nbytes < 0) return(EINVAL);  if ((f = get_filp(m_in.fd)) == NIL_FILP) return(err_code);  if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {	return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);  }  if (m_in.nbytes == 0)  	 return(0);	/* so char special files need not check for 0*/  /* check if user process has the memory it needs.   * if not, copying will fail later.   * do this after 0-check above because umap doesn't want to map 0 bytes.   */  if ((r = sys_umap(usr, seg, (vir_bytes) m_in.buffer, m_in.nbytes, &p)) != OK)	return r;  position = f->filp_pos;  oflags = f->filp_flags;  rip = f->filp_ino;  f_size = rip->i_size;  r = OK;  if (rip->i_pipe == I_PIPE) {	/* fp->fp_cum_io_partial is only nonzero when doing partial writes */	cum_io = fp->fp_cum_io_partial;   } else {	cum_io = 0;  }  op = (rw_flag == READING ? DEV_READ : DEV_WRITE);  mode_word = rip->i_mode & I_TYPE;  regular = mode_word == I_REGULAR || mode_word == I_NAMED_PIPE;  if ((char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0))) {  	if (rip->i_zone[0] == NO_DEV)  		panic(__FILE__,"read_write tries to read from "  			"character device NO_DEV", NO_NUM);  	block_size = get_block_size(rip->i_zone[0]);  }  if ((block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0))) {  	f_size = ULONG_MAX;  	if (rip->i_zone[0] == NO_DEV)  		panic(__FILE__,"read_write tries to read from "  		" block device NO_DEV", NO_NUM);  	block_size = get_block_size(rip->i_zone[0]);  }  if (!char_spec && !block_spec)  	block_size = rip->i_sp->s_block_size;  rdwt_err = OK;		/* set to EIO if disk error occurs */  /* Check for character special files. */  if (char_spec) {  	dev_t dev;	dev = (dev_t) rip->i_zone[0];	r = dev_io(op, dev, usr, m_in.buffer, position, m_in.nbytes, oflags);	if (r >= 0) {		cum_io = r;		position += r;		r = OK;	}  } else {	if (rw_flag == WRITING && block_spec == 0) {		/* Check in advance to see if file will grow too big. */		if (position > rip->i_sp->s_max_size - m_in.nbytes) 			return(EFBIG);		/* Check for O_APPEND flag. */		if (oflags & O_APPEND) position = f_size;		/* Clear the zone containing present EOF if hole about		 * to be created.  This is necessary because all unwritten		 * blocks prior to the EOF must read as zeros.		 */		if (position > f_size) clear_zone(rip, f_size, 0);	}	/* Pipes are a little different.  Check. */	if (rip->i_pipe == I_PIPE) {	       r = pipe_check(rip, rw_flag, oflags,	       		m_in.nbytes, position, &partial_cnt, 0);	       if (r <= 0) return(r);	}	if (partial_cnt > 0) partial_pipe = 1;	/* Split the transfer into chunks that don't span two blocks. */	while (m_in.nbytes != 0) {		off = (unsigned int) (position % block_size);/* offset in blk*/		if (partial_pipe) {  /* pipes only */			chunk = MIN(partial_cnt, block_size - off);		} else			chunk = MIN(m_in.nbytes, block_size - off);		if (chunk < 0) chunk = block_size - off;		if (rw_flag == READING) {			bytes_left = f_size - position;			if (position >= f_size) break;	/* we are beyond EOF */			if (chunk > bytes_left) chunk = (int) bytes_left;		}		/* Read or write 'chunk' bytes. */		r = rw_chunk(rip, position, off, chunk, (unsigned) m_in.nbytes,			     rw_flag, m_in.buffer, seg, usr, block_size, &completed);		if (r != OK) break;	/* EOF reached */		if (rdwt_err < 0) break;		/* Update counters and pointers. */		m_in.buffer += chunk;	/* user buffer address */		m_in.nbytes -= chunk;	/* bytes yet to be read */		cum_io += chunk;	/* bytes read so far */		position += chunk;	/* position within the file */		if (partial_pipe) {			partial_cnt -= chunk;			if (partial_cnt <= 0)  break;		}	}  }  /* On write, update file size and access time. */  if (rw_flag == WRITING) {	if (regular || mode_word == I_DIRECTORY) {		if (position > f_size) rip->i_size = position;	}  } else {	if (rip->i_pipe == I_PIPE) {		if ( position >= rip->i_size) {			/* Reset pipe pointers. */			rip->i_size = 0;	/* no data left */			position = 0;		/* reset reader(s) */			wf = find_filp(rip, W_BIT);			if (wf != NIL_FILP) wf->filp_pos = 0;		}	}  }  f->filp_pos = position;  /* Check to see if read-ahead is called for, and if so, set it up. */  if (rw_flag == READING && rip->i_seek == NO_SEEK && position % block_size== 0		&& (regular || mode_word == I_DIRECTORY)) {	rdahed_inode = rip;	rdahedpos = position;  }  rip->i_seek = NO_SEEK;  if (rdwt_err != OK) r = rdwt_err;	/* check for disk error */  if (rdwt_err == END_OF_FILE) r = OK;  /* if user-space copying failed, read/write failed. */  if (r == OK && r2 != OK) {	r = r2;  }  if (r == OK) {	if (rw_flag == READING) rip->i_update |= ATIME;	if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;	rip->i_dirt = DIRTY;		/* inode is thus now dirty */	if (partial_pipe) {		partial_pipe = 0;			/* partial write on pipe with */		/* O_NONBLOCK, return write count */		if (!(oflags & O_NONBLOCK)) {			fp->fp_cum_io_partial = cum_io;			suspend(XPIPE);   /* partial write on pipe with */			return(SUSPEND);  /* nbyte > PIPE_SIZE - non-atomic */		}	}	fp->fp_cum_io_partial = 0;	return(cum_io);  }  if (bufs_in_use < 0) {  	panic(__FILE__,"end - bufs_in_use negative", bufs_in_use);  }  return(r);}/*===========================================================================* *				rw_chunk				     * *===========================================================================*/PRIVATE int rw_chunk(rip, position, off, chunk, left, rw_flag, buff, seg, usr, block_size, completed)register struct inode *rip;	/* pointer to inode for file to be rd/wr */off_t position;			/* position within file to read or write */unsigned off;			/* off within the current block */int chunk;			/* number of bytes to read or write */unsigned left;			/* max number of bytes wanted after position */int rw_flag;			/* READING or WRITING */char *buff;			/* virtual address of the user buffer */int seg;			/* T or D segment in user space */int usr;			/* which user process */int block_size;			/* block size of FS operating on */int *completed;			/* number of bytes copied */{/* Read or write (part of) a block. */  register struct buf *bp;  register int r = OK;  int n, block_spec;  block_t b;  dev_t dev;  *completed = 0;  block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;  if (block_spec) {	b = position/block_size;	dev = (dev_t) rip->i_zone[0];  } else {	b = read_map(rip, position);	dev = rip->i_dev;

⌨️ 快捷键说明

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