This lesson will explore important concepts to learn in operating systems as a backend engineer.
POSIX (Portable Operating System Interface) is a set of standards that define a common interface for compatibility between operating systems. It was developed to promote software portability and interoperability across UNIX-like operating systems.
POSIX standards were originally established by the Institute of Electrical and Electronics Engineers (IEEE) and are now maintained by the IEEE POSIX working group. The standards specify various interfaces, utilities, and system calls, allowing applications to be written consistently across different POSIX-compliant operating systems.
Here are some key components of POSIX:
Shell and Utilities: POSIX defines a standard command-line interface, including shell syntax and utilities such as file management, text processing, and program execution.
System Calls: POSIX specifies a set of system calls that provide low-level access to the operating system's services and resources. These system calls include functions for process management, file operations, interprocess communication, and networking.
Library Functions: POSIX-compliant operating systems provide a standardized set of library functions that applications can use. These functions are defined in the POSIX standard and cover areas such as file I/O, memory management, and string manipulation.
Threads: POSIX includes a thread interface that allows applications to create and manage multiple threads of execution within a process. The POSIX thread library (pthread) provides thread creation, synchronization, and communication functions.
File System: POSIX defines a file system interface that specifies how files and directories should be organized and accessed. It includes functions for file manipulation, directory traversal, and file permissions.
Environment Variables: POSIX provides a standard set of environment variables that allow applications to access information about the system's configuration, user settings, and runtime environment.
By adhering to the POSIX standards, developers can write more portable applications across different POSIX-compliant operating systems. This means that code written for one POSIX-compliant system can often be compiled and executed on another POSIX-compliant system without significant modifications, enhancing software portability and reducing the need for system-specific adaptations.
Processes and Process Management
A process is a running program in an operating system, and these running programs are executed sequentially. For instance, when you write and execute a program, it becomes a process that executes all the instructions you specified in the program accordingly.
To go deeper, when a program is loaded into memory for execution, it becomes a process, and this running program is divided into four sections.
Stack: The stack contains temporary data such as method or function parameters, local variables, and return address.
Heap: This is the memory allocator. It dynamically allocates memory to the process during its run time.
Text: The section includes the current activity represented by the value Program Counter and the content of the processor’s registries.
Data: All the global and static variables are stored here.
Could you look at the diagram below for a clearer view and understanding?
A process passes through different states during execution. However, it’s important to note that these states may differ in some operating systems and bear different names.
Nevertheless, a process can have one of the following state:
Start: This is the first state when the process is started, loaded in memory, or created.
Ready: This state is when the process is waiting to be assigned to a processor. Processes in this state are either waiting to be assigned to a processor or interrupted by the scheduler to assign the CPU to another process.
Running: When a processor is assigned to a process, the process is set to running while the processor starts to execute the instructions within the process.
Waiting: If a process needs to wait for resources, such as user input or a file, to become available, they are moved to the waiting state.
Terminated, blocked, or exit: The process is moved to terminated state once it finished execution or the CPU or operating system terminated it. The process is removed from memory from this state.
Every operating system has an individual structure that stores information about a process called the Process Control Block (PCB). The PCB is a data structure maintained by the Operating System for every process and contains information about each process (sometimes called a process descriptor).
Here are some of the information that is needed to track each process stored in PCB:
Process ID: This is a unique identification for each of the processes in the operating system.
Program Counter: This is a pointer to the address of the next instruction to be executed for the current process.
Process State: This is the current state of the process, such as running, blocked, waiting, etc
Process Privileges: This is required to allow/disallow access to system resources.
CPU Registers: These are various CPU registers where processes need to be stored for execution for the running state.
CPU Scheduling Information: This is process priority and other information required to schedule the process.
Accounting Information: This includes the amount of CPU used for process execution, time limits, execution ID, etc.
IO Status Information: This includes a list of I/O devices allocated to the process.
Memory Management Information: This includes the information of the page table, memory limits, and Segment table depending on the memory used by the operating system.
Threads and Concurrency
Operating systems, threads, and concurrency are crucial in managing and executing tasks efficiently. Let's explore each of these concepts in detail:
Threads A thread is the smallest unit of execution within a process. A process is an independent program with its own memory space, while threads within a process share the same memory space. Threads allow multiple tasks to be executed concurrently within a single process, enabling better resource utilization and responsiveness.
Each thread has its program counter, stack, and registers, but they share the same code section, data section, and other resources of the parent process. Threads can communicate with each other more easily and efficiently since they have direct access to shared data.
Threads are often used in multithreading applications to perform parallel processing, where multiple threads work on different parts of a task simultaneously, speeding up overall execution.
Concurrency refers to the ability of an operating system to manage multiple tasks and execute them seemingly simultaneously. In a concurrent system, multiple tasks progress independently, and the operating system switches between tasks to give the illusion of simultaneous execution. This allows efficient utilization of CPU time, especially when some tasks are waiting for input/output or other resources.
Concurrency can be achieved using multiple processes or threads. The primary advantage of threads over processes in achieving concurrency is that they are more lightweight since they share the same resources, whereas processes have separate memory spaces.
Thread and Concurrency Relationship Threads are a common way to implement concurrency. When multiple threads are executed concurrently, they can perform different tasks or work on different parts of a task simultaneously. The operating system's scheduler allocates CPU time to each thread, switching between them rapidly, making it appear like they are running simultaneously.
Benefits of Threads and Concurrency
Improved Responsiveness: Concurrency allows multiple tasks to progress simultaneously, leading to better application responsiveness.
Resource Sharing: Threads can efficiently share data and resources within the same process, reducing overhead and communication complexity.
Efficient Resource Utilization: Concurrency enables better utilization of CPU time by switching between threads when one thread is blocked or waiting for resources.
Simplified Programming: Threads provide a more straightforward way to implement parallel processing than managing multiple processes.
However, concurrent execution brings challenges like race conditions, deadlocks, and other synchronization problems. Proper synchronization mechanisms, like semaphores, mutexes, and condition variables, ensure threads cooperate and communicate correctly, avoiding potential issues arising from concurrent access to shared resources.
Threads are implemented in the following two ways:
User-level Threads (ULTs) User-level threads are managed entirely by the application or program without the direct involvement of the operating system. A thread library handles the thread management in the user space, and the kernel remains unaware of the existence of these threads. The operating system schedules the process containing these threads as a single unit, unaware of the internal threads.
Advantages of User-level Threads
Lightweight: Since thread management is handled by the application, creating, switching, and destroying threads is generally faster.
Flexible: The application can define its scheduling policies for threads.
Portable: The thread library can be written to be portable across different operating systems.
Disadvantages of User-level Threads
Lack of true parallelism: If one thread within a process blocks a system call or enters a long-running operation, it can block the entire process, including all other threads.
No utilization of multiple cores: User-level threads cannot be distributed across multiple CPU cores, limiting true parallel execution.
The operating system directly manages kernel-level Threads (KLTs) Kernel-level threads. Each thread is treated as a separate entity by the kernel, and the OS scheduler performs the scheduling of threads, which can take advantage of multiple CPU cores.
Advantages of Kernel-level Threads
True Parallelism: Since the operating system manages threads, they can be scheduled across multiple CPU cores, enabling true parallel execution.
Better responsiveness: If one thread blocks, the operating system can schedule another thread from the same or different process.
Support for multithreading in legacy applications: Kernel-level threads can be used to parallelize applications not explicitly designed for multithreading.
Disadvantages of Kernel-level Threads
Heavier overhead: Creating, switching, and destroying kernel-level threads involve more overhead than user-level threads.
Synchronization complexity: Inter-thread communication and synchronization may require system calls, which can be more expensive than user-level thread library calls.
Hybrid Approaches: In practice, some operating systems use hybrid approaches combining user-level and kernel-level threads. These hybrid models attempt to combine the advantages of both user-level and kernel-level threads while mitigating their respective disadvantages.
For example, a system could have multiple user-level threads mapped to fewer kernel-level threads. If one user-level thread blocks, another user-level thread mapped to the same kernel-level thread can still progress, providing some concurrency and avoiding complete process blocking.
It's important to note that the choice between user-level and kernel-level threads depends on the specific requirements of the application and the characteristics of the underlying operating system.
Scheduling in operating systems refers to determining which processes or threads should be allocated CPU time and in what order. The scheduler is a critical component of an operating system that manages the execution of processes or threads to achieve efficient and fair utilization of system resources.
The primary objectives of scheduling are:
Fairness: Ensuring that all processes or threads get a fair share of CPU time, preventing starvation of any particular task.
Efficiency: Maximizing CPU utilization by keeping the CPU busy as much as possible.
Responsiveness: Providing quick response times for interactive tasks, ensuring a smooth user experience.
Throughput: Maximizing the number of processes or threads completed within a given time.
Various scheduling algorithms are used to achieve these objectives. Some of the commonly used scheduling algorithms include:
First-Come, First-Served (FCFS) Scheduling: In FCFS scheduling, the process that arrives is given the CPU first. The next process in line gets CPU time only when the previous one completes. It is simple and easy to implement but may result in long waiting times for later processes (the "convoy effect").
Shortest Job Next (SJN) Scheduling: SJN scheduling allocates CPU time to the process with the shortest expected processing time next. It aims to minimize average waiting time, but it requires knowledge of the processing time beforehand, which could be more practical.
Round-Robin (RR) Scheduling: In RR scheduling, each process is given a fixed time slice (time quantum) to execute on the CPU. If a process doesn't complete within its time quantum, it is preempted and placed at the end of the ready queue. RR ensures fair sharing of the CPU and responsiveness for interactive tasks.
Priority Scheduling: Each process is assigned a priority, and the scheduler executes the process with the highest priority first. Priority scheduling can be either preemptive (higher priority process can preempt lower priority process) or non-preemptive (current process continues until it voluntarily releases the CPU).
Multilevel Queue Scheduling: Processes are divided into multiple queues based on their attributes or priorities. Each queue may have its scheduling algorithm. For example, interactive tasks may be placed in a higher-priority queue to ensure responsiveness, while CPU-bound tasks may be placed in a lower-priority queue to achieve fairness.
Multilevel Feedback Queue Scheduling: A variation of multilevel queue scheduling where processes can move between queues based on their behavior and resource requirements. Long-running processes can be demoted to a lower-priority queue to give a chance to shorter jobs.
Lottery Scheduling: Each process is assigned a certain number of lottery tickets in lottery scheduling. The scheduler randomly draws a ticket, and the corresponding process gets CPU time. The more tickets a process has, the higher its chances of being selected.
The choice of scheduling algorithm depends on factors like the nature of tasks, system workload, and system objectives. Some operating systems use a combination of different scheduling algorithms or implement variations of existing algorithms to suit their specific needs.
Memory management in operating systems efficiently manages the computer's primary memory (RAM) to enable the execution of multiple processes or programs simultaneously. The main goals of memory management are to ensure that processes can coexist peacefully in memory, prevent conflicts, and optimize memory utilization.
Here are the key aspects of memory management:
Address Spaces: Each process in the operating system has its own virtual address space, which is the range of memory addresses the process can use. Virtual addresses are translated by the hardware's memory management unit (MMU) to physical addresses in RAM. This abstraction provides isolation between processes, preventing one process from accessing the memory of another directly.
Memory Allocation: The operating system allocates memory to processes when they are created or when they request additional memory during runtime. Memory allocation can be classified into two main techniques:
a. Contiguous Memory Allocation: Each process allocates Memory in contiguous blocks. This method is simple and efficient but can lead to fragmentation, where free memory becomes fragmented into small unusable chunks.
b. Non-contiguous Memory Allocation: Techniques like paging and segmentation allocate memory non-contiguously. These methods reduce fragmentation but add complexity to the memory management system.
Paging: In paging, physical and virtual memory are divided into fixed-size blocks called "frames" and "pages," respectively. The process's virtual address space is divided into pages of the same size. The MMU maps virtual pages to physical frames, enabling processes to access memory non-contiguously.
Segmentation: In segmentation, the process's virtual address space is divided into variable-sized segments, such as code segment, data segment, stack segment, etc. Each segment is mapped to a corresponding physical memory location. Segmentation allows for more flexibility in memory allocation but requires additional hardware support for address translation.
Virtual Memory: Virtual memory is a technique that allows processes to use more memory than physically available in RAM. Parts of the process's virtual address space can be temporarily stored on disk in a special area called the page file or swap space. When a process accesses data not currently in RAM, a page fault occurs, and the required page is fetched from the disk into RAM. Virtual memory provides the illusion of ample address space and facilitates efficient memory utilization.
Memory Protection: Memory protection ensures the integrity and security of the operating system and processes. The MMU enforces memory protection by restricting processes from accessing memory regions that do not belong to them. Unauthorized access attempts lead to segmentation faults or access violations.
Memory Sharing: In some cases, processes may need to share memory regions for efficient communication or code reuse. Operating systems provide mechanisms like shared memory or memory-mapped files to facilitate such sharing.
Memory management is a complex and critical aspect of modern operating systems. Efficient memory management is essential for maintaining system stability, performance, and overall user experience.
Inter-Process Communication (IPC) in operating systems refers to the mechanisms and techniques that allow different processes to exchange data, share resources, and communicate. IPC is essential for coordinating activities, enabling cooperation between processes, and facilitating parallel execution of tasks. There are several methods of IPC, including:
Pipes: Pipes are a unidirectional form of IPC, used for communication between processes that have a parent-child relationship or are related in a pipeline. One process writes data to the pipe, and another process reads the data from the pipe. Pipes are typically used for sequential data transfer and are suitable for linear data flow scenarios.
Named Pipes (FIFOs): Named pipes, also known as FIFOs (First-In-First-Out), are similar to pipes but have a unique name in the file system. They allow unrelated processes to communicate by reading and writing data through the named pipe. Unlike regular pipes, named pipes can be used for communication between any processes on the system.
Message Queues: Message queues allow processes to send and receive messages in a predefined format. A process can send a message to a queue, and another process can read the message from the same queue. Message queues are used for asynchronous communication and are particularly useful when the sending and receiving processes do not need to interact directly with each other.
Shared Memory: Shared memory is a method of IPC that allows multiple processes to access the same region of memory. By mapping a memory section into their address spaces, processes can share data more efficiently than through message passing. However, shared memory requires synchronization mechanisms (e.g., semaphores) to manage concurrent access to the shared data and avoid race conditions.
Semaphores: Semaphores are synchronization primitives that control access to shared resources and avoid conflicts between multiple processes. They provide a way for processes to signal each other and coordinate their activities.
Signals: Signals are used to notify processes of specific events or to request termination gracefully. A process can send a signal to another process to indicate that an event has occurred or to instruct it to handle the signal in a specific way.
Sockets: Sockets are used for IPC over a network or between processes on different machines. They provide a bidirectional communication channel between processes and are commonly used for client-server communication.
Remote Procedure Call (RPC): RPC is a higher-level IPC mechanism that allows a process to execute procedures or functions in another process's address space as local. It provides a more abstract way for processes to communicate and share resources.
The choice of the IPC method depends on factors such as the nature of communication required, the relationship between processes, and the level of abstraction needed for the communication. Each IPC method has its strengths and weaknesses, and different scenarios may require different IPC mechanisms for efficient and secure communication between processes.
I/O (Input/Output) Management in operating systems manages the communication and interaction between the computer's hardware devices and software processes. It facilitates data transfer between peripheral devices (e.g., keyboard, mouse, disks, network cards) and the computer system's CPU, memory, and other components. I/O management is crucial for efficient and reliable data transfer, resource utilization, and overall system performance. Here are the key aspects of I/O management:
Device Drivers: Device drivers are software components that act as intermediaries between the operating system and hardware devices. They provide an abstraction layer that allows the operating system to communicate with diverse hardware devices using standardized interfaces. Device drivers manage the specifics of each device, including initialization, data transfer, and error handling.
I/O Scheduling: I/O scheduling algorithms determine the order in which I/O requests from different processes are serviced by the underlying hardware. The scheduler aims to optimize the use of I/O resources, minimize response times, and prevent resource contention. Common I/O scheduling algorithms include First-Come, First-Served (FCFS), Shortest Seek Time First (SSTF), and SCAN.
Buffering: Buffering temporarily stores data in memory before it is read from or written to a device. Buffers smooth out variations in I/O speeds between devices and the CPU, preventing the CPU from waiting for slow I/O operations to complete. Buffers also help reduce the number of direct accesses to I/O devices, which can be relatively slow compared to memory access.
Caching involves storing frequently accessed data from I/O devices in a cache (usually in main memory) to expedite subsequent access. Caching helps reduce the time and frequency of reading data from slower storage devices like disks, as the data can be fetched from the cache instead.
Spooling: Spooling (Simultaneous Peripheral Operation On-line) manages multiple I/O requests from different processes to a single device, such as a printer. The I/O requests are queued in a spooling directory, and the device processes them individually in the order they were received. Spooling enables concurrent access to the device by multiple processes without conflicting with each other.
Interrupt Handling: When an I/O operation completes or requires attention (e.g., data transfer completed, device error occurred), the hardware generates an interrupt to signal the CPU. The operating system's interrupt handler then takes appropriate action, such as waking up the waiting process or handling errors.
I/O Control: I/O control involves providing an interface for processes to request I/O operations and manage devices. The operating system must maintain the integrity and security of I/O operations by ensuring proper permissions and access controls.
Direct Memory Access (DMA): DMA is a hardware feature that transfers data directly between memory and an I/O device without CPU intervention. DMA significantly reduces the CPU overhead in managing I/O operations and speeds up data transfer rates.
Efficient I/O management is essential for maximizing system performance and ensuring smooth interaction between processes and peripheral devices. The operating system's I/O management is responsible for abstracting and optimizing the complexities of interacting with diverse hardware devices, making the overall system operation transparent and efficient to applications.
Virtualization in operating systems refers to creating virtual resources or environments that abstract and mimic physical hardware or software components. It allows multiple virtual instances (e.g., virtual machines, virtual storage, virtual networks) to coexist on a single physical machine, providing isolation, flexibility, and resource optimization.
There are several types of virtualization in operating systems:
Virtual Machines (VMs): Virtual machine technology enables the creation of multiple virtualized instances of complete operating systems on a single physical machine. Each virtual machine behaves as an independent computer with its own virtual CPU, memory, storage, and network interfaces. VMs provide isolation and security, enabling the execution of different operating systems and applications within their dedicated virtual environments.
Hardware Virtualization: Hardware virtualization, or platform virtualization, is achieved through hypervisors or virtual machine monitors (VMMs). These software or firmware layers run directly on the hardware and manage the creation and execution of multiple virtual machines. The hypervisor ensures that each VM has isolated access to hardware resources and manages the scheduling of virtual CPU, memory, and I/O operations.
Containerization: Containers provide a lightweight form of virtualization, allowing applications and their dependencies to run in isolated environments. Unlike virtual machines, containers share the host operating system's kernel, making them more efficient and faster to start than VMs. Containerization technology, such as Docker and Kubernetes, has become popular for deploying and managing applications in cloud environments.
Emulation: Emulation involves creating a virtual version of hardware or software that mimics the behavior of a different platform or architecture. Emulators allow software designed for one platform to run on a different platform. For example, some emulators enable running old console games on modern computers, which require simulating the original console's hardware.
Virtual Storage: Virtual storage allows the creation of logical storage units that abstract and optimize physical storage devices. Storage virtualization techniques include disk pooling, virtual storage area networks (SANs), and software-defined storage (SDS). These technologies enable efficient utilization of storage resources and improve storage management.
Virtual Networks: Virtual networks allow the creation of logical network segments that abstract and optimize physical network infrastructure. Virtual Local Area Networks (VLANs) and Software-Defined Networking (SDN) are examples of virtual networking technologies. Virtual networks provide flexibility in network configuration and segregation while optimizing network resources.
Benefits of Virtualization:
Resource Utilization: Virtualization enables better utilization of physical resources by allowing multiple virtual instances to share the same hardware.
Isolation: Virtualization provides strong isolation between different virtual instances, enhancing security and stability.
Flexibility: Virtualization allows for easy provisioning and migration of virtual instances, making it simpler to scale applications and services.
Consolidation: Virtualization enables the consolidation of multiple physical machines into a single physical host, reducing hardware costs and maintenance efforts.
Virtualization has become a fundamental technology in modern computing, enabling the efficient use of hardware resources and providing a flexible and scalable infrastructure for various applications and services. It has revolutionized how IT infrastructure is managed and deployed, especially in cloud computing environments.
Distributed File Systems
A Distributed File System (DFS) in operating systems is a network-based file system that allows multiple computers or nodes in a distributed computing environment to access and share files and data stored on remote storage devices. The primary goal of a distributed file system is to provide a transparent and unified view of files and directories across a network, making it appear as if the files are stored locally on each node. This abstraction hides the underlying complexity of the distributed storage infrastructure from end-users and applications. Some key features and components of distributed file systems include:
Transparency: Distributed file systems aim to provide transparency to users and applications by presenting a consistent and unified view of files, regardless of their physical location or storage device. Users interact with files using familiar file operations (e.g., read, write, create, delete) without knowing the data's actual location.
Scalability: Distributed file systems are designed to scale as the number of nodes and the volume of data grow. They can handle large amounts of data and distribute the load across multiple nodes to perform better.
Fault Tolerance: Distributed file systems often incorporate mechanisms to ensure data availability and reliability in the face of node failures or network disruptions. Replication and redundancy are commonly used techniques to provide fault tolerance.
File Caching: Caching improves performance by storing frequently accessed data in memory on the client side, reducing the need to fetch data from remote servers.
Namespace Management: Distributed file systems maintain a global namespace that maps file names to their physical locations. This namespace management ensures that files are uniquely identified across the distributed environment.
File Locking: To maintain data consistency and avoid conflicts, distributed file systems implement file-locking mechanisms that allow multiple clients exclusive or shared access to files.
Security: Distributed file systems include security features such as authentication and access control to protect sensitive data and restrict unauthorized access.
Popular Distributed File Systems:
NFS (Network File System): Developed by Sun Microsystems, NFS is a widely used distributed file system protocol for UNIX-based systems. It allows clients to access remote files and directories over a network as if they were local.
CIFS/SMB (Common Internet File System / Server Message Block): CIFS, later known as SMB, is a protocol developed by Microsoft for file and printer sharing in Windows-based environments. It is also commonly used in mixed environments that involve Windows and non-Windows systems.
AFS (Andrew File System): AFS is a distributed file system initially developed at Carnegie Mellon University. It focuses on scalability, fault tolerance, and providing a single global namespace.
HDFS (Hadoop Distributed File System): HDFS is a distributed file system designed for storing large volumes of data across a cluster of commodity hardware. It is commonly used in big data processing frameworks like Apache Hadoop.
Distributed file systems play a vital role in modern computing, especially in cloud computing and large-scale data processing environments, where data needs to be accessible and shared across multiple nodes efficiently and reliably.
Distributed Shared Memory
Distributed Shared Memory (DSM) in operating systems is a concept that allows multiple processes running on different nodes in a distributed computing environment to share a common memory space. DSM provides the illusion that all participating processes have access to a shared memory, even though the physical memory is distributed across multiple machines.
The key idea behind DSM is to abstract the complexities of distributed memory management and provide a programming model that resembles shared memory multiprocessing. This approach enables programmers to write parallel applications using familiar shared memory programming techniques, making it easier to develop parallel algorithms.
There are two main approaches to implementing DSM:
Software-based DSM: In software-based DSM, the shared memory abstraction is implemented entirely in software without requiring any hardware support. Each node in the distributed system runs a DSM runtime library that handles communication and synchronization between processes to maintain the shared memory illusion.
Software-based DSM relies on communication protocols like Remote Procedure Calls (RPCs) or message passing to exchange data and coordinate access to shared memory. When a process on one node accesses a shared memory location, the DSM software coordinates with other nodes to ensure the coherence and consistency of the shared data.
One of the challenges in software-based DSM is the overhead of communication and synchronization, which can negatively impact performance. However, advancements in network and interconnect technologies have made software-based DSM more practical for certain parallel applications.
Hardware-based DSM: Hardware-based DSM leverages hardware support to implement shared memory semantics in a distributed system. This approach often involves specialized hardware components, such as shared memory interconnects or specialized memory controllers, to enable efficient and low-latency communication between nodes.
Hardware-based DSM can significantly reduce the overhead associated with communication and synchronization, providing better performance for parallel applications. However, it requires specialized hardware, making it less flexible and more costly to deploy.
Advantages of Distributed Shared Memory:
Simplified Parallel Programming: DSM provides a familiar shared memory programming model, simplifying the development of parallel applications compared to message-passing-based approaches.
Efficient Data Sharing: DSM allows processes to share large amounts of data directly, avoiding the need for explicit message passing.
Scalability: DSM can scale to many nodes, enabling the development of parallel applications on distributed computing clusters.
Data Locality: Processes can access data that resides on a remote node as if it were local, enhancing data locality and reducing data transfer overhead.
Challenges of Distributed Shared Memory:
Consistency and Coherency: Ensuring the consistency of shared data across distributed nodes and maintaining cache coherency can be challenging and may require complex protocols.
Latency and Overhead: Communication and synchronization overhead can impact performance, especially in software-based DSM.
Scalability Limits: As the number of nodes increases, the complexity of maintaining coherency and consistency also grows, limiting scalability.
DSM is a powerful concept for parallel computing, enabling efficient utilization of distributed resources while simplifying the development of parallel applications. However, the choice between software-based and hardware-based DSM depends on the specific requirements and characteristics of the distributed computing environment.