Operating Systems Design and Implementation Chapter 03 (version - - PDF document

operating systems
SMART_READER_LITE
LIVE PREVIEW

Operating Systems Design and Implementation Chapter 03 (version - - PDF document

Operating Systems Design and Implementation Chapter 03 (version January 30, 2008 ) Melanie Rieback Vrije Universiteit Amsterdam, Faculty of Sciences Dept. Computer Science Room R4.23. Tel: (020) 598 7874 E-mail: melanie@cs.vu.nl, URL:


slide-1
SLIDE 1

Operating Systems

Design and Implementation

Chapter 03

(version January 30, 2008)

Melanie Rieback

Vrije Universiteit Amsterdam, Faculty of Sciences

  • Dept. Computer Science

Room R4.23. Tel: (020) 598 7874 E-mail: melanie@cs.vu.nl, URL: www.cs.vu.nl/∼melanie/

01 Introduction 02 Processes 03 Input/Output 04 Memory Management 05 File Systems

00 – 1 /

Input/Output

  • Principles of I/O hardware
  • Principles of I/O software
  • Deadlocks
  • Lots of MINIX

03 – 1 Input/Output/

slide-2
SLIDE 2

Input/Output

Basic idea: I/O devices are attached to a computer and are available to programs by means of an inter-

  • face. It is the interface that we’re interested in here.

Note: Interfaces hide differences between similar de- vices (you don’t care whether you have an IDE or SATA hard disk).

  • Character devices: all I/O occurs as a sequen-

tial stream of bytes:

read( out data ); write( in data );

  • Block devices: all I/O occurs in units of randomly

accessible blocks of bytes:

read( in block_number out data ); write( in block_number, in data );

Note: Distinction is often blurred, e.g. is a tape a block device or not? Others don’t fit, e.g. clocks.

03 – 2 Input/Output/3.1 Principles I/O Hardware

Device Controllers (1/3)

Basic function: controllers sit between the mechan- ical hardware device and the rest of the computer: they offer an electronic interface in the form of reg- isters. By writing values into these registers the controller subsequently puts the device into action. Results of a device operation are returned in registers as well.

03 – 3 Input/Output/3.1 Principles I/O Hardware

slide-3
SLIDE 3

Device Controllers (2/3)

Question: how do we make that interface available to programs.

  • Memory-mapped I/O: the registers of the con-

troller are mapped (by the hardware) into addresses

  • f main memory.

mov 23, DATA ; copy data to register ; at address #23

  • I/O mapped I/O: all I/O registers are contained

in a separate address space that can only be ac- cessed through special I/O instructions:

mov dx, PORT ; Register address = port mov ax, VALUE ; Register value

  • ut

; Set the register.

03 – 4 Input/Output/3.1 Principles I/O Hardware

Device Controllers (3/3)

When I/O is finished, most controllers generate an in-

  • terrupt. Each controller has an associated interrupt

vector. The interrupt vector is an index in a table containing pointers to interrupt handlers. There is one interrupt handler per controller. An interrupt handler is a procedure that is to be exe- cuted when an interrupt occurs.

interrupt vector interrupt handler

03 – 5 Input/Output/3.1 Principles I/O Hardware

slide-4
SLIDE 4

Direct Memory Access

CPU DMA controller Disk controller Main memory Buffer

  • 1. CPU

programs the DMA controller Interrupt when done

  • 2. DMA requests

transfer to memory

  • 3. Data transferred

Bus

  • 4. Ack

Address Count Control Drive

The internal buffer at the I/O Controller is needed to smoothen the transfer of data between the (disk)device and main memory:

  • The controller catches the data on the device as a

constant bit stream, which are fed into the buffer.

  • The buffer is checked for errors (checksum). If
  • kay, then data is transferred to memory.

The transfer between controller and memory is de- pendent on the availability of the bus: we can’t wait for that once a data transfer has been issued — you need a buffer.

03 – 6 Input/Output/3.1 Principles I/O Hardware

Principles of I/O Software (1/2)

  • Device independence: The I/O software should

provide a level of abstraction that allows programs to make use of I/O facilities that are independent

  • f particular devices or even interfaces.
  • Naming: The identification/name of a device should

be supported in such a way that it is independent

  • f the device itself.
  • Error handling: Errors should be corrected (if

possible) nearest to their source ⇒ don’t just de- tect them and say something went wrong, but do something about it.

03 – 7 Input/Output/3.2 Principles I/O Software

slide-5
SLIDE 5

Principles of I/O Software (2/2)

  • Blocking vs. interrupts: We want a simple model.

A process that does I/O issues a request, waits for I/O to complete, and continues ⇒ synchronous data transfer. Lower levels have a simplistic model: start the de- vice; go ahead as if nothing happened; just catch the interrupt later on ⇒ asynchronous model. We’ll have to implement the synchronous one on top of the asynchronous model.

  • sharable vs. dedicated: The software has to make

the distinction between devices that can be shared (disks), and those that can not (printers). The user doesn’t care: as long as the transfer suc- ceeds as expected. Solution: structure I/O software into layers: (1) inter- rupts, (2) drivers, (3) device-independent I/O, (4) user space I/O.

03 – 8 Input/Output/3.2 Principles I/O Software

Interrupt Handlers

interrupt register

0 1 1 0 1 1 0 1 0 0 1 1 0 0 0 1 0 0 1 1 0 0 1 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 1 0 1 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 1 1 0 1 1 0 1 1 0 1 0 1 2 3 4 5 6 7 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 0 0 1 0 1 1 0 1 0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 0 1 0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 0 1 1 1 1 0 1 1 0 1

0 1 1 1 0 1 1 1 0 1 0 1 0 1 1 1 0 1 0 1

program counter

0 0 0 0 0 1 0 1

interrupt vector

Basics: the interrupt handler does what is strictly nec- essary to ensure that the next I/O operation can be executed:

  • Results of the last I/O operation are safely stored.
  • It unblocks the driver/task who was waiting for the

I/O operation to complete.

03 – 9 Input/Output/3.2 Principles I/O Software

slide-6
SLIDE 6

Device Drivers

process device admin. request pool

read/ write read/ write

interrupt handler

query/ update query/ update

request handler I/O controller device handler UPPER HALF LOWER HALF

Question: What’s the difference between the upper and lower half? Question: What’s in the device administration?

03 – 10 Input/Output/3.2 Principles I/O Software

Device-Independent I/O Software

Basic idea: The device-independent software pro- vides an interface to higher layers that completely hides all I/O specific aspects.

  • Device naming, e.g., by using major and minor

device numbers.

  • Protecting devices against access by unauthorized

processes/users.

  • Handling different block sizes for different devices.
  • Provide buffering mechanisms for data blocks (soft-

ware cache).

  • Manages block devices, e.g. by keeping track of

which blocks of a block device are still available.

  • Allocates/deallocates dedicated devices to users.
  • Takes care of proper error handling.

Question: To what extent is this software itself device independent?

03 – 11 Input/Output/3.2 Principles I/O Software

slide-7
SLIDE 7

User Space I/O

Idea: You can actually do better by providing your own view on what I/O looks like. These solutions are im- plemented completely on top of an operating system and are independent of any device. Example: The C standard I/O library:

extern FILE *fopen(const char *, const char *); extern int fclose(FILE *); extern int fflush(FILE *); extern int fprintf(FILE *, const char *, ...); extern int fscanf(FILE *, const char *, ...); extern int printf(const char *, ...); extern int scanf(const char *, ...); extern int sprintf(char *, const char *, ...); extern int fgetc(FILE *); extern char *fgets(char *, int, FILE *); extern int fputc(int, FILE *); extern int fputs(const char *, FILE *); extern int getc(FILE *); ...

Question: Is this actually operating system stuff?

03 – 12 Input/Output/3.2 Principles I/O Software

User Space I/O – Daemons

daemon lpr paper.ps lpr

  • rdinary

process OS

Idea: In order to properly manage some resource (e.g. a printer), only one special process is allowed to do actual I/O requests for that device. All other pro- cesses have their I/O requests propagated to the dae- mon. Note: This type of I/O can be structured completely independently of an operating system

03 – 13 Input/Output/3.2 Principles I/O Software

slide-8
SLIDE 8

I/O Layering

I/O request Layer I/O reply I/O functions Make I/O call; format I/O; spooling Naming, protection, blocking, buffering, allocation Set up device registers; check status Wake up driver when I/O completed Perform I/O operation User processes Device-independent software Device drivers Interrupt handlers Hardware

Note: We’ve just discussed this layering from bottom to top.

03 – 14 Input/Output/3.2 Principles I/O Software

Deadlock

Examples:

  • Four cars at a junction arrive at the same time. All

have right of way, and politely wait for the other to continue.

  • Five philosophers sit at a round table with one fork

between each plate. They all start to eat by lifting their left fork...

  • Process A opens file #1, and then attempts to
  • pen file #2 which is currently opened by process
  • B. Process B, meanwhile, waits until it can open

file #1. Definition: A set of processes are in deadlock if each process is waiting for an event to happen that only another process in that set can cause.

03 – 15 Input/Output/3.3 Deadlock

slide-9
SLIDE 9

Deadlock – Conditions

Model: processes (1) request, (2) use, and (3) re- lease a resource. Deadlock happens if and only if:

  • Mutual exclusion: Each resource is assigned to

at most one process.

  • Hold and wait: Processes can request a resource

while holding another.

  • No preemption: Resources cannot be taken away

from a process.

  • Circular wait: Two or more processes must be

waiting for release of a resource held by another.

assigned to requests process resource

Note: Deadlock iff there is a cycle ⇒ don’t honor a request if it leads to a cycle.

03 – 16 Input/Output/3.3 Deadlock

Avoiding Deadlock

(j) A

  • Request R

Request S Release R Release S B

  • Request S

Request T Release S Release T C

  • Request T

Request R Release T Release R

  • 1. A requests R
  • 2. B requests S
  • 3. C requests T
  • 4. A requests S
  • 5. B requests T
  • 6. C requests R

deadlock

  • 1. A requests R
  • 2. C requests T
  • 3. A requests S
  • 4. C requests R
  • 5. A releases R
  • 6. A releases S

no deadlock A R B S C T (i) A R B S C T (h) A R B S C T (g) A R B S C T (f) A R B S C T (e) (d) (c) (b) (a) A R B S C T (q) A R B S C T (p) A R B S C T (o) A R B S C T (n) A R B S C T (m) A R B S C T (l) (k) A R B S C T

03 – 17 Input/Output/3.3 Deadlock

slide-10
SLIDE 10

Dealing with Deadlocks

  • Just ignore them: really not that bad when you

realize that it takes a lot of work to prevent or avoid them.

  • Detect them, and subsequently recover. In prac-

tice, this means checking the resource allocation graph for cycles, and breaking ties by killing pro-

  • cess. Okay for mainframes. Not okay for interac-

tive systems.

  • Avoidance by careful resource allocation.
  • Prevention by making sure that one of the four

conditions can never happen. The best one is to prevent circular wait by ordering resources, and allocating resources in that order.

03 – 18 Input/Output/3.3 Deadlock

Avoidance: Banker’s Algorithm (1/3)

Essence: Devise an algorithm that allows you to ac- tually avoid getting into a deadlock situation. A safe state is one in which resources can be allocated in such a way that we can still get to the end:

A B C D 6 Has Max 5 4 7 Free: 10 A B C D 1 1 2 4 6 Has Max 5 4 7 Free: 2 A B C D 1 2 2 4 6 Has Max 5 4 7 Free: 1 (a) (b) (c)

03 – 19 Input/Output/3.3 Deadlock

slide-11
SLIDE 11

Avoidance: Banker’s Algorithm (2/3)

Plotter Printer Printer Plotter B A u (Both processes finished) p q r s t I8 I7 I6 I5 I4 I3 I2 I1

✁ ✁

Note: In either shaded area, both A and B will have the printer and plotter, respectively ⇒ impossible. This also means that entering the box at t leads to an unsafe state.

03 – 20 Input/Output/3.3 Deadlock

Avoidance: Banker’s Algorithm (3/3)

Process Tape drives Plotters A B C D E 3 1 1 1 1 1 1 1 1 1 E = (6342) P = (5322) A = (1020)

  • Resources assigned

Process Tape drives Plotters A B C D E 1 3 2 1 1 1 1 1 1 1 2 Resources still needed Printers CD ROMs Printers CD ROMs

Question: Assuming that once a process has had all its resources allocated, it will eventually return all of them, in what order would you allocate them to pro- cesses?

03 – 21 Input/Output/3.3 Deadlock

slide-12
SLIDE 12

Overview of I/O in Minix

  • Overview
  • Block devices
  • RAM disks
  • Hard disks
  • Clocks
  • Terminals

03 – 22 Input/Output/3.4 Overview I/O Minix

Positioning Device Drivers

Processes Process-structured system 1 4 2 3 hardware 6 5 File system User process System task Device driver Monolithic system (b) (a) A process The user-space part calls the kernel-space part by trapping. The file system calls the device driver as a

  • procedure. The entire
  • perating system is part
  • f each process

User- space part File system Device driver User space Kernel space 1–6 are request and reply messages between four independent processes.

Note: All communication between processes is gen- erally handled in a uniform way (sending and receiving messages according to some predefined format).

03 – 23 Input/Output/3.4 Overview I/O Minix

slide-13
SLIDE 13

Principle of Device Task

message mess; void io_driver( void ){ int rcode, caller; initialize(); /* called once */ while( TRUE ){ receive( ANY, &mess ); caller = mess.m_source; switch( mess.m_type ){ case READ : rcode = do_read(); break; case WRITE : rcode = do_write(); break; case OTHER : rcode = do_other(); break; default : rcode = ERROR; } mess.m_type = DRIVER_REPLY; mess.REP_STATUS = rcode; send( caller, &mess ); } }

Note: during the call of do ... the device task may block until hardware interrupts:

void do_something( void ){ ...; set controller; receive( HARDWARE, &mess ); ... }

03 – 24 Input/Output/3.4 Overview I/O Minix

Main Driver Task

11057 PUBLIC void driver_task(dp) 11058 struct driver *dp; /* Device dependent entry points. */ 11059 { 11062 int r, proc_nr; 11063 message mess; 11066 init_buffer(); /* Get a DMA buffer */ ..... 11071 while (TRUE) { 11073 /* Wait for a request to read or write a disk block. */ 11074 if(receive(ANY, &mess) != OK) continue; 11076 device_caller = mess.m_source; 11077 proc_nr = mess.PROC_NR; 11080 switch(mess.m_type) { 11081 case DEV_OPEN: r = (*dp->dr_open)(dp, &mess); break; 11082 case DEV_CLOSE: r = (*dp->dr_close)(dp, &mess); break; 11083 case DEV_IOCTL: r = (*dp->dr_ioctl)(dp, &mess); break; 11084 case CANCEL: r = (*dp->dr_cancel)(dp, &mess);break; 11085 case DEV_SELECT: r = (*dp->dr_select)(dp, &mess);break; 11086 11087 case DEV_READ: 11088 case DEV_WRITE: r = do_rdwt(dp, &mess); break; 11089 case DEV_GATHER: /* Reading/writing multiple blocks in one go */ 11090 case DEV_SCATTER: r = do_vrdwt(dp, &mess); break; 11091 11092 case HARD_INT: if(dp->dr_hw_int) (*dp->dr_hw_int)(dp, &mess); 11096 continue; ..... 11107 } 11109 /* Clean up leftover state. */ 11110 (*dp->dr_cleanup)(); 11111 11112 /* Finally, prepare and send the reply message. */ 11113 if (r != EDONTREPLY) { 11114 mess.m_type = TASK_REPLY; 11115 mess.REP_PROC_NR = proc_nr; 11116 /* Status is # of bytes transferred or error code. */ 11117 mess.REP_STATUS = r; 11118 send(device_caller, &mess); 11119 } 11120 } 11121 }

03 – 25 Input/Output/3.5 Block Devices

slide-14
SLIDE 14

Read/Write Operation

11148 PRIVATE int

✂☎✄✝✆✟✞✝✂✝✠✝✡ (dp, mp)

11149 struct driver *dp; /* device dependent entry points */ 11150 message *mp; /* pointer to read or write message */ 11151 11152 /* Carry out a single read or write request. */ 11153 iovec_t iovec1; 11154 int r, opcode; 11155 phys_bytes phys_addr; 11156 11157 /* Disk address? Address and length of the user buffer? */ 11158 if (mp->COUNT < 0) return(EINVAL); 11159 11160 /* Check the user buffer. */ 11161 sys_umap(mp->PROC_NR, D, (vir_bytes) mp->ADDRESS, mp->COUNT, &phys_addr); 11162 if (phys_addr == 0) return(EFAULT); 11163 11164 /* Prepare for I/O. */ 11165 if ((*dp->dr_prepare)(mp->DEVICE) == NIL_DEV) return(ENXIO); 11166 11167 /* Create a one element scatter/gather vector for the buffer. */ 11168

  • pcode = mp->m_type == DEV_READ ? DEV_GATHER :

DEV_SCATTER; 11169 iovec1.iov_addr = (vir_bytes) mp->ADDRESS; 11170 iovec1.iov_size = mp->COUNT; 11171 11172 /* Transfer bytes from/to the device. */ 11173 r = (*dp->dr_transfer)(mp->PROC_NR, opcode, mp->POSITION, &iovec1, 1); 11174 11175 /* Return the number of bytes transferred or an error code. */ 11176 return(r == OK ? (mp->COUNT - iovec1.iov_size) : r); 11177

Note: this is a general template; the actual functions for preparing, scheduling, and finishing the operation, are device specific.

03 – 26 Input/Output/3.5 Block Devices

RAM Disk

  • Treat main memory as just some kind of block de-

vice: read or write addressable blocks of data as if they were disk operations.

  • Use separate, free space of main memory to map

root file system to (so-called root device) ⇒ al- lows you to mount/unmount other “real” periph- eral devices.

  • Write a single device driver, but also use different

“devices”: – /dev/null: the RAM disk with no storage ca- pacity (= wastebasket). – /dev/ram: a real RAM disk (contains the root file system). – /dev/mem: is mapped to complete memory. – /dev/kmem: is mapped to kernel memory. Question: What are these minor devices actually do- ing?

03 – 27 Input/Output/3.6 RAM Disks

slide-15
SLIDE 15

Read/Write to RAM Disk (1/2)

11706 PRIVATE int m_transfer(proc_nr, opcode, position, iov, nr_req) 11707 int proc_nr; /* process doing the request */ 11708 int opcode; /* DEV_GATHER or DEV_SCATTER */ 11709 off_t position; /* offset on device to read or write */ 11710 iovec_t *iov; /* pointer to read or write request vector */ 11711 unsigned nr_req; /* length of request vector */ 11712 { 11713 /* Read or write one the driver’s minor devices. */ 11714 phys_bytes mem_phys; 11715 int seg; 11716 unsigned count, left, chunk; 11717 vir_bytes user_vir; 11718 struct device *dv; 11719 unsigned long dv_size; 11720 int s; 11721 11722 /* Get minor device number and check for /dev/null. */ 11723 dv = &m_geom[m_device]; 11724 dv_size = cv64ul(dv->dv_size); 11725 11726 while (nr_req > 0) { 11727 11728 /* How much to transfer and where to / from. */ 11729 count = iov->iov_size; 11730 user_vir = iov->iov_addr; 11731 11732 switch (m_device) { 11733 11734 /* No copying; ignore request. */ 11735 case NULL_DEV: 11736 if (opcode == DEV_GATHER) return(OK); /* always at EOF */ 11737 break; .....

03 – 28 Input/Output/3.6 RAM Disks

Read/Write to RAM Disk (2/2)

..... 11739 /* Virtual copying. For RAM disk, kernel memory and boot device. */ 11740 case RAM_DEV: 11741 case KMEM_DEV: 11742 case BOOT_DEV: 11743 if (position >= dv_size) return(OK); /* check for EOF */ 11744 if (position + count > dv_size) count = dv_size - position; 11745 seg = m_seg[m_device]; 11746 11747 if (opcode == DEV_GATHER) { /* copy from SELF to proc_nr */ 11748 sys_vircopy(SELF,seg,position, proc_nr,D,user_vir, count); 11749 } else { 11750 sys_vircopy(proc_nr,D,user_vir, SELF,seg,position, count); 11751 } 11752 break; 11753 11754 /* Physical copying. Only used to access entire memory. */ 11755 case MEM_DEV: 11756 if (position >= dv_size) return(OK); /* check for EOF */ 11757 if (position + count > dv_size) count = dv_size - position; 11758 mem_phys = cv64ul(dv->dv_base) + position; 11759 11760 if (opcode == DEV_GATHER) { /* copy data */ 11761 sys_physcopy(NONE, PHYS_SEG, mem_phys, proc_nr, D, user_vir, count); 11763 } else { 11764 sys_physcopy(proc_nr, D, user_vir, NONE, PHYS_SEG, mem_phys, count); 11766 } 11767 break; ..... 11787 } 11788 11789 /* Book the number of bytes transferred. */ 11790 position += count; 11791 iov->iov_addr += count; 11792 if ((iov->iov_size -= count) == 0) { iov++; nr_req--; } 11793 11794 } 11795 return(OK); 11796 }

03 – 29 Input/Output/3.6 RAM Disks

slide-16
SLIDE 16

Disk Hardware

cylinder (8) sector (12 per track)

1

2 4 5 6 7 8 3

Note: There are multiple platters in a single hard disk, with as many tracks as their are heads. Observation: The disk controller hides the actual de- tails of disk layout: it’s all virtual. Now simply use Log- ical Block Addressing (LBA).

03 – 30 Input/Output/3.7 Disks

Disk Arm Scheduling

Initial position Pending requests Cylinder X X X X X X X 5 10 15 20 25 30 35 Time

Sequence of seeks SSF Sequence of seeks FCFS Sequence of seeks elevator

Note: graphs are not “correct”: there is additional time needed for starting/stopping the arm movement.

03 – 31 Input/Output/3.7 Disks

slide-17
SLIDE 17

Disks – Error Handling (1/2)

Real problem: because we are dealing with electro- mechanical devices, lots of things can go wrong. The problem is that the hardware is not going to help us very much ⇒ a lot of code is used to catch/correct error situations.

  • Programming error: yes, just bugs (read cylin-

der 232, get sector −3). Go phone your dealer and get yourself a yap: yet another patch.

  • Transient checksum error: the disk’s dusty so

that read and write errors occur. Trying a number

  • f times usually does the trick.
  • Permanent checksum error: the sector is marked

as a bad block. Pretty nasty with backups that scan a disk rather than files. Sometimes hard- ware can cheat by mapping another block at the same position. That’s called intelligence.

03 – 32 Input/Output/3.7 Disks

Disks – Error Handling (2/2)

  • Seek errors: Again, a mechanical thing, e.g. the

arm is a bit loose and sweeps too far (sector 6 becomes 7). Controllers keep track of where the arm is. Primitive controllers sometimes require recalibration: sweep the arm, and take that as cylinder 0.

  • Controller error: yes, just hardware bugs. The

ultimate solution is the reset button (or reset bit/register). The controller is recalibrated. So what about MINIX: Everything’s very simple there. This means no advanced disk arm scheduling stuff (basically just FCFS), and lots of error control.

03 – 33 Input/Output/3.7 Disks

slide-18
SLIDE 18

Disk I/O transfer (1/2)

12848 PRIVATE int w_transfer(proc_nr, opcode, position, iov, nr_req) 12849 int proc_nr; /* process doing the request */ 12850 int opcode; /* DEV_GATHER or DEV_SCATTER */ 12851 off_t position; /* offset on device to read or write */ 12852 iovec_t *iov; /* pointer to read or write request vector.

☛✌☞✟✍✝✎✑✏☎☞✓✒☎✔✖✕✘✗✚✙✘✛

*/ 12853 unsigned nr_req; /* length of request vector */ 12854 { 12855 struct wini *wn = w_wn; 12856 iovec_t *iop, *iov_end = iov + nr_req; 12857 int r, s, errors; 12858 unsigned long block; 12859 unsigned long dv_size = cv64ul(w_dv->dv_size); 12860 unsigned cylinder, head, sector, nbytes; 12861 12862 /* Check disk address. */ 12863 if ((position & SECTOR_MASK) != 0) return(EINVAL); 12864 12865 errors = 0; 12866 12867 while (nr_req > 0) { 12868 /* How many bytes to transfer? */ 12869 nbytes = 0; 12870 for (iop = iov; iop < iov_end; iop++) nbytes += iop->iov_size; 12871 if ((nbytes & SECTOR_MASK) != 0) return(EINVAL); 12872 12873 /* Which block on disk and how close to EOF? */ 12874 if (position >= dv_size) return(OK); /* At EOF */ 12875 if (position + nbytes > dv_size) nbytes = dv_size - position; 12876 block = div64u(add64ul(w_dv->dv_base, position), SECTOR_SIZE); 12877 12878 if (nbytes >= wn->max_count) { 12879 /* The drive can’t do more then max_count at once. */ 12880 nbytes = wn->max_count; 12881 } ..... 12886 /* Tell the controller to transfer nbytes bytes. */ 12887 r = do_transfer(wn, wn->precomp, ((nbytes >> SECTOR_SHIFT) & BYTE), 12888 block, opcode); 12889 12890 while (r == OK && nbytes > 0) { 12891 /* For each sector, wait for an interrupt and fetch the data 12892 * (read), or supply data to the controller and wait for an 12893 * interrupt (write). 12894 */

03 – 34 Input/Output/3.7 Disks

Disk I/O transfer (2/2)

12896 if (opcode == DEV_GATHER) { 12897 /* First an interrupt, then data. */ 12898 if ((r = at_intr_wait()) != OK) { ..... 12905 } 12906 } 12907 12908 /* Wait for data transfer requested. */ 12909 if (!w_waitfor(STATUS_DRQ, STATUS_DRQ)) { r = ERR; break; } 12910 12911 /* Copy bytes to or from the device’s buffer. */ 12912 if (opcode == DEV_GATHER) { 12913 if ((s=sys_insw(...)) != OK) 12914 panic(w_name(),"Call to sys_insw() failed", s); 12915 } else { 12916 if ((s=sys_outsw(...)) != OK) 12917 panic(w_name(),"Call to sys_insw() failed", s); 12918 12919 /* Data sent, wait for an interrupt. */ 12920 if ((r = at_intr_wait()) != OK) break; 12921 } 12922 12923 /* Book the bytes successfully transferred. */ 12924 nbytes -= SECTOR_SIZE; 12925 position += SECTOR_SIZE; 12926 iov->iov_addr += SECTOR_SIZE; 12927 if ((iov->iov_size -= SECTOR_SIZE) == 0) { iov++; nr_req--; } 12928 } 12929 12930 /* Any errors? */ 12931 if (r != OK) { 12932 /* Don’t retry if sector marked bad or too many errors. */ 12933 if (r == ERR_BAD_SECTOR || ++errors == max_errors) { 12934 w_command = CMD_IDLE; 12935 return(EIO); 12936 } 12937 } 12938 } 12939 12940 w_command = CMD_IDLE; 12941 return(OK); 12942 }

03 – 35 Input/Output/3.7 Disks

slide-19
SLIDE 19

Transferring data (1/2)

12814 PRIVATE int do_transfer(struct wini *wn, unsigned int precomp, unsigned int count, 12815 unsigned int sector, unsigned int opcode) 12816 { 12817 struct command cmd; 12818 unsigned secspcyl = wn->pheads * wn->psectors; 12819 12820 cmd.precomp = precomp; 12821 cmd.count = count; 12822 cmd.command = opcode == DEV_SCATTER ? CMD_WRITE : CMD_READ; 12823 /* 12826 if (wn->ldhpref & LDH_LBA) { 12827 cmd.sector = (sector >> 0) & 0xFF; 12828 cmd.cyl_lo = (sector >> 8) & 0xFF; 12829 cmd.cyl_hi = (sector >> 16) & 0xFF; 12830 cmd.ldh = wn->ldhpref | ((sector >> 24) & 0xF); 12831 } else { 12832 int cylinder, head, sec; 12833 cylinder = sector / secspcyl; 12834 head = (sector % secspcyl) / wn->psectors; 12835 sec = sector % wn->psectors; 12836 cmd.sector = sec + 1; 12837 cmd.cyl_lo = cylinder & BYTE; 12838 cmd.cyl_hi = (cylinder >> 8) & BYTE; 12839 cmd.ldh = wn->ldhpref | head; 12840 } 12841 12842 return com_out(&cmd); 12843 }

03 – 36 Input/Output/3.7 Disks

Transferring data (2/2)

04125 /* Macro shorthand to set (port,value)-pair. */ 04126 #define pv_set(pv, p, v) ((pv).port = (p), (pv).value = (v)) ..... 12947 PRIVATE int com_out(cmd) 12948 struct command *cmd; /* Command block */ 12949 { 12950 /* Output the command block to the winchester controller and return status */ 12951 12952 struct wini *wn = w_wn; 12953 unsigned base_cmd = wn->base_cmd; 12954 unsigned base_ctl = wn->base_ctl; 12955 pvb_pair_t outbyte[7]; /* vector for sys_voutb() */ 12956 int s; /* status for sys_(v)outb() */ ..... 12965 /* Select drive. */ 12966 if ((s=sys_outb(base_cmd + REG_LDH, cmd->ldh)) != OK) 12967 panic(w_name(),"Couldn’t write register to select drive",s); 12968 12969 if (!w_waitfor(STATUS_BSY, 0)) { 12970 printf("%s: com_out: drive not ready\n", w_name()); 12971 return(ERR); 12972 } 12973 12974 /* Schedule a wakeup call, some controllers are flaky. This is done with 12975 * a synchronous alarm. If a timeout occurs a SYN_ALARM message is sent 12976 * from HARDWARE, so that w_intr_wait() can call w_timeout() in case the 12977 * controller was not able to execute the command. Leftover timeouts are 12978 * simply ignored by the main loop. 12979 */ 12980 sys_setalarm(wakeup_ticks, 0); 12981 12982 wn->w_status = STATUS_ADMBSY; 12983 w_command = cmd->command; 12984 pv_set(outbyte[0], base_ctl + REG_CTL, wn->pheads >= 8 ? CTL_EIGHTHEADS : 0); 12985 pv_set(outbyte[1], base_cmd + REG_PRECOMP, cmd->precomp); 12986 pv_set(outbyte[2], base_cmd + REG_COUNT, cmd->count); 12987 pv_set(outbyte[3], base_cmd + REG_SECTOR, cmd->sector); 12988 pv_set(outbyte[4], base_cmd + REG_CYL_LO, cmd->cyl_lo); 12989 pv_set(outbyte[5], base_cmd + REG_CYL_HI, cmd->cyl_hi); 12990 pv_set(outbyte[6], base_cmd + REG_COMMAND, cmd->command); 12991 if ((s=sys_voutb(outbyte,7)) != OK) 12992 panic(w_name(),"Couldn’t write registers with sys_voutb()",s); 12993 return(OK); 12994 }

03 – 37 Input/Output/3.7 Disks

slide-20
SLIDE 20

Floppy Disks

Note: the software to control floppy disk I/O is more complicated than for hard disks:

  • the hardware is so simple, we have to do every-

thing in software: explicitly position the head above the right track; recalibrate the heads if such a seek fails, etc.

  • there are different types of floppies, but we still

want to have a single device driver that can han- dle all of them.

  • floppies are removable, so we have to explicitly

control the motor. In addition, we simply can’t leave the motor on: heads are always positioned

  • n the disk.

03 – 38 Input/Output/3.7 Disks

Terminals

Basics: Terminals consist of a keyboard and a mon- itor that need to be handled separately, but not too separately...

RS-232 interface Network interface Memory-mapped interface Terminals X terminal Character

  • riented

Bit

  • riented

Glass tty Intelligent terminal

03 – 39 Input/Output/3.8 Terminals

slide-21
SLIDE 21

Memory-Mapped Terminals

CPU Memory Graphics adapter Video controller Video RAM Analog video signal Parallel port Bus

  • Character-mapped: A full screen is represented

in video RAM. A character screen (25 × 80) may require 2 bytes per displayed character ⇒ 4000 bytes.

  • Bit-mapped: A screen (800 × 1024) requires at

least that every bit in video RAM controls a screen

  • pixel. Having 1 or 2 bytes per bit isn’t unusual.

03 – 40 Input/Output/3.8 Terminals

Keyboard Driver

Essence: just pick up keystrokes and pass it over to the application.

  • raw: Pass every character as-is to the program

that needs it. Useful for advanced screen editors such as emacs. Note that all keystrokes need to be processed by the program, including backspaces, deletes, etc.

  • cooked: Have the driver handle a line at time:

backspaces etc. are thus processed before hand- ing the edited line to the program (also called canon- ical mode in POSIX). In both cases the driver still has the responsibility for catching keystrokes and collecting characters. In ei- ther case it is essential that character buffering takes place (needed for smoothening input with process- ing).

03 – 41 Input/Output/3.8 Terminals

slide-22
SLIDE 22

Character Buffering

(a) (b) Terminal data structure Terminal data structure Terminal

  • Terminal
  • Central

buffer pool Buffer area for terminal 0 1 Buffer area for terminal 1 1 2 3

Two approaches:

  • Take buffers from a central pool ⇒ efficient use of
  • memory. Used for systems with many terminals.
  • Construct a buffer per terminal ⇒ conceptually

simple, but requires a lot of memory. Used for personal computers with a just a few terminals.

03 – 42 Input/Output/3.8 Terminals

Character Echoing

Idea: immediately display characters when they are typed in. Problems:

  • Screen may be used for program output when

user is typing in characters.

  • What to do when more characters have been typed

that fit into a line?

  • What to do with tabs? (most terminals have no

notion of a tab).

03 – 43 Input/Output/3.8 Terminals

slide-23
SLIDE 23

Special Characters

Note: when operating in cooked mode, we have to be careful in handling special characters: Note: in order to handle some special characters, but not in cooked mode, there is also a cbreak mode. The terminals acts in raw mode, but DEL, CTRL–\, CTRL–S, and CTRL–Q work.

03 – 44 Input/Output/3.8 Terminals

Controlling the Display

This is really simple:

  • Just write characters to the appropriate place in

video RAM – the controller does the rest.

  • Some further assistance from the hardware:

– A scroll register that points to the first line that is to be displayed. The hardware then just wraps around video RAM. – Cursor register that is used to keep track of where the cursor is (controlled by mice and/or arrow keys).

03 – 45 Input/Output/3.8 Terminals

slide-24
SLIDE 24

Terminal Input (1/2)

User FS TTY 1 11 9 9…

2 4 5 8 7 6 3 10 Keyboard Interrupt System task

1: read input request and block 2: request input for user’s terminal 3: reply that there are no characters currently buffered 4: interrupt the terminal driver: there are characters to be processed 5-7: instruct system task to read complete keyboard data

03 – 46 Input/Output/3.8 Terminals

Terminal Input (2/2)

User FS TTY 1 11 9 9…

2 4 5 8 7 6 3 10 Keyboard Interrupt System task

8: instruct the system task to copy data to the ap- propriate address spaces 9: copy keyboard data 10: tell the file system the work has been done 11: unblock the user

03 – 47 Input/Output/3.8 Terminals