OS File
OS File
BCS401-Operating System
LAB FILE
(2023-24)
TH
4 SEMESTER
Unix:
Hardware Requirements: UNIX-like systems have traditionally been known for their flexibility
to run on various hardware architectures, including x86, ARM, SPARC, and others. The hardware
requirements can vary significantly depending on the specific UNIX variant and its intended use
case. Generally, UNIX systems can run on relatively modest hardware configurations, making
them suitable for both low-power devices and high-performance servers.
Software Requirements: UNIX typically requires a compatible kernel along with a set of system
utilities and libraries. Additionally, specific software packages may be needed based on the UNIX
variant and the user's requirements. UNIX systems are highly customizable, allowing users to
install and configure only the software they need, which contributes to their efficiency and
stability.
Linux:
Hardware Requirements: Linux distributions are known for their wide hardware support,
enabling them to run on a vast array of devices, from embedded systems to supercomputers. The
hardware requirements can vary significantly depending on the chosen distribution and the
intended use case. Many modern Linux distributions can run efficiently on relatively low-spec
hardware, making them suitable for older computers and resource-constrained devices.
Software Requirements: Linux requires a compatible kernel, which serves as the core of the
operating system. In addition to the kernel, Linux distributions come with a vast selection of
software packages, including desktop environments, system utilities, development tools, and
server applications. Users have the flexibility to customize their Linux systems by installing or
removing software packages according to their needs.
Windows XP:
Hardware Requirements: Windows XP was released in 2001 and has relatively modest
hardware requirements compared to modern operating systems. The minimum hardware
requirements for Windows XP include a Pentium 233-megahertz (MHz) processor or faster, 64
MB of RAM (although 128 MB or higher is recommended), and at least 1.5 GB of available hard
disk space. However, for optimal performance, higher specifications are recommended,
especially for multitasking and running modern software.
Software Requirements: Windows XP comes with its kernel and a suite of essential system
utilities and drivers. Users can install additional software applications based on their
requirements, such as productivity software, multimedia applications, and security tools.
Windows 7/8:
Hardware Requirements: Windows 7 and 8 have higher hardware requirements compared to
Windows XP due to their more advanced features and improved graphical capabilities. The
recommended hardware specifications for Windows 7 and 8 include a modern CPU (1 GHz or
faster), 1 GB (32-bit) or 2 GB (64-bit) of RAM, and at least 16 GB (32-bit) or 20 GB (64-bit) of
available hard disk space. Higher specifications may be needed for optimal performance,
especially for running demanding software and multitasking.
Software Requirements: Similar to Windows XP, Windows 7 and 8 come with their kernels,
system utilities, and drivers. Users can install additional software applications from the
Windows Store or third-party sources to enhance functionality and productivity.
Practical-II
#include <unistd.h>
#include <stdio.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
// Child process
printf("Child process created.\n");
} else if (pid > 0) {
// Parent process
printf("Parent process. Child PID: %d\n", pid);
} else {
// Error
perror("fork");
}
return 0;
}
2. exec(): Replaces the current process with a new process image. There are variants of the exec()
family, such as execl(), execv(), etc., allowing different ways to pass arguments to the new
process.
#include <unistd.h>
#include <stdio.h>
int main() {
execl("/bin/ls", "ls", "-l", NULL);
perror("exec");
return 0;
}
3. wait(): Suspends execution of the calling process until one of its child processes terminates.
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
// Child process
printf("Child process executing.\n");
sleep(2); // Simulate some work
return 0;
} else if (pid > 0) {
// Parent process
printf("Parent process waiting for child to finish.\n");
wait(NULL);
printf("Child process finished.\n");
} else {
// Error
perror("fork");
}
return 0;
}
ii. File Management:
1. open(): Opens a file and returns a file descriptor.
#include <fcntl.h>
#include <stdio.h>
int main() {
int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
printf("File opened successfully. File Descriptor: %d\n", fd);
close(fd);
return 0;
}
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main() {
int fd = open("example.txt", O_RDONLY);
if (fd == -1) {
perror("open");
return 1;
}
char buffer[100];
ssize_t bytes_read = read(fd, buffer, sizeof(buffer));
if (bytes_read == -1) {
perror("read");
return 1;
}
printf("Read %zd bytes: %s\n", bytes_read, buffer);
close(fd);
return 0;
}
iii. Input/Output System Calls:
1. write(): Writes data from a buffer to a file descriptor.
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
int main() {
int fd = open("output.txt", O_WRONLY | O_CREAT | O_TRUNC,
0644); if (fd == -1) {
perror("open");
return 1;
}
close(fd);
return 0;
}
Practical-III
i. SJF
#include <stdio.h>
waiting_time[0] = 0;
// Print results
printf("Process ID\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (int i = 0; i < n; i++) {
printf("%d\t\t%d\t\t%d\t\t%d\n", processes[i], burst_time[i], waiting_time[i],
turnaround_time[i]);
}
int main() {
int processes[] = {1, 2, 3, 4};
int n = sizeof(processes) / sizeof(processes[0]);
int burst_time[] = {6, 8, 7, 3};
sjf(processes, n, burst_time);
return 0;
}
ii. Priority
#include <stdio.h>
// Swap processes
temp = processes[max_index];
processes[max_index] = processes[i];
processes[i] = temp;
}
waiting_time[0] = 0;
// Calculate waiting time
for (int i = 1; i < n; i++) {
waiting_time[i] = burst_time[i - 1] + waiting_time[i - 1];
total_waiting_time += waiting_time[i];
}
// Print results
printf("Process ID\tBurst Time\tPriority\tWaiting Time\tTurnaround Time\n");
for (int i = 0; i < n; i++) {
printf("%d\t\t%d\t\t%d\t\t%d\t\t%d\n", processes[i], burst_time[i], priority[i],
waiting_time[i], turnaround_time[i]);
}
int main() {
int processes[] = {1, 2, 3, 4};
int n = sizeof(processes) / sizeof(processes[0]);
int burst_time[] = {6, 8, 7, 3};
int priority[] = {2, 1, 3, 4};
return 0;
}
iii. FCFS
#include <stdio.h>
waiting_time[0] = 0;
// Print results
printf("Process ID\tBurst Time\tWaiting Time\tTurnaround Time\n");
for (int i = 0; i < n; i++) {
printf("%d\t\t%d\t\t%d\t\t%d\n", processes[i], burst_time[i], waiting_time[i],
turnaround_time[i]);
}
fcfs(processes, n, burst_time);
return 0;
}
##include <stdio.h>
// Current time
int current_time = 0;
// Process queue 2
while (front2 <= rear2) {
struct Process p = queue2[front2++];
printf("%d\t\t%d\t\t%d\t\t%d\n", p.id, p.burst_time, current_time, current_time
+ quantum);
current_time += quantum;
p.burst_time -= quantum;
if (p.burst_time > 0)
queue2[++rear2] = p; // Requeue the process if burst time remains
else
printf("%d\t\t%d\t\t%d\t\t%d\n", p.id, p.burst_time, current_time,
current_time - p.burst_time);
}
}
}
int main() {
// Example processes
struct Process processes[] = {{1, 6}, {2, 8}, {3, 7}, {4, 3}}; int
n = sizeof(processes) / sizeof(processes[0]);
Practical-IV
#include <stdio.h>
#include <stdlib.h>
struct File {
int start_block;
int length;
};
return start_block;
}
void display_disk_status() {
printf("Disk Status:\n");
for (int i = 0; i < MAX_BLOCKS; i++)
{ printf("%d ", disk[i]);
}
printf("\n\n");
}
int main() {
// Initialize disk blocks (0 for free)
for (int i = 0; i < MAX_BLOCKS; i++)
{ disk[i] = 0;
}
printf("File Allocation:\n");
for (int i = 0; i < num_files; i++) {
int start_block = allocate_contiguous(file_sizes[i]);
if (start_block != -1) {
files[i].start_block = start_block;
files[i].length = file_sizes[i];
printf("File %d: Allocated from block %d to %d\n", i + 1, start_block, start_block + file_sizes[i] - 1);
} else {
printf("File %d: Not enough contiguous free space\n", i + 1);
}
display_disk_status();
}
return 0;
}
(ii).Linked List Allocation:
#include <stdio.h>
#include <stdlib.h>
struct Node {
int block;
struct Node* next;
};
struct File {
struct Node* start;
int length;
};
if (head == NULL)
{ files[file_index].start =
new_node; head = new_node;
} else {
head->next = new_node;
head = head->next;
}
}
files[file_index].length = file_size;
}
void display_linked_list(int file_index) {
struct Node* current = files[file_index].start;
int main() {
// Example file allocation
int file_sizes[] = {5, 3, 4}; // File sizes
int num_files = sizeof(file_sizes) / sizeof(file_sizes[0]);
printf("File Allocation:\n");
for (int i = 0; i < num_files; i++)
{ allocate_linked_list(file_sizes[i], i);
printf("File %d: Allocated blocks: ", i + 1);
display_linked_list(i);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
struct File {
int index_block[INDEX_BLOCK_SIZE];
int length;
};
// Allocate blocks for the file and store block numbers in index block
for (int i = 0; i < num_index_blocks; i++) {
files[file_index].index_block[i] = i + 1; // Assuming blocks start from 1
}
files[file_index].length = file_size;
}
int main() {
// Example file allocation
int file_sizes[] = {25, 35, 15}; // File sizes
int num_files = sizeof(file_sizes) / sizeof(file_sizes[0]);
printf("File Allocation:\n");
for (int i = 0; i < num_files; i++)
{ allocate_indirect_indexing(file_sizes[i], i);
printf("File %d: Allocated blocks: ", i + 1);
display_indirect_indexing(i);
}
return 0;
}
PRACTICAL V
i. Worst-Fit
#include <stdio.h>
#include <stdlib.h>
struct IndexBlock {
int pointers[MAX_BLOCKS];
};
struct File {
int size;
struct IndexBlock* index;
};
if (file->index == NULL) {
file->index = (struct IndexBlock*)malloc(sizeof(struct
IndexBlock)); initializeIndexBlock(file->index);
}
file->size += numBlocks;
}
int main() {
struct File myFile;
myFile.size = 0;
myFile.index = NULL;
free(myFile.index);
return 0;
}
#include <stdio.h>
int main() {
int blockSize[] = {100, 500, 200, 300, 600};
int processSize[] = {212, 417, 112, 426};
int m = sizeof(blockSize) / sizeof(blockSize[0]);
int n = sizeof(processSize) /
sizeof(processSize[0]); bestFit(blockSize, m,
processSize, n);
return 0;
}
#include <stdio.h>
int main() {
int blockSize[] = {100, 500, 200, 300, 600};
int processSize[] = {212, 417, 112, 426};
int m = sizeof(blockSize) / sizeof(blockSize[0]);
int n = sizeof(processSize) /
sizeof(processSize[0]); firstFit(blockSize, m,
processSize, n);
return 0;
}
PRACTICAL VI
Calculation of external and internal fragmentation i. Free space list of blocks from system ii.
List process file from the system
Let’s write a simple C program that demonstrates external and internal fragmentation using contiguous allocation
techniques (Worst-Fit, Best-Fit, and First-Fit). We’ll assume fixed-sized memory blocks for simplicity:
#include <stdio.h>
int main() {
// Example processes
allocateFirstFit(1, 230);
allocateFirstFit(2, 180);
allocateFirstFit(3, 130);
allocateFirstFit(4, 120);
allocateFirstFit(5, 200);
return 0;
}
PRACTICAL VII
Implementation of compaction for the continually changing memory layout and calculate
total movement of data
#include <stdio.h>
int main() {
// Example processes
allocateFirstFit(1, 230);
allocateFirstFit(2, 180);
allocateFirstFit(3, 130);
allocateFirstFit(4, 120);
allocateFirstFit(5, 200);
// Compact memory
compactMemory();
return 0;
}
PRACTICAL VIII
#include <stdio.h>
#include <stdbool.h>
#define MAX_PROCESSES 10
#define MAX_RESOURCES 10
bool resource_allocation_graph[MAX_PROCESSES][MAX_RESOURCES];
int num_processes, num_resources;
int main() {
// Enter processes and resources
printf("Enter the number of processes: ");
scanf("%d", &num_processes);
printf("Enter the number of resources: ");
scanf("%d", &num_resources);
return 0;
}
PRACTICAL IX
// Number of
processes const int P =
5;
// Number of
resources const int R
= 3;
// To store safe
sequence int
safeSeq[P];
found = true;
}
}
}
return true;
}
// Driver code
int main()
{
int processes[] = {0, 1, 2, 3, 4};
// Available instances of
resources int avail[] = {3, 3, 2};
// Resources allocated to
processes int allot[][R] = {{0, 1,
0},
{2, 0, 0},
{3, 0, 2},
{2, 1, 1},
{0, 0, 2}};
PRACTICAL X
Conversion of resource allocation graph (RAG) to wait for graph (WFG) for each type
of method used for storing graph
#include <stdio.h>
int main() {
// Initialize RAG
int rag[P + R][P + R] = {0};
// Initialize WFG
int wfg[P][P];
// Display WFG
printf("Wait-For Graph (WFG):\
n"); displayGraph(wfg);
return 0;
}
RAG
#include <stdio.h>
#include <stdlib.h>
int main() {
// Initialize RAG
Node* rag[P + R] = {NULL};
// Initialize WFG
Node* wfg[P] = {NULL};
// Display WFG
printf("Wait-For Graph (WFG):\
n"); displayGraph(wfg, P);
return 0;
}
#include <stdio.h>
int main() {
// Initialize RAG
int rag[P + R][P + R] = {0};
// Initialize WFG
int wfg[P][P];
// Display WFG
printf("Wait-For Graph (WFG):\
n"); displayGraph(wfg);
return 0;
}
PRACTICAL XI
Implement the solution for Bounded Buffer (producer-consumer)problem using inter process
communication techniques-Semaphores
PRACTICAL XII
#include<stdio.h>
#include<pthread.h>
#include<semaphore.h>
sem_t mutex,writeblock;
int data = 0,rcount = 0;
int main()
{
int i,b;
pthread_t rtid[5],wtid[5];
sem_init(&mutex,0,1);
sem_init(&writeblock,0,1);
for(i=0;i<=2;i++)
{
pthread_create(&wtid[i],NULL,writer,(void *)i);
pthread_create(&rtid[i],NULL,reader,(void *)i);
}
for(i=0;i<=2;i++)
{
pthread_join(wtid[i],NULL);
pthread_join(rtid[i],NULL);
}
return 0;
}