Operating System

Chapter 11
Virtualization, Containers, and Cloud-Native Operating Systems

Post Graduate Program in Computer Science Engineering
Operating System   •   Post Graduate

11. Virtualization, Containers, and Cloud-Native Operating Systems

Introduction and Context

Operating systems traditionally manage physical processors, memory, storage devices, and networks for applications running on a single machine. Modern computing, however, is increasingly delivered as a pool of software-defined resources distributed across data centres, edge locations, and public or private clouds. A physical server may host many independent virtual machines; each virtual machine may run several containerized services; and those services may be created, replicated, migrated, and terminated automatically in response to demand.

This transformation is not merely a change in packaging. It changes the boundary of the operating system. The kernel still schedules computation, manages memory, enforces protection, and controls devices, but additional layers now virtualize hardware and organize workloads. Hypervisors expose virtual hardware to guest operating systems. Container runtimes isolate processes while sharing a host kernel. Orchestrators coordinate thousands of containers across clusters. Cloud-native operating systems and platforms treat infrastructure as programmable, observable, and replaceable.

The central engineering question is therefore not simply how to run a program. It is how to allocate, isolate, secure, monitor, move, and economically operate many heterogeneous workloads on shared infrastructure. This chapter examines that question through virtualization, containers, orchestration, virtual networking and storage, serverless execution, migration, security, governance, and resource economics.

Learning Objectives

After studying this chapter, a student should be able to:

1. Distinguish full virtualization, para-virtualization, hardware-assisted virtualization, containers, and serverless execution.

2. Explain how hypervisors, namespaces, control groups, and container runtimes provide isolation and resource control.

3. Compare virtual machines and containers in terms of performance, portability, security, and operational complexity.

4. Describe orchestration, virtual networking, software-defined storage, migration, and cluster scheduling.

5. Analyse cloud resource economics, including utilization, elasticity, overcommitment, and total cost of ownership.

6. Evaluate security, governance, ethical, and operational risks in virtualized and cloud-native systems.

7. Select an appropriate execution model for a given application and organizational context.

From Physical Machines to Software-Defined Infrastructure

Virtualization is the abstraction of a physical computing resource into one or more logical resources. A virtual machine (VM) presents a software-defined processor, memory system, disk, firmware interface, and network adapter to a guest operating system. The guest behaves as if it owns a machine, although its resources are multiplexed with those of other guests.

The software layer that provides this abstraction is a hypervisor, also called a virtual machine monitor. A Type 1, or bare-metal, hypervisor runs directly on the hardware and is common in data centres. A Type 2 hypervisor runs as an application on a host operating system and is frequently used on desktops and development systems. The distinction is useful, although modern products may combine characteristics of both models.

Virtualization can be understood through four properties. First, isolation prevents one guest from directly reading or corrupting another guest's memory and devices. Second, equivalence attempts to provide behaviour sufficiently similar to physical hardware for the guest operating system. Third, resource control allows the hypervisor to allocate processor time, memory, storage, and network capacity. Fourth, encapsulation represents a machine as files and configuration, making it easier to copy, back up, or migrate.

Methods of CPU Virtualization

In full virtualization, the guest operating system is not modified. Historically, privileged instructions posed a problem because a guest might attempt to control hardware directly. Hypervisors addressed this through techniques such as binary translation and trap-and-emulate execution. In trap-and-emulate, a sensitive operation causes a controlled transfer to the hypervisor, which validates and performs the operation on behalf of the guest.

Para-virtualization modifies the guest operating system so that it makes explicit hypercalls to the hypervisor for operations that cannot be executed directly. This can reduce overhead, but it requires a specially adapted guest. Hardware-assisted virtualization, supported by processor extensions, supplies execution modes in which guest kernel operations can trap efficiently into the hypervisor. Modern systems commonly combine hardware assistance with optimized drivers and memory-management techniques.

Virtualizing memory requires more than dividing physical RAM. The guest maintains virtual addresses that are translated to guest-physical addresses, while the hypervisor maps those addresses to host-physical memory. Nested page tables or equivalent hardware support accelerate this second level of translation. Memory ballooning allows a guest driver to return memory to the hypervisor under pressure. Transparent page sharing can identify identical pages, although security concerns and workload characteristics limit its desirability. Swapping guest memory to storage is possible but generally introduces severe latency.

