It is of interest to work through an abbreviated summary of the code which is invoked when a user process performs a “read” system call before examining the code in detail.
.... read (f, b, n); /*user program/ {trap occurs} 2693 trap {system call #3} 5711 read (); 5713 rdwr (PREAD);
Execution of the system call by the user process results in the activation of “trap” running in kernel mode. “trap” recognises system call #3, and calls (via “trapl”) the routine “read”, which calls “rdwr”.
5731 rdwr 5736 fp = getf (u.u_ar0[R0]; 5743 u.u_base = u.u_arg[0]; 5744 u.u_count = u.u_arg[1]; 5745 u.u_segflg = 0; 5751 u.u_offset[1] = f2->f offset[1]; 5752 u.u_offset[0] = fp->f offset[0]; 5754 readi(fp->f inode); 5756 dpadd(fp->f offset, u.u_arg[1]-u.u_count);
“rdwr” includes much code which is common to both “read” and “write” operations. It converts, via “getf” (6619), the file identification supplied by the user process into the address of an entry in the “file” array.
Note that the first parameter of the system call is passed in a different way from the remaining two parameters.
“u.u_segflg” is set to zero to indicate that the operation destination is in the user address space. After “readi” is called with a parameter which is an “inode” pointer, the final accounting is performed by adding the number of characters requested for transfer less the residual number not transferred (left in “u.u_count”) to the file offset.
6221 readi 6239 lbn = lshift (u.u_offset, -9); 6240 on = u.u_offset[1] & 0777; 6241 n = min (512 - on, u.u_count); 6248 bn = bmap(ip, lbn); 6250 dn = ip->i_dev; 6258 bp = bread (dn, bn); 6260 iomove (bp, on, n, B READ); 6261 brelse (bp);
“readi” converts the file offset into two parts: a logical block number, “lbn”, and an index into the block, “on”. The number of characters to be transferred is the minimum of “u.u_count” and the number of characters left in the block (in which case additional block(s) must be read (not shown)) (and the number of characters remaining in the file (this case is not shown)).
“dn” is the device number which is stored within the “inode”. “bn” is the actual block number on the device (disk), which is computed by “bmap” (6415) using “lbn”.
The call on “bread” finds the required block, copying it into core from disk if necessary. “iomove” (6364) transfers the appropriate characters to their destination, and performs accounting chores.