Chapter 2 Interfaces to an operating system 2.1 The system service interface System Services from the outside Gray introduces UNIX manual pages in Appendix A, as does Robbins in Appendix A.1. Robbins Appendix A.1.3 covers the apropos and whatis commands. Gray introduces library functions in Section 1.2, and system calls in Section 1.3. Goldt gives an alphabetical list of system calls in Chapter 6. Haviland Section 1.3 introduces system calls and libraries, as does Stevens Section 1.11. See Robbins Appendix A.1.1 on system calls and C library programs, Appendix A.4 on header files, and Appendix A.5 on the linker and libraries. Pomerantz Chapter 7 contains a program which hooks system calls. See Robbins Section 1.4 on system programming. Program 1.1 shows how to use command line arguments in a program. Section 1.6 gives an assignment using argument arrays. Solomon introduces the Win32 API (as used with NT) in Chapter One. Errors Gray deals with on error handling in Section 1.5, and with UNIX error messages in Appendix B. Program 1.2 in Gray illustrates the use of errno and perror(). Robbins Example 1.5 shows the use of strerror(). Haviland Section 2.4 deals with errno, with Section 2.4.1 on perror(). Appendix A gives the errno error codes and their associated messages. See Stevens Section 1.7 on error handling. Appendix B2 gives code for error handling routines, if perror() is not good enough for you. Program B2 writes error messages to standard error. Program B3 writes error messages to standard error, or syslog, depending on a debug flag. Even better, Butenhof Chapter 8 gives hints on how to avoid errors, specifically when programming with threads. System services from the inside The references to Beck, Card, and Maxwell in Appendix A.2 of the textbook cover system services from inside Linux. The distinction between kernel and user mode in NT is introduced in Solomon Chapter One. In Chapter Three, Solomon introduces trap dispatching, or first level interrupt handling. The kernel’s trap handler acts as a switchboard for interrupts, system service calls, © John O’Gorman 2000 hardware exceptions, and memory exceptions. For this, it uses the Interrupt Descriptor Table. System services use interrupt 0x2E; otherwise it is similar to Linux. It synchronizes access to shared kernel data structures by raising the interrupt request level (IRQL). 2.2 Interface with the hardware Simple interface Rusling Chapter 6 covers the Peripheral Component Interconnect (PCI) standard. Interrupt mechanism Rusling Chapter 7 covers interrupts and interrupt handling. Section 7.1 deals with the peripheral interrupt controller, while Section 7.3 covers interrupt handling. Section 8.1 is on polling and interrupts; Section 11.3 is on timers in Linux. Pomerantz Chapter 10 contains code for a program which schedules a function to be called on every timer interrupt. Direct memory access Rusling Section 8.2 covers DMA. 2.4 Discussion questions 1. printf() formats its input parameters into an ASCII string, in accordance with the specification in the format string. Then it passes this string to the appropriate system service of the operating system on which it is running. [Section 2.1] 2. The Win 32 API is probably the most readily available. Others can be found by searching the web. 3. Declarations of structures Typedefs #defines MACROS Prototypes of functions. The actual code for each function is in the libc library. [Section 2.1] 4. Note that it is necessary to type man 2 read to get the correct page. If the return value is –1, then there is an error; check why. Otherwise, check if the return value is equal to the value of the third parameter. [Section 2.1] © John O’Gorman 2000 5. Read the manual page. It could be used to implement your own error handling, or to get a list of all error messages. 6. Using Linux on a PC, the instruction is INT 0x80, which is set up at boot time to point to system_call(). This only allows you to execute one of a number of predefined functions – not take over the whole machine. Of course if you write your own bootstrap program, then you have full control of the machine. [Section 2.1] 7. Each entry is an eight-byte gate descriptor, consisting of a six-byte full pointer (16 bit selector + 32 bit offset), and 16 bits of attributes. [Section 2.2] 8. There are different machine level instructions. MOV moves data to or from the memory address space. IN and OUT are used to read or write the I/O address space. [Section 2.2] 9. It would be sufficient to poll at frequent intervals. But how would it do that without an interrupt to remind it? [Section 2.2] 10. The interrupt handler must save and restore these values itself. But as the handler knows just which registers it is going to use (maybe only one), only the minimum of work is required. [Section 2.2] 11. All unused slots in the interrupt descriptor table are set up at boot time to point to a default handler. This could be as simple as one instruction, IRET. Or it could notify the user that an invalid interrupt has been called. [Section 2.2] 12. Clock Network Disk Terminal Printer [Section 2.2] 13. See Beck Section 7.2.4 [Section 2.2] 14. Update the time of day clock. Decrement the quantum of the current process. Check for completion of I/O requests. [Section 2.2] © John O’Gorman 2000