I/O virtualization may emulate familiar devices, use paravirtualized drivers, or assign a physical device directly to a guest. Device emulation provides compatibility but may be expensive. Paravirtualized devices reduce overhead by using guest-aware interfaces. Direct assignment and technologies such as single-root I/O virtualization can provide high performance, but they complicate migration and sharing.

Containers: Process Isolation Rather Than Hardware Emulation

A container is an isolated execution environment for one or more processes. Unlike a VM, a conventional container does not contain a complete guest kernel. It uses the host kernel while receiving an isolated view of processes, filesystems, users, networks, and other resources. Consequently, containers usually start faster and consume less memory than VMs, but the shared-kernel boundary creates different security and compatibility assumptions.

On Linux, namespaces provide distinct views of system resources. A process namespace gives a container its own process identifier hierarchy. A mount namespace controls visible filesystems and mount points. Network namespaces provide separate interfaces, routing tables, and ports. User namespaces map container identities to different host identities. Other namespaces isolate hostname and inter-process communication resources.

Control groups, or cgroups, organize processes and constrain their resource use. They can limit or account for CPU time, memory, block I/O, and other resources. A memory limit, for example, prevents an application from consuming all host memory, although the resulting response may be termination or throttling rather than graceful degradation. Resource controls are therefore operational mechanisms, not substitutes for capacity planning.

A container image is an immutable package containing an application, its libraries, configuration defaults, and a filesystem description. Images are commonly built from layers. Layer reuse reduces storage and transfer costs, but it also creates concerns about stale dependencies, vulnerable base images, and accidental inclusion of credentials. A container runtime retrieves an image, creates namespaces and cgroup settings, prepares a writable layer or volume, and starts the process. Container engines add image management, networking, logging, and lifecycle commands; low-level runtimes perform the actual process setup.

The phrase “container” should not be confused with a security guarantee. A privileged container, an exposed host socket, an unsafe kernel interface, or a vulnerable runtime can weaken the boundary substantially. Rootless execution, seccomp filtering, Linux capabilities, mandatory access-control systems, read-only filesystems, minimal images, and regular patching improve the security posture.

Virtual Machines and Containers in Comparison

VMs provide stronger abstraction from the underlying operating system. A guest may run a different kernel and operating-system family from the host, making VMs appropriate for legacy applications, incompatible software stacks, strong tenant separation, and kernel experimentation. Their disadvantages include larger images, longer boot times, and higher management overhead.

Containers provide process-level packaging and rapid deployment. They support dense placement, reproducible application environments, and convenient scaling of stateless services. They are less suitable when workloads require different kernels, highly privileged device access, or isolation against a powerful adversary. In practice, the models are frequently combined: a cloud cluster may run a hardened host operating system, place containers inside VMs, and expose the combination as a managed service.

The correct comparison is not “which technology is universally better?” but “which boundary and lifecycle does the workload require?” A regulated database may benefit from VM isolation and carefully managed storage, while a horizontally scalable web API may benefit from containers and orchestration. Some platforms use lightweight VMs to improve container isolation while preserving rapid startup.

Orchestration and the Cluster as an Operating System

A single container engine cannot manage the placement, health, networking, secrets, and scaling of a large application. Orchestration introduces a control plane that maintains a desired state across a cluster of machines. The user specifies objects such as services, replicas, resource requests, configuration, and placement constraints. Controllers compare the desired state with observed state and take corrective action.

A typical orchestrator includes an API server, persistent state, scheduling logic, node agents, service discovery, networking components, and controllers. The scheduler selects a node based on available resources, affinity and anti-affinity rules, taints, topology, and policy. A node agent starts and monitors workloads. If a process exits, a health check fails, or a node disappears, the control plane may restart or reschedule the workload.

This model is sometimes called declarative management. Instead of writing every operational step, an administrator describes the intended result. Declarative control improves repeatability, but it does not remove complexity. A desired state may be impossible because of insufficient capacity, conflicting constraints, unavailable storage, or network failure. Operators must understand both the abstraction and the underlying mechanisms.

Schedulers must account for CPU and memory requests, actual usage, affinity, data locality, disruption budgets, and failure domains. Packing workloads densely increases utilization but may amplify noisy-neighbour effects. Spreading replicas across hosts or zones improves availability but can increase cost. Autoscaling may respond to CPU, memory, queue length, latency, or business metrics. Poorly selected signals can cause oscillation, delayed scaling, or uncontrolled expenditure.

