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

📄 read.c

📁 一个简单的操作系统minix的核心代码
💻 C
📖 第 1 页 / 共 2 页
字号:
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
				src/fs/read.c	 	 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

23400	/* This file contains the heart of the mechanism used to read (and write)
23401	 * files.  Read and write requests are split up into chunks that do not cross
23402	 * block boundaries.  Each chunk is then processed in turn.  Reads on special
23403	 * files are also detected and handled.
23404	 *
23405	 * The entry points into this file are
23406	 *   do_read:    perform the READ system call by calling read_write
23407	 *   read_write: actually do the work of READ and WRITE
23408	 *   read_map:   given an inode and file position, look up its zone number
23409	 *   rd_indir:   read an entry in an indirect block 
23410	 *   read_ahead: manage the block read ahead business
23411	 */
23412	
23413	#include "fs.h"
23414	#include <fcntl.h>
23415	#include <minix/com.h>
23416	#include "buf.h"
23417	#include "file.h"
23418	#include "fproc.h"
23419	#include "inode.h"
23420	#include "param.h"
23421	#include "super.h"
23422	
23423	#define FD_MASK          077    /* max file descriptor is 63 */
23424	
23425	PRIVATE message umess;          /* message for asking SYSTASK for user copy */
23426	
23427	FORWARD _PROTOTYPE( int rw_chunk, (struct inode *rip, off_t position,
23428	                        unsigned off, int chunk, unsigned left, int rw_flag,
23429	                        char *buff, int seg, int usr)                   );
23430	
23431	/*===========================================================================*
23432	 *                              do_read                                      *
23433	 *===========================================================================*/
23434	PUBLIC int do_read()
23435	{
23436	  return(read_write(READING));
23437	}
	
	
23440	/*===========================================================================*
23441	 *                              read_write                                   *
23442	 *===========================================================================*/
23443	PUBLIC int read_write(rw_flag)
23444	int rw_flag;                    /* READING or WRITING */
23445	{
23446	/* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
23447	
23448	  register struct inode *rip;
23449	  register struct filp *f;
23450	  off_t bytes_left, f_size, position;
23451	  unsigned int off, cum_io;
23452	  int op, oflags, r, chunk, usr, seg, block_spec, char_spec;
23453	  int regular, partial_pipe = 0, partial_cnt = 0;
23454	  dev_t dev;
23455	  mode_t mode_word;
23456	  struct filp *wf;
23457	
23458	  /* MM loads segments by putting funny things in upper 10 bits of 'fd'. */
23459	  if (who == MM_PROC_NR && (fd & (~BYTE)) ) {
23460	        usr = (fd >> 8) & BYTE;
23461	        seg = (fd >> 6) & 03;
23462	        fd &= FD_MASK;          /* get rid of user and segment bits */
23463	  } else {
23464	        usr = who;              /* normal case */
23465	        seg = D;
23466	  }
23467	
23468	  /* If the file descriptor is valid, get the inode, size and mode. */
23469	  if (nbytes < 0) return(EINVAL);
23470	  if ((f = get_filp(fd)) == NIL_FILP) return(err_code);
23471	  if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
23472	        return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
23473	  }
23474	  if (nbytes == 0) return(0);   /* so char special files need not check for 0*/
23475	  position = f->filp_pos;
23476	  if (position > MAX_FILE_POS) return(EINVAL);
23477	  if (position + nbytes < position) return(EINVAL); /* unsigned overflow */
23478	  oflags = f->filp_flags;
23479	  rip = f->filp_ino;
23480	  f_size = rip->i_size;
23481	  r = OK;
23482	  if (rip->i_pipe == I_PIPE) {
23483	        /* fp->fp_cum_io_partial is only nonzero when doing partial writes */
23484	        cum_io = fp->fp_cum_io_partial; 
23485	  } else {
23486	        cum_io = 0;
23487	  }
23488	  op = (rw_flag == READING ? DEV_READ : DEV_WRITE);
23489	  mode_word = rip->i_mode & I_TYPE;
23490	  regular = mode_word == I_REGULAR || mode_word == I_NAMED_PIPE;
23491	
23492	  char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0);
23493	  block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0);
23494	  if (block_spec) f_size = LONG_MAX;
23495	  rdwt_err = OK;                /* set to EIO if disk error occurs */
23496	
23497	  /* Check for character special files. */
23498	  if (char_spec) {
23499	        dev = (dev_t) rip->i_zone[0];
23500	        r = dev_io(op, oflags & O_NONBLOCK, dev, position, nbytes, who,buffer);
23501	        if (r >= 0) {
23502	                cum_io = r;
23503	                position += r;
23504	                r = OK;
23505	        }
23506	  } else {
23507	        if (rw_flag == WRITING && block_spec == 0) {
23508	                /* Check in advance to see if file will grow too big. */
23509	                if (position > rip->i_sp->s_max_size - nbytes) return(EFBIG);
23510	
23511	                /* Check for O_APPEND flag. */
23512	                if (oflags & O_APPEND) position = f_size;
23513	
23514	                /* Clear the zone containing present EOF if hole about
23515	                 * to be created.  This is necessary because all unwritten
23516	                 * blocks prior to the EOF must read as zeros.
23517	                 */
23518	                if (position > f_size) clear_zone(rip, f_size, 0);
23519	        }
23520	
23521	        /* Pipes are a little different.  Check. */
23522	        if (rip->i_pipe == I_PIPE) {
23523	               r = pipe_check(rip,rw_flag,oflags,nbytes,position,&partial_cnt);
23524	               if (r <= 0) return(r);
23525	        }
23526	
23527	        if (partial_cnt > 0) partial_pipe = 1;
23528	
23529	        /* Split the transfer into chunks that don't span two blocks. */
23530	        while (nbytes != 0) {
23531	                off = (unsigned int) (position % BLOCK_SIZE);/* offset in blk*/
23532	                if (partial_pipe) {  /* pipes only */
23533	                        chunk = MIN(partial_cnt, BLOCK_SIZE - off);
23534	                } else
23535	                        chunk = MIN(nbytes, BLOCK_SIZE - off);
23536	                if (chunk < 0) chunk = BLOCK_SIZE - off;
23537	
23538	                if (rw_flag == READING) {
23539	                        bytes_left = f_size - position;
23540	                        if (position >= f_size) break;  /* we are beyond EOF */
23541	                        if (chunk > bytes_left) chunk = (int) bytes_left;
23542	                }
23543	
23544	                /* Read or write 'chunk' bytes. */
23545	                r = rw_chunk(rip, position, off, chunk, (unsigned) nbytes,
23546	                             rw_flag, buffer, seg, usr);
23547	                if (r != OK) break;     /* EOF reached */
23548	                if (rdwt_err < 0) break;
23549	
23550	                /* Update counters and pointers. */
23551	                buffer += chunk;        /* user buffer address */
23552	                nbytes -= chunk;        /* bytes yet to be read */
23553	                cum_io += chunk;        /* bytes read so far */
23554	                position += chunk;      /* position within the file */
23555	
23556	                if (partial_pipe) {
23557	                        partial_cnt -= chunk;
23558	                        if (partial_cnt <= 0)  break;
23559	                }
23560	        }
23561	  }
23562	
23563	  /* On write, update file size and access time. */
23564	  if (rw_flag == WRITING) {
23565	        if (regular || mode_word == I_DIRECTORY) {
23566	                if (position > f_size) rip->i_size = position;
23567	        }
23568	  } else {
23569	        if (rip->i_pipe == I_PIPE && position >= rip->i_size) {
23570	                /* Reset pipe pointers. */
23571	                rip->i_size = 0;        /* no data left */
23572	                position = 0;           /* reset reader(s) */
23573	                if ( (wf = find_filp(rip, W_BIT)) != NIL_FILP) wf->filp_pos =0;
23574	        }
23575	  }
23576	  f->filp_pos = position;
23577	
23578	  /* Check to see if read-ahead is called for, and if so, set it up. */
23579	  if (rw_flag == READING && rip->i_seek == NO_SEEK && position % BLOCK_SIZE== 0
23580	                && (regular || mode_word == I_DIRECTORY)) {
23581	        rdahed_inode = rip;
23582	        rdahedpos = position;
23583	  }
23584	  rip->i_seek = NO_SEEK;
23585	
23586	  if (rdwt_err != OK) r = rdwt_err;     /* check for disk error */
23587	  if (rdwt_err == END_OF_FILE) r = OK;
23588	  if (r == OK) {
23589	        if (rw_flag == READING) rip->i_update |= ATIME;
23590	        if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
23591	        rip->i_dirt = DIRTY;            /* inode is thus now dirty */
23592	        if (partial_pipe) {
23593	                partial_pipe = 0;
23594	                        /* partial write on pipe with */
23595	                        /* O_NONBLOCK, return write count */
23596	                if (!(oflags & O_NONBLOCK)) {
23597	                        fp->fp_cum_io_partial = cum_io;
23598	                        suspend(XPIPE); /* partial write on pipe with */
23599	                        return(0);      /* nbyte > PIPE_SIZE - non-atomic */
23600	                }
23601	        }
23602	        fp->fp_cum_io_partial = 0;
23603	        return(cum_io);
23604	  } else {
23605	        return(r);
23606	  }
23607	}
	
	
23610	/*===========================================================================*
23611	 *                              rw_chunk                                     *
23612	 *===========================================================================*/
23613	PRIVATE int rw_chunk(rip, position, off, chunk, left, rw_flag, buff, seg, usr)
23614	register struct inode *rip;     /* pointer to inode for file to be rd/wr */
23615	off_t position;                 /* position within file to read or write */
23616	unsigned off;                   /* off within the current block */
23617	int chunk;                      /* number of bytes to read or write */
23618	unsigned left;                  /* max number of bytes wanted after position */
23619	int rw_flag;                    /* READING or WRITING */
23620	char *buff;                     /* virtual address of the user buffer */
23621	int seg;                        /* T or D segment in user space */
23622	int usr;                        /* which user process */
23623	{
23624	/* Read or write (part of) a block. */
23625	
23626	  register struct buf *bp;
23627	  register int r;
23628	  int n, block_spec;
23629	  block_t b;
23630	  dev_t dev;
23631	
23632	  block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
23633	  if (block_spec) {
23634	        b = position/BLOCK_SIZE;
23635	        dev = (dev_t) rip->i_zone[0];
23636	  } else {
23637	        b = read_map(rip, position);
23638	        dev = rip->i_dev;
23639	  }
23640	
23641	  if (!block_spec && b == NO_BLOCK) {
23642	        if (rw_flag == READING) {
23643	                /* Reading from a nonexistent block.  Must read as all zeros.*/
23644	                bp = get_block(NO_DEV, NO_BLOCK, NORMAL);    /* get a buffer */
23645	                zero_block(bp);
23646	        } else {
23647	                /* Writing to a nonexistent block. Create and enter in inode.*/
23648	                if ((bp= new_block(rip, position)) == NIL_BUF)return(err_code);
23649	        }
23650	  } else if (rw_flag == READING) {
23651	        /* Read and read ahead if convenient. */
23652	        bp = rahead(rip, b, position, left);
23653	  } else {
23654	        /* Normally an existing block to be partially overwritten is first read
23655	         * in.  However, a full block need not be read in.  If it is already in

⌨️ 快捷键说明

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