Operating Systems
Concept Map
Operating systems are used to coordinate the resources of a computer system and provide these resources to users or services needing them. Operating systems perform as a control program and resource allocator, providing applications access to Files, I/O devices, memory, and networks. The Kernel is loaded as the system control program and must allow for system processes and background services to be loaded. Once the Kernel is loaded, user applications may be loaded and request access to the machine through APIs developed for the particular type of hardware. Depending on the user audience of the device (i.e., embedded computers may not have a user interface), the typical components are some user interface, services, and system calls. User interfaces can be as simple as a command line with support for operations against the system via small command line programs. Systems administrators typically use batch and shell processing to perform repetitive tasks against machines they are responsible for. Perhaps updates, backups, and file directory cleanups are repeatedly done. A batch environment allows a script to be saved that will perform each of these steps on-demand or on a schedule. Graphical User Interfaces (GUI) are used by end user-facing machines that often provide much of the functionality the command or batch environments can, but with a pleasing interface that allows users to explore options through menus and mouse/finger interactions. All of these services provide access to system calls that will manipulate the loaded processes (loading/unloading/canceling), file manipulation (file/directory read/create/modify/delete), device manipulation (keyboard/mouse/monitor), information maintenance, communications (network calls) and protection (ensuring users do not overwrite the system or each other's work).
Processes are the way an operating system manages applications and services. These items are loaded and placed into a long-term scheduler or job queue. As the processor is available, control is given to these applications after they are loaded into the short-term scheduler or ready queue. An important strategy in determining which jobs are placed in the ready queue is identifying a mix of systems that are I/O bound (thus likely to have several waits) vs CPU-bound (will use the CPU more rigorously). Balancing these two concerns allows the system to handle the two different workloads without bogging down service just one need. Processes are managed in a state of new, running, waiting, ready, and terminated. New is a process that is created and placed in the job queue. Running is a process that is in progress. Waiting is a state used for I/O blocks or interrupts. Ready is a job in the ready queue. Terminated is a job that is complete, and resources can be deallocated. The Process control block contains the process state, number, instruction counter, registers, memory limits, and a list of open files. Swapping running processes involves saving the current state of the waited process in its process control block and loading the state from a process control block when a process is set to running.
The overhead of managing a process swap is relatively expensive for the operating system. Threads were designed as a strategy for reusing the processor to get results without the overhead of loading a process. In Concurrent processing, one thread runs on a single CPU, and techniques such as pipelining can optimize the CPU use. In Multi-threaded programming, the idea of parallelism becomes actual as tasks can be delegated to multiple processors. The two strategies for this are data parallelism, where the same task is performed on multiple elements in a dataset, which can thus be shared across multiple processors, and the aggregated results can be combined. Task parallelism, where the system has disparate operations that can be run asynchronously, allows for a responsive experience where resources are shared and economies of scale are realized.
The critical section problem occurs when multiple threads need to collaborate with a common data element. If two processes access and update the common data element simultaneously a race condition is created where the last in "wins" and accurate element processing does not occur. A strategy for handling this is creating a lock or semaphore that indicates a process has exclusive write access to the common element. Code is structured so that there is a critical section where locks are established and released and a remainder section where those common elements are not modified. If a lock cannot be obtained, the software can delay and retry establishing the lock. This should create a situation where each process or thread can modify the common resource and the full consequences of each modification are realized as each thread "takes its turn."
System I/O is accomplished through an interaction between the operating system and system interfaces, for example, mouse, keyboard, disk drive, and network cards. These interfaces define a standard way the operating system expects to interact with hardware. These interfaces are implemented through device drivers that are coded for a specific operating system and device to allow the operation of the device. The operating system will receive requests through hardware interrupt channels that indicate the priority and nature of the request from the device. Output to the device may be queued in memory, buffered to handle mismatches in data type and sizes, or spooled to disk to await sequential delivery when the device is ready.
File systems are another expression of this. Operating systems need the ability to handle different types of files from users. Files are kept on the system along with ownership and access control information to protect files while allowing sharing. The more types of files the operating system can handle by default, the larger the operating system code and the more complicated. Many allow for extensibility to provide the common needs in a more manageable size.
Files need to be stored in a directory system. Three types of file systems are discussed in our reading. Single is all files in a single directory, which ends up with potentially thousands of files and a strong risk of name collision or awkward naming to facilitate all the files in one location. Double storage has a similar problem; it utilizes a master directory that addresses user-specific files stored in a common directory indexed by user and file name. This allows for similar naming but is still unwieldy for the user. Tree directory storage is a more complicated system as far as implementing it is concerned, but it gives the best flexibility for users in managing data. It allows for better logical organization of files and the ability to organize permissions for sharing based on logical subdirectories or file-specific permissions.
Protection is the domain of threats inside the system, while security addresses external threats. For the system's protection, permissions are granularly assigned with a strategy of granting the least privileged access for a user to perform the task. Users needing to consume or read reports may be given read-level access to a directory to see current and previous reports. Editors, on the other hand, would be given write permission to create and modify reports. An administrator would be given owner permission to configure additional readers and editors. These permissions may be assigned in capability lists or access control lists. A capability list would be a distributed set of permissions, enabling access to resources near the resource. These facilitate quick lookup of capabilities for a user, and the system modifies the permissions on behalf of the user. As this is difficult to administer across many users, directory or access control lists allow for centralized permissions management, making it easier to review access and change permissions for larger systems. Permissions may be controlled at a user, device, process, or group level to facilitate the least privileged model. Using a group, common permissions can be assigned to a resource, allowing easy addition and removal of a user to the group and its assigned permissions without re-establishing each permission.
For the security domain, we are concerned with threats from programs run by the user. Depending on the source of the programs, they could contain hostile code that sneaks into the system without the user being aware. Trojan horses and trap doors allow access into systems in ways not intended. There is a common software exploit of overriding buffers or stacks and then redirecting the error code to execute the code the virus needs. For example, opening a shell session in which the virus continues to execute malicious code while the system is otherwise attempting to recover from this error. These errors can be avoided by using bounds checking on inputs to ensure a value exceeding buffer or stack size is not provided to the program. Violations can lead to breaches where privileged information is shared or altered, essential information is destroyed, service is stolen, or services are denied.
System administrators should ensure that systems are set up with security by default, only turning on processes or services once needed. Failure to do so runs the risk of worms, port scanning attacks, and denial of service attacks. Port scanning attacks are pernicious because a hostile attacker can chain a series of vulnerabilities into one program. They methodologically scan each port on the system and test for vulnerabilities that a series of malicious programs can exploit. Viruses are another concern, often slipped in by users executing unsafe code. Viruses come in many flavors, including polymorphic viruses that copy and strategically alter themselves to avoid detection. Or stealth viruses that modify detection code and use hidden file attributes to conceal their presence.
Protection from this comes through Security Policies, which are living documents encoding the best practices the company suggests for preventing unintended system access. Vulnerability assessments and intrusion detection systems can complement this to find issues and preemptively protect the system. The most challenging vulnerability is the end users of the system. Passwords identify the user and may be compromised in several manners. Writing down, shoulder surfing, sharing, and commonly used passwords across systems are common ways for attackers to get permissions they should not have. Strategies to avoid this include aging of passwords (periodic forced changes), two-factor authentication (asking the user to validate themselves with a separate device they have), and biometrics (fingerprints).
The goal of the operating system is to provide services and prevent unintended access. This is a constant struggle and very difficult to control, seemingly impossible to prevent entirely. Awareness of how systems are exploited is a constantly evolving domain, which makes it essential to educate users on correct access methods, safe ways of handling external programs, and their responsibilities in using systems.
Understanding operating systems and how they are structured is a great basis for a programming career. Knowing how things are put together is important, but why they are put together will inform your choices. Being aware of the tradeoffs made in design allows you to choose the right fit for your budget, security, and operational needs.
Comments
Post a Comment