Virtual Networking and Software-Defined Storage

Virtual networking separates logical connectivity from physical cabling. A container or VM may receive a virtual interface connected to a virtual switch, overlay network, bridge, or software router. The platform can assign addresses, implement service discovery, enforce network policy, and expose selected services through load balancers or gateways.

Overlay networks encapsulate packets so that workloads on different physical hosts appear to share a logical network. They simplify mobility and cluster administration but add encapsulation overhead and troubleshooting complexity. Service discovery maps a stable logical name to changing workload instances. Load balancing distributes requests, while ingress or gateway components handle external access, TLS termination, routing, and policy.

Network isolation should be explicit. A workload that does not need to communicate with a database should not be granted unrestricted access to it. Segmentation, identity-based policies, encryption in transit, and careful management of metadata services reduce lateral movement risks. Observability is essential because a virtual network may fail through incorrect policy, address exhaustion, overlay malfunction, or an unhealthy service rather than a physical link failure.

Virtual storage abstracts disks and storage services as volumes, claims, snapshots, and replicated datasets. Ephemeral storage belongs to a workload instance and may disappear when that instance is replaced. Persistent storage survives instance replacement and is essential for databases, queues, and user data. Storage classes may offer different performance, durability, locality, and price characteristics.

The abstraction hides neither physics nor policy. Replication consumes capacity and network bandwidth. Synchronous durability can increase latency. Snapshots are not always equivalent to application-consistent backups. A portable workload may still be tied to a particular storage provider through specialized APIs or performance assumptions.

Migration, Availability, and Failure Management

Migration moves a running or stopped VM or workload between hosts. Cold migration stops the guest, copies its state, and restarts it elsewhere. Live migration transfers memory while the guest continues to execute, usually repeating the copy until the remaining changed state is small enough for a brief pause. It can support maintenance and load balancing, but it consumes network bandwidth and may be unsuitable for devices, latency-sensitive workloads, or rapidly changing memory pages.

Container rescheduling is usually not live migration. The orchestrator starts a replacement instance, reconnects it to services and storage, and terminates the old instance. This approach assumes that applications are designed for failure and that durable state is externalized or replicated. Stateless services are particularly well suited to replacement. Stateful services require coordinated replication, failover, backup, and recovery procedures.

Availability is commonly designed through redundancy across hosts, racks, zones, or regions. Redundancy is effective only when failure domains are genuinely independent. A cluster with replicas on different virtual machines but the same physical host does not tolerate host failure. Similarly, multiple services may depend on one identity system, network gateway, or storage control plane, creating a hidden common dependency.

Serverless Execution

Serverless computing hides server provisioning from the application developer. In a function-as-a-service model, code is invoked by an event, request, schedule, or message. The provider allocates execution environments, scales them, and charges according to a usage measure such as invocation count, execution duration, or allocated resources. Serverless does not mean that servers disappear; it means that their operation is largely delegated to the provider.

Serverless is attractive for irregular workloads, event processing, APIs, automation, and rapid experimentation. It can reduce idle capacity and operational responsibility. However, cold starts, execution limits, statelessness, provider-specific interfaces, distributed tracing challenges, and unpredictable high-volume costs must be considered. Long-running, latency-sensitive, highly stateful, or resource-intensive applications may be better served by VMs or containers.

Cloud Resource Economics and Capacity Decisions

Cloud economics is an operating-systems concern because allocation mechanisms determine utilization, performance, and cost. A physical server has a capital cost, energy consumption, space requirement, maintenance burden, and finite capacity. Virtualization can improve utilization by consolidating workloads with different demand patterns. Yet consolidation also creates contention and correlated failure risk.

Capacity planning begins with workload characterization: average and peak CPU, memory, storage, network, latency, and growth. Overprovisioning protects performance but leaves resources idle. Overcommitment sells or allocates more virtual capacity than the physical system can simultaneously deliver, relying on statistical variation. It is beneficial when demand is uncorrelated, but dangerous when many workloads peak together.

Important economic measures include utilization, reservation, actual consumption, elasticity, unit cost, and total cost of ownership. A workload with low average usage but strict peak requirements may be cheaper in an elastic public cloud. A stable, high-utilization workload may justify reserved capacity or privately operated infrastructure. Data transfer, managed-service charges, licensing, observability, backup, compliance, and staff time must be included; comparing compute prices alone produces misleading decisions.

