IT Embedded System Key
IT Embedded System Key
The processor executes program instructions, processes data, and controls all operations of the
embedded system.
Processor/Microcontroller
Memory (RAM, ROM/Flash)
Input/Output interfaces
Sensors and actuators
Power supply
Embedded software/firmware
The ALU (Arithmetic Logic Unit) performs arithmetic operations (addition, subtraction,
multiplication, etc.) and logical operations (AND, OR, NOT, comparison).
Memory organization determines how program and data are stored and accessed, affecting
system speed, power consumption, cost, and overall performance.
1. Start condition
2. Slave address
3. Read/Write bit
4. Acknowledge (ACK) bit
5. Data byte(s)
6. ACK/NACK
7. Stop condition
1(f) How is a serial device interfaced with a microcontroller?
A serial device is interfaced using serial communication protocols such as UART, SPI, or I2C
through TX/RX or clock/data lines.
Macros are used to simplify repetitive code, improve readability, reduce execution overhead,
and make hardware register access easier.
1(h) In embedded firmware, why would you choose assembly language over C for certain
tasks? Give one scenario.
Assembly language is chosen when very high speed, precise timing, or direct hardware control
is required.
Example: Writing an Interrupt Service Routine (ISR) for fast real-time response in a motor
control system.
1(i) What is the role of the I/O subsystem manager in an embedded operating system?
The I/O subsystem manager controls communication between hardware devices and software,
manages device drivers, and handles input/output operations efficiently.
1(j) How would you use message queues for inter-process communication in an embedded
system? Provide a brief example.
Example:
A sensor task sends temperature data to a queue, and a display task reads the queue to show the
temperature on an LCD.
2a. Elaborate the operational and non-operational Discuss the quality attributes of
embedded system.
Embedded system quality attributes are divided into operational (runtime performance) and
non-operational (lifecycle/development) categories. Key operational attributes include response
time, throughput, reliability, security, and safety, which dictate how the system functions. Non-
operational attributes focus on development, such as testability, maintainability, portability, and
time-to-market.
Operational Quality Attributes (Runtime Functionality)
These attributes are observed while the embedded system is actively functioning.
Response Time: Measures the speed of the system in responding to an input or event. In real-
time systems, this is critical (e.g., airbag deployment must happen instantly).
Throughput: Refers to the efficiency of the system, defined as the rate of production or the
number of tasks completed per unit of time.
Reliability: The percentage of confidence that the system will perform its intended function
without failure over a specific period. Measured by metrics like Mean Time Between Failures
(MTBF).
Maintainability: Represents the ease with which a system can be modified or repaired to fix
faults, improve performance, or adapt to a changed environment.
Security: Ensures the confidentiality, integrity, and availability of data and functionalities,
protecting the system against unauthorized access or attacks.
Safety: Measures the potential risk of accidents or damage to users and surroundings, especially
in critical systems like medical devices or automobiles.
Non-Operational Quality Attributes (Development Lifecycle)
These attributes are associated with the system's development, deployment, and overall
lifecycle, rather than its active operation.
Testability and Debug-ability: Refers to how easily the system's firmware/hardware can be
tested, and faults can be identified and fixed.
Evaluability (Flexibility): The ease with which the system can be updated or upgraded with
new features without completely redesigning the system.
Portability: The capability of the embedded system (specifically the software) to run on
different hardware environments with minimal changes.
Time to Prototype and Market: The duration taken to develop a functional prototype and
bring the final product to market.
Cost (Per Unit and Total): The cost optimization for manufacturing (per unit cost) and the
overall development budget (total cost)
2 b. Explain the design process of an embedded system/ explain the
abstraction steps in the embedded system design process.
Abstraction
In this stage the problem related to the system is abstracted.
Hardware – Software Architecture
Proper knowledge of hardware and software to be known before starting any design process.
Extra Functional Properties
Extra functions to be implemented are to be understood completely from the main design.
System Related Family of Design
When designing a system, one should refer to a previous system-related family of design.
Modular Design
Separate module designs must be made so that they can be used later on when required.
Mapping
Mapping into various representations is done from software and hardware
requirements. For example, data flow and program flow are mapped into one.
User Interface Design
In user interface design it depends on user requirements, analysis and function of the system. For
example, in an automatic chocolate vending machine (ACVM) system, the user interface is LCD
multiline graphic display. It can display a welcome message, specifies coins need to insert into
machine for each type of chocolate.
Refinement
Every component and module must be refined appropriately so that the software
team can understand.
3.a. Illustrate with block diagram the interaction of embedded hardware and
software components.
Hardware components of embedded systems form the physical backbone of any embedded
system. These include processors, memory types in embedded systems, timers, sensors, and
input/output devices. Without reliable hardware, the system cannot process data or interact
with the environment effectively. It provides the foundation on which software and RTOS can
function.
1. Power Supply: Every embedded system requires a stable power source.
o Most systems operate on 5V or lower (1.8V–3.3V).
o Battery-powered devices include power management in embedded systems circuits to
extend battery life.
2. Embedded Processor: The processor is the brain of the system. It can be a
microcontroller (MCU) or a microprocessor (MPU).
o Microcontroller: Combines CPU, memory, and peripherals in one chip. Ideal for small
devices like washing machines or remotes.
o Microprocessor: More powerful, suited for complex applications like smartphones and
industrial systems.
3. Memory: Memory in embedded systems stores both instructions and data.
o Program Memory (ROM, Flash, EEPROM) – Stores permanent instructions.
o Data Memory (RAM, SRAM, DRAM, SDRAM) – Stores temporary data while tasks are
running.
4. Timers and Counters: Timers help control time-based tasks like delays, alarms, and cycle
counts. For example, washing machines use timers to switch between wash and spin cycles.
5. Interrupt Controller: An interrupt controller manages signals from different devices.
o Allows urgent tasks (like a button press) to pause current operations.
o Prevents data loss and ensures real-time responses.
6. Communication Interfaces: Communication interfaces in embedded systems help
devices talk to external hardware or networks.
o UART – Short-distance serial communication.
o SPI / I2C – Common in sensors and displays.
o RS232 / RS485 – Widely used for industrial communication.
o Ethernet, USB, Wi-Fi, Bluetooth – Enable internet and device connectivity.
7. Sensors: Sensors allow systems to sense the environment.
o Temperature sensors – Thermostats, AC units.
o Proximity sensors – Parking sensors in cars.
o Humidity and IR sensors – IoT devices and security systems.
o Light and alcohol sensors – Smart lighting, breath analyzers.
8. Actuators: Actuators in embedded systems convert electronic signals into physical
actions.
o Motors in fans, robots, or automotive systems.
o Valves in irrigation or industrial systems.
9. Peripherals: Peripherals extend functionality beyond the CPU.
o ADC (Analog-to-Digital Converter) – Converts real-world signals like temperature into
digital form.
o PWM (Pulse Width Modulation) – Controls motor speed or LED brightness.
o Watchdog Timer – Resets the system if it hangs.
Software Components of Embedded Systems
Software components define how the hardware behaves and ensure that tasks are executed
properly. They include compilers, linkers, debuggers, and emulators that help developers
write, test, and optimize code. Good software tools make it easier to manage memory types
in embedded systems and improve performance. Together, they bring the hardware to life
with intelligence.
1. Compiler / Assembler
o Compiler: Converts high-level code (C, C++) into machine code.
o Assembler: Converts assembly language instructions into object code.
2. Linker: Combines multiple code files into one final executable program. Without a linker, a
system cannot run smoothly.
3. Debugger: A debugger helps detect and fix errors in the code. It shows why the program
did not run as expected.
4. Emulator: An emulator mimics another system’s behavior. Developers use it to test designs
without the actual hardware.
3 b. Suggest how you would select the processor and memory for an embedded
system used in a traffic control system. Justify your choices.
Selecting a processor and memory for an embedded traffic control system requires balancing
real-time performance, high reliability, safety, and durability, as these systems operate 24/7 in
harsh outdoor environments.
For a modern, adaptive, or smart traffic control system, I would select an ARM Cortex-M
based microcontroller (MCU) or an ARM Cortex-A based Microprocessor (MPU),
depending on the complexity, combined with Flash and SRAM memory, utilizing EEPROM
for configuration.
1. Processor Selection: ARM Cortex-M or Cortex-A SoC
I would choose an ARM Cortex-M4 or M7 MCU (e.g., STM32 series) for typical, localized
intersections, or an ARM Cortex-A (e.g., NXP [Link] series) for intelligent/networked systems.
Choice: 32-bit ARM Cortex-M7 (MCU)
o Justification (Performance & Real-time): Traffic lights need to react instantly to sensor
inputs (pedestrian buttons, loop detectors). A 32-bit core running at ~200-400 MHz provides
enough processing power for FSM (Finite State Machine) logic and timing calculations without
the overhead of a full Operating System.
o Justification (Peripherals): ARM-based SoCs integrate crucial peripherals directly on-chip:
GPIOs for lights, UART/CAN for communication with other controllers, and timers for precise
1-second cycling.
o Justification (Low Power/Reliability): They offer high performance while maintaining low
power consumption and generating less heat, improving the reliability and lifetime of the
controller cabinet.
Alternative for Smart/Adaptive Systems: If the system requires camera-based vision (AI) to
count vehicles, I would choose a high-end Cortex-A processor to handle image processing
algorithms.
2. Memory Selection: Flash, SRAM, and EEPROM
The memory architecture must ensure that program code is safe during power outages and that
temporary data (vehicle counts) can be quickly updated.
Internal Flash Memory (Non-Volatile - 512KB to 2MB):
o Justification: Stores the firmware (operating code). It is non-volatile, meaning the traffic
program will not be lost if power is cut.
Internal SRAM (Volatile - 128KB to 512KB):
o Justification: Used for temporary storage of real-time variables, data buffering, and stack
operation during processing. Its high speed ensures fast responsiveness.
EEPROM or Secure External Flash (Non-Volatile):
o Justification: Required to store configuration parameters (e.g., traffic cycle times, ID numbers,
network settings) that might change over time, allowing for updates without reflashing the
entire firmware.
Industrial-Grade SD Card / NAND Flash (Optional for Data Logging):
o Justification: If traffic logging (data recording) is needed, this provides large, non-volatile
storage for historical data.
Summary of Selection Justification
Component Choice Key Requirement Addressed
RISC (Reduced Instruction Set Computer) and CISC (Complex Instruction Set Computer) are
processor design philosophies. RISC uses simple, fixed-length instructions (e.g., ARM, MIPS)
for fast, single-cycle execution and high efficiency, while CISC uses varied-length complex
instructions (e.g., Intel x86) to perform multiple operations, reducing code size but increasing
complexity.
Key Differences between RISC and CISC:
Instruction Complexity: RISC uses simple instructions designed to complete in one clock
cycle. CISC instructions are complex, often taking multiple clock cycles for one instruction.
Instruction Format & Length: RISC typically uses fixed-length instructions (32-bit). CISC
uses variable-length instructions.
Memory Access: RISC employs a load/store approach, meaning only specific instructions
access memory, while others use registers. CISC allows direct memory-to-memory operations
within instructions.
Performance Focus: RISC relies on software/compilers for optimization. CISC prioritizes
hardware capability to reduce the total number of instructions per program.
Hardware Usage: RISC uses fewer transistors for instructions, often freeing space for more
registers. CISC requires more hardware complexity to decode and execute complex instructions.
Power Consumption: RISC generally consumes less power, making it ideal for mobile
devices, while CISC consumes higher power.
Summary Table
Feature RISC (Reduced Instruction Set) CISC (Complex Instruction Set)
Instruction Size Fixed length Variable length
Cycles/Instruction Typically 1 Multiple
Memory Access Load/Store instructions only Directly from memory allowed
Pipelining Highly efficient Less efficient
Control Unit Hardwired Micro-programmed
Examples ARM, MIPS, RISC-V, PowerPC Intel x86, AMD, VAX
7b. Compare I2C SPI AND UART in terms of number of lines, speed and
complexity. Conclude which is best for memory interfacing
I2C (Inter-Integrated Circuit), SPI (Serial Peripheral Interface), and UART (Universal
Asynchronous Receiver-Transmitter) are foundational protocols for embedded systems in 2026,
with SPI offering the highest speeds, I2C excelling in low-pin-count device connectivity, and
UART providing simple, two-wire point-to-point communication.
Comparison of Communication Protocols
Number of Lines:
o I2C: Uses 2 lines (SDA/Data, SCL/Clock).
o SPI: Uses 4 lines (MOSI, MISO, SCLK, SS/CS) + 1 line for every additional slave device.
o UART: Uses 2 lines (TX/Transmit, RX/Receive).
Speed:
o SPI: Highest speed (up to 100+ Mbps), suitable for high-data scenarios.
o I2C: Moderate speed (Standard 100 kbps, Fast 400 kbps, High-speed up to 3.4 Mbps).
o UART: Slowest (Typical, often up to 1 Mbps).
Complexity:
o I2C: High hardware complexity due to addressing, but low pin count.
o SPI: High software simplicity, but complex wiring for multiple devices.
o UART: Lowest complexity, as it is asynchronous and requires no clock signal
o
8a. Explain the assembly language to machine language conversion process with
neat sketch
8b. Explain in detail about super loop based approach for embedded firmware
design.
The Super Loop (or Super-Loop) architecture is a fundamental bare-metal firmware design
approach where tasks are executed sequentially within a single infinite loop. It is the most
common starting point for microcontroller programming because it requires no Operating
System (OS) or complex scheduling.
Core Structure
The architecture consists of two primary sections:
1. Initialization: Hardware peripherals (clocks, GPIO, memory) and software modules are
configured once before entering the loop.
2. Infinite Loop: A while(1) or for(;;) loop that repeatedly executes tasks in a hard-coded, fixed
orderConceptual C Implementation:
c
void main() {
System_Init(); // Configure hardware and variables
while(1) { // The "Super Loop"
Task_Read_Inputs();
Task_Process_Data();
Task_Update_Outputs();
}
}
Use code with caution.
Key Characteristics
Sequential Execution: Each task must complete before the next one begins.
Fixed Priority: Since tasks are hard-coded, their "priority" is determined by their position in the
loop and how often they are called.
Foreground-Background Model: Often, Interrupt Service Routines (ISRs) act as the
"foreground" to handle time-critical events, while the super loop acts as the "background" for
non-critical processing.
Advantages
Low Resource Usage: Ideal for constrained hardware with limited RAM/Flash, as it avoids the
overhead of RTOS context switching and per-task stack allocation.
Simplicity: Easy to implement, debug, and understand for smaller projects.
Predictability: The execution flow is highly deterministic for simple systems without complex
branching.
Disadvantages
Lack of Real-Timeliness: If one task takes a long time (e.g., waiting for a slow sensor), it
delays every other task in the loop, potentially causing missed events.
Single Point of Failure: If the firmware hangs or enters an infinite loop inside a single task, the
entire system stops functioning unless a Watchdog Timer (WDT) is used.
Scalability Issues: As more features are added, the loop becomes "spaghetti code," making
maintenance difficult.
Typical Applications
Super loops are best for low-cost, non-time-critical devices:
Simple toys and household appliances.
Basic sensor monitoring nodes.
Automatic door systems.
Arduino projects (which use a setup() and loop() structure)
9a. You are working on a embedded system where memory efficiency is crucial.
Explain how choosing appropriate data types can impact the performance and
memory usage.
Choosing appropriate data types in embedded systems, such as using uint8_t instead of int,
directly reduces RAM/Flash consumption, minimizes CPU cycles for processing, and prevents
padding waste. Optimal choices minimize memory footprint, avoid heavy floating-point
operations, and align data to 32-bit boundaries to increase system speed and power efficiency.
Impact on Memory and Performance:
Memory Footprint Optimization: Utilizing smaller data types (uint8_t, int16_t) instead of
default int (which can be 32-bit) significantly reduces usage of scarce SRAM and Flash
memory.
Preventing Padding Waste: Structs should be arranged from largest to smallest type to avoid
"padding" bytes, which are empty, wasted bytes inserted by compilers to align data to memory
boundaries.
CPU Processing Speed: Smaller data types often map directly to smaller registers, allowing the
processor to perform calculations faster. For instance, an 8-bit MCU operates faster on 8-bit
data than on 32-bit integers.
Floating-Point Penalties: Avoiding float or double types in favor of fixed-point or integer
arithmetic saves code space and,, on many microcontrollers lacking an FPU (Floating Point
Unit), significantly boosts performance.
Fixed-Width Types: Using <stdint.h> types (e.g., uint32_t, int8_t) ensures consistent memory
consumption across different compiler architectures
9b. In embedded firmware how would the use of processor directives and source
files influence the maintainability and scalability of a project. Analysis with
suitable example.
In embedded firmware, the strategic use of pre-processor directives (e.g., #define, #ifdef,
#include) and source file organization (.c/.h files) is critical for managing complexity, ensuring
long-term maintenance, and allowing projects to scale. They transform code from a static,
fragile blob into a modular, configurable system.
1. Influence on Maintainability
Maintainability refers to how easily code can be understood, debugged, and modified without
introducing new errors.
Pre-processor Directives (#define, #ifdef):
o Symbolic Constants: Using #define or typedef to define hardware register addresses or
configuration values instead of hardcoding numbers allows for easy changes.
o Conditional Debugging: #ifdef DEBUG allows developers to include logging or testing code
without affecting the final production image size.
o Code Portability: Conditional compilation can swap hardware drivers, enabling the same
source code to be maintained for different microcontrollers.
Source Files (.c/.h):
o Modular Separation: Dividing code into functional units (e.g., sensor.c, motor.c, main.c)
isolates faults, making debugging faster.
o Header Guarding: #ifndef MODULE_H / #define MODULE_H prevents double-definition
errors, crucial for large projects.
2. Influence on Scalability
Scalability refers to the project's ability to grow in features, support new hardware, or handle
increased data volumes.
Pre-processor Directives:
o Feature Management: #ifdef ENABLE_BLUETOOTH enables adding new features to a
project without altering existing, tested code.
o Hardware Variants: A single repository can support different hardware variants (e.g., Lite,
Pro) by changing a single #define in a config file.
Source Files:
o Component Reuse: Well-structured header files (.h) allow components developed for one
project (e.g., an I2C driver) to be dropped into a new project, reducing development time.
o Parallel Development: Multiple engineers can work on different .c files simultaneously
without constant file conflicts.
Analysis with Suitable Example: Intelligent Sensor Module
Imagine an embedded project for a sensor unit that needs to work with either a temperature
sensor or a pressure sensor and have a "Debug" mode.
A. Poor Implementation (Low Maintenance/Scalability)
Everything is in main.c.
c
// main.c
void main() {
// Hardcoded sensor address
char data = ReadRegister(0x40);
if (data > 50) { // Hardcoded threshold
TurnOnLED(); // Specific to this hardware
}
// Hardcoded UART config
UART_Init(115200);
}
Use code with caution.
Issue: To change the sensor or the threshold, you must edit main.c. To port this to a new board,
you must create a new file.
B. Good Implementation (High Maintenance/Scalability)
Utilizing source files and preprocessor directives. [1]
1. config.h (Centralized Configuration)
c
#ifndef CONFIG_H
#define CONFIG_H
// Feature toggles
#define USE_TEMPERATURE_SENSOR
#define DEBUG_MODE
// Configuration Constants
#define SENSOR_THRESHOLD 50
#define UART_BAUD_RATE 115200
#endif
Use code with caution.
2. sensor.c (Hardware Abstraction)
c
#include "sensor.h"
#include "config.h"
int ReadSensor() {
#ifdef USE_TEMPERATURE_SENSOR
return ReadTemp(0x40);
#else
return ReadPressure(0x50);
#endif
}
Use code with caution.
3. main.c (Logical Flow)
c
#include "config.h"
#include "sensor.h"
void main() {
InitSystem();
#ifdef DEBUG_MODE
printf("System Initialized\n");
#endif
while(1) {
if (ReadSensor() > SENSOR_THRESHOLD) {
// Action
}
}
}
Use code with caution.
Impact Summary
Technique Effect on Maintainability Effect on Scalability
Changes occur in one place, reducing
#define Easy adaptation for new parameters.
bugs.
#ifdef Allows clean, safe debugging. Enables feature toggling (scaling up).
#include Promotes modular, readable code. Enables code reuse across projects.
Allows team-based, parallel
Source Files Isolate bugs and simplify testing.
development.
By using these methods, a project can grow from a simple 8-bit application to a complex, multi-
component 32-bit system without becoming unmanageable
10a. Explain the different multitasking models in the operating system context.
Multitasking in operating systems allows multiple tasks to share CPU resources, creating the
illusion of parallel execution. The main models are pre-emptive multitasking (OS manages
task switching via time-slots) and cooperative multitasking (tasks yield control voluntarily). It
boosts efficiency and responsiveness.
1. Pre-emptive Multitasking
In this model, the operating system holds full control and can interrupt (pre-empt) a currently
running process to give CPU time to another process based on priority or time limits (time
slicing).
Mechanism: The OS scheduler assigns a specific time quantum (time slot) to each process. If a
process exceeds this time, the OS pre-empts it, saves its context, and switches to the next task.
Examples: Modern desktop systems like Windows NT/95 and later, macOS, and Linux use this
model for stability and responsiveness.
Pros: Prevents a single task from monopolizing the CPU; ensures system responsiveness.
2. Cooperative (Non-Pre-emptive) Multitasking
In this model, the currently running task must voluntarily yield control of the CPU to let other
tasks run.
Mechanism: The OS waits for a process to complete its task or voluntarily yield control back to
the system, allowing other processes to execute.
Examples: Older systems like Windows 3.x and older MacOS.
Pros/Cons: Requires less overhead for context switching, but a misbehaving or hung
application can crash the entire system because it refuses to release the CPU.
3. Hybrid Multitasking Some modern systems use a hybrid approach, combining pre-emptive
techniques for high-priority tasks with cooperative multitasking for specialized applications to
optimize both efficiency and resource distribution.
Key Concepts in Multitasking
Context Switching: The mechanism of saving the state of the current task and loading the state
of the next task so that execution can resume later.
Time Sharing: A mechanism where CPU time is divided among multiple tasks in a round-robin
fashion, ensuring each gets a slice of processing time.
Process vs. Thread-Based: Process-based multitasking runs multiple independent applications
simultaneously, while thread-based multitasking runs multiple threads within a single process.
Feature Pre-emptive Cooperative
Control Operating System (Scheduler) Active Task
Switching Forced Voluntary
Stability High Low (one task can halt system)
Use Case Modern Desktops, Servers Legacy/Simple Embedded
Shared data is a cornerstone of task communication in multitasking operating systems and real-
time systems (RTOS), allowing different tasks or processes to efficiently exchange information
by accessing common memory locations. While this mechanism provides high performance and
low latency, it inherently introduces risks of data corruption if multiple tasks attempt to read and
write to the same memory space concurrently without proper control. Synchronization
mechanisms, such as semaphores, are therefore critical to enforcing orderly access and
maintaining data integrity.
11.b. Explain how semaphores are used to manage resource sharing and
synchronization between tasks.
Semaphores are synchronization tools used in operating systems to manage access to shared
resources and coordinate execution among multiple tasks (threads or processes). Developed by
Edsger Dijkstra, they work as integer variables—effectively counters—that are accessed
exclusively through two atomic (indivisible) operations: Wait (also known as P or down) and
Signal (also known as V or up).
By using these operations, semaphores prevent race conditions and ensure that only allowed
tasks access shared resources at a given time.
How Semaphores Manage Resources (The Mechanism)
A semaphore maintains a counter representing the number of available resources. When a task
needs a resource, it tries to acquire it, and when finished, it releases it.
Initialize: The semaphore is initialized with a positive integer value representing the number of
resource instances (e.g., initialized to \(1\) for one printer, or \(5\) for five database
connections).
Wait() / P() (Acquire):
o Decrements the semaphore value.
o If the resulting value is negative or zero, it means the resource is busy or unavailable. The task
is blocked (placed in a queue) until a signal is received.
o If the value is positive, the task proceeds.
Signal() / V() (Release):
o Increments the semaphore value.
o If there are tasks waiting in the queue, one is awakened and granted access.
Types of Semaphores
1. Binary Semaphore (Mutex): Can only hold values \(0\) or \(1\). It is used for mutual
exclusion to ensure only one task enters a critical section of code at a time.
2. Counting Semaphore: Can hold any non-negative integer. It is used to control access to a pool
of multiple identical resources.
Examples of Semaphore Usage
1. Managing Mutual Exclusion (Binary Semaphore)
When multiple tasks want to write to a single file, only one should write at a time to prevent
corruption.
Init: Semaphore lock = 1.
Task 1: Calls wait(lock). lock becomes \(0\).
Task 2: Calls wait(lock). lock is already \(0\), so Task 2 is blocked.
Task 1: Writes to file, then calls signal(lock). lock becomes \(1\).
Task 2: Is awakened and proceeds to write.
2. Managing Shared Resources (Counting Semaphore)
Imagine a system with 3 printer devices.
Init: Semaphore printers = 3.
When a process needs a printer, it calls wait(printers). If the value was 3, it becomes 2 and the
process uses a printer.
If three processes are already printing, printers = 0. A fourth process calling wait() will be
blocked until a printer is released.
3. Task Synchronization (Ordering)
Semaphores can force a specific order of execution. [
Init: Semaphore sync = 0.
Task B (Receiver): Calls wait(sync) before starting its work. It will immediately block because
sync is \(0\).
Task A (Sender): Performs work, then calls signal(sync).
Task B: Is unblocked and proceeds, ensuring it doesn't run before Task A finishes its initial
setup.