FinOps practices connect engineering choices with financial accountability. Teams can use budgets, cost allocation tags, rightsizing, scheduling of non-production resources, commitment discounts, and chargeback or showback. Cost optimization must not undermine reliability, security, or accessibility. Removing redundancy to reduce expenditure may violate a service-level objective or create unacceptable operational risk.

Security, Governance, and Professional Responsibility

Virtualization adds privileged software layers. A hypervisor vulnerability, management-plane compromise, insecure image registry, stolen credential, or misconfigured network policy can affect many workloads. Security must therefore be layered: trusted boot and patching for hosts, hardened hypervisors, least privilege, identity-aware administration, signed and scanned images, secrets management, segmentation, runtime monitoring, backup protection, and tested incident response.

Multi-tenancy raises questions of confidentiality, performance interference, and lawful data handling. Organizations must identify where data is stored, who can administer the platform, how long logs are retained, and how deleted data is treated. Regulatory obligations may require data residency, audit trails, encryption, segregation, or documented recovery capabilities. Automated orchestration also requires governance: an incorrect configuration can be replicated across an entire cluster within seconds.

Professional responsibility includes communicating limits honestly. A container is not automatically a secure VM; a snapshot is not automatically a backup; autoscaling is not automatically reliability; and a managed service is not automatically compliant. Engineers should document assumptions, test failure modes, review permissions, and ensure that cost and risk decisions are visible to accountable stakeholders.

Applied Case: Modernizing a University Research Platform

Background

A university research group operates a web portal that receives sensor data from laboratories. The original system consists of two physical servers, a monolithic application, a relational database, and manually configured backup jobs. During semester projects, traffic increases sharply. Maintenance requires downtime, and one server failure previously caused a prolonged outage.

Situation and Analysis

The application has three distinct characteristics. The web and ingestion components are largely stateless and can be replicated. The relational database is stateful and requires durable, consistent storage. Data-processing jobs are intermittent and consume significant CPU for short periods. The group also has limited operations staff and must protect research data.

Moving everything directly into functions would create difficulties because processing jobs may exceed execution limits and the database requires stable storage. Keeping everything on the original physical servers would preserve low utilization during normal periods and maintain a large failure domain. A mixed architecture is therefore more appropriate.

Approach and Strategy

The university places a small cluster of hardened VMs under a managed orchestration layer. The portal and ingestion services are packaged as containers with explicit CPU and memory requests. Replicas are distributed across hosts, and health checks permit failed instances to be replaced. Network policies restrict ingestion services to the database and message broker. The database uses persistent, replicated storage with tested backups.

Intermittent processing jobs are submitted to a queue and executed as batch containers. During teaching peaks, the cluster autoscaler adds capacity; outside those periods, non-production nodes are reduced. Images are built through a controlled pipeline that scans dependencies and signs approved artifacts. Monitoring combines application latency, queue length, resource usage, failed scheduling attempts, and expenditure.

Outcome

The architecture separates stateless elasticity from stateful durability. Maintenance can be performed by replacing instances rather than modifying servers in place. The group gains better utilization and recovery options, although it accepts new responsibilities: cluster policy, image security, storage testing, and cost monitoring.

Learning Points

The case illustrates that cloud-native modernization is an architectural decision, not simply a conversion of servers into containers. Workload characteristics, failure tolerance, data requirements, staff capability, and cost must be considered together. It also demonstrates why orchestration, observability, and governance are as important as packaging technology.

Challenges and Common Mistakes

Several recurring mistakes weaken virtualized systems. Treating resource limits as a substitute for performance testing can produce throttling and unstable applications. Creating containers from large, unpatched images increases attack surface and deployment time. Storing credentials in images or source repositories exposes secrets through registries and build history. Running every container with excessive privilege defeats isolation.

Another mistake is assuming that replicas automatically provide availability. Replicas may share a host, zone, storage system, or dependency. Similarly, autoscaling may increase the number of failing instances when the real bottleneck is a database or external service. Teams also underestimate observability: without logs, metrics, traces, and audit records, distributed failures become difficult to diagnose.

Finally, organizations may optimize for portability while ignoring operational reality. An abstract workload can still depend on provider-specific networking, storage performance, identity systems, or managed databases. Portability should be evaluated against the cost of migration, not treated as an absolute property.

Current Developments

Contemporary infrastructure increasingly combines VMs, containers, and lightweight isolation mechanisms. Confidential-computing technologies attempt to protect data in use through hardware-enforced trusted execution environments. eBPF-based tooling enables programmable observability and networking within operating-system boundaries, although it requires careful privilege control. WebAssembly is being explored for portable, fast-starting workloads with more constrained execution models.

Edge computing moves orchestration and virtualization closer to sensors and users, where bandwidth, power, and intermittent connectivity matter. Specialized accelerators for artificial intelligence require device-aware scheduling and virtualization. Policy-as-code, software supply-chain provenance, confidential workloads, and automated remediation are becoming central to platform engineering. These developments do not eliminate operating-system principles; they extend them to new hardware, trust boundaries, and economic models.

Best Practices for Design and Operation

A sound implementation generally follows these principles:

  • Choose the isolation boundary according to threat model, kernel requirements, performance, and regulatory obligations.
  • Define resource requests, limits, quotas, priorities, and failure domains explicitly.
  • Use minimal, reproducible, signed images and maintain a controlled software supply chain.
  • Apply least privilege to users, containers, service accounts, devices, and management interfaces.
  • Separate stateless computation from durable state and test restoration rather than merely creating backups.
  • Design for replacement and failure; do not depend on manual repair of individual instances.
  • Make networking, storage, identity, logging, and policy observable and auditable.
  • Measure unit cost and reliability together, including transfer, storage, licensing, and staff effort.
  • Test upgrades, migration, node failure, capacity exhaustion, credential compromise, and regional disruption.

Chapter Summary

Virtualization abstracts physical resources and permits multiple isolated guest systems to share hardware. Hypervisors use software techniques and hardware assistance to virtualize processors, memory, and devices. Containers provide a lighter process-level boundary through namespaces, control groups, filesystem layers, and runtime controls, but they share the host kernel and therefore require careful security engineering.

Orchestration turns a cluster into a programmable resource platform by maintaining desired state, scheduling workloads, replacing failed instances, and coordinating networking and storage. Virtual networks and persistent volumes provide useful abstractions, but they introduce policy, performance, and troubleshooting challenges. Migration and redundancy improve continuity when designed around real failure domains. Serverless execution shifts infrastructure management to a provider and is valuable for suitable event-driven workloads, not as a universal replacement.

Cloud resource economics depends on utilization, elasticity, contention, data movement, commitments, reliability, compliance, and operational labour. Effective cloud-native design balances performance, isolation, security, availability, portability, and cost. The mature engineer treats virtualization not as a single product but as a set of mechanisms for managing shared computation under technical, organizational, and economic constraints.

Key Terms

Hypervisor: Software that creates and manages virtual machines.

Type 1 hypervisor: A hypervisor that runs directly on physical hardware.

Type 2 hypervisor: A hypervisor that runs above a host operating system.

Full virtualization: Execution in which an unmodified guest operating system is presented with virtual hardware.

Para-virtualization: Virtualization in which a guest is modified to communicate explicitly with the hypervisor.

Hardware-assisted virtualization: Processor-supported mechanisms that improve execution and trapping of guest operations.

Virtual machine: An isolated software representation of a computer system.

Namespace: A kernel mechanism that gives a process an isolated view of a resource.

Control group: A mechanism for limiting, accounting for, and prioritizing resource use by processes.

Container image: An immutable, layered package describing an application filesystem and its dependencies.

Container runtime: Software that creates and executes isolated container processes.

Orchestration: Automated coordination of workload placement, scaling, networking, and recovery.

Declarative management: Specification of desired state rather than a complete sequence of commands.

Overlay network: A logical network implemented over an underlying physical network, often through encapsulation.

Persistent volume: Storage that remains available beyond the lifetime of a particular workload instance.

Live migration: Movement of a running virtual machine with only a brief service interruption.

Serverless computing: Execution in which infrastructure provisioning and scaling are largely managed by a provider.

Overcommitment: Allocation of more virtual capacity than can be simultaneously supplied physically, based on demand assumptions.

FinOps: Practices that connect cloud usage, engineering decisions, and financial accountability.

Confidential computing: Protection of data during processing through hardware-supported trusted execution mechanisms.

Review Questions

Short Answer Questions

1. What are the principal differences between a Type 1 and a Type 2 hypervisor?

2. How do namespaces and control groups contribute to container isolation?

3. Why does a container generally start faster than a virtual machine?

4. What is the purpose of declarative management in orchestration?

5. Distinguish ephemeral storage from persistent storage.

Long Answer Questions

1. Explain CPU, memory, and I/O virtualization, including the role of hardware assistance.

2. Compare virtual machines and containers with respect to isolation, portability, performance, and operational use.

3. Describe the main components and responsibilities of a cluster orchestration platform.

4. Discuss the security and governance risks associated with multi-tenant virtualized infrastructure.

5. Explain the economic trade-offs among overprovisioning, overcommitment, elasticity, and reserved capacity.

Analytical / Application Questions

1. A financial application requires a different kernel, strong tenant separation, and stable access to encrypted storage. Would you recommend containers, VMs, or a combination? Justify the decision.

2. An autoscaled web service experiences high latency whenever its database reaches maximum connection capacity. Analyse why simply adding application replicas may fail and propose a better approach.

3. Design an execution strategy for an intermittent data-processing workload with irregular demand, strict data-protection requirements, and a small operations team. Compare containers, serverless execution, and VMs.

22. Multiple Choice Questions with Answers

Question 1

Which mechanism primarily provides a container with an isolated process identifier hierarchy?

A. A hypervisor

B. A process namespace

C. A persistent volume

D. A virtual switch

Correct Answer: B. A process namespace

Question 2

A major advantage of hardware-assisted virtualization is that it:

A. Eliminates the need for a guest operating system

B. Allows efficient handling of sensitive guest operations

C. Converts all stateful applications into stateless ones

D. Prevents all side-channel attacks

Correct Answer: B. Allows efficient handling of sensitive guest operations

Question 3

Which situation most strongly favours a virtual machine over a conventional container?

A. A service requiring rapid horizontal replication

B. A short-lived event handler with irregular demand

C. An application requiring a different guest kernel and strong isolation

D. A stateless web endpoint with immutable images

Correct Answer: C. An application requiring a different guest kernel and strong isolation

Question 4

What is the principal purpose of a control group?

A. To provide service discovery

B. To limit and account for process resource consumption

C. To encrypt data stored in a volume

D. To emulate a physical network card

Correct Answer: B. To limit and account for process resource consumption

Question 5

In declarative orchestration, the control plane primarily:

A. Executes only manually specified repair commands

B. Maintains observed infrastructure in relation to a desired state

C. Replaces every persistent database with object storage

D. Removes the need for application health checks

Correct Answer: B. Maintains observed infrastructure in relation to a desired state

Question 6

Why can live migration be difficult for a workload with rapidly changing memory?

A. The guest cannot use virtual CPUs

B. The memory changes may outpace repeated copying

C. The workload must be converted into a serverless function

D. Persistent storage automatically becomes read-only

Correct Answer: B. The memory changes may outpace repeated copying

Question 7

Which statement best describes persistent storage in an orchestrated environment?

A. It is always deleted when a workload process exits

B. It survives replacement of the particular workload instance

C. It is equivalent to a container image layer

D. It removes the need for backups

Correct Answer: B. It survives replacement of the particular workload instance

Question 8

A company places many replicas on one physical host to reduce cost. What risk is most directly introduced?

A. Improved independence from host failure

B. A common failure domain affecting all replicas

C. Guaranteed reduction in network latency

D. Automatic compliance with data-residency rules

Correct Answer: B. A common failure domain affecting all replicas

Question 9

Which workload is generally a strong candidate for serverless execution?

A. A continuously running, highly stateful database

B. An event-driven task with irregular demand and short execution duration

C. A kernel-development environment requiring custom modules

D. A latency-critical process requiring dedicated hardware at all times

Correct Answer: B. An event-driven task with irregular demand and short execution duration

Question 10

Which practice best supports both security and supply-chain integrity for containers?

A. Running all containers with unrestricted privilege

B. Embedding credentials in the image for portability

C. Using minimal, scanned, signed, and reproducible images

D. Disabling logging to reduce operating cost

Correct Answer: C. Using minimal, scanned, signed, and reproducible images

Operating System
Chapter 11 of 15