Uploaded by Muhammad Anas

OS Assignment 3

advertisement
Name: Khawaja Tahir Zia
Roll No.: 451365
Section: B
Name: Muhammad Anas
Roll no.: 452581
Section: B
OS Assignment 3
Q1:
#include <iostream>
#include <pthread.h>
#include <chrono>
#include <mutex>
#include <atomic>
using namespace std;
typedef struct thread_arg {
int start_index;
int end_index;
} thread_arg;
void* runner(void* param);
void single_thread();
void two_threads();
void three_threads();
void four_threads();
atomic<bool> stop = false;
string passwd = "99999"; // Password of length 5
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; //
Possible characters in password
int main()
{
single_thread();
// two_threads();
// three_threads();
// four_threads();
}
// Thread Function to guess password
void* runner(void* param)
{
thread_arg *th_arg = (thread_arg *) param; // Work Division
string attempt = "aaaaa";
// Check all combinations
for (int h = th_arg->start_index; h <= th_arg->end_index; h++)
{
attempt[0] = alphabet[h];
for (int i = 0; i < alphabet.length(); i++)
{
attempt[1] = alphabet[i];
for (int j = 0; j < alphabet.length(); j++)
{
attempt[2] = alphabet[j];
for (int k = 0; k < alphabet.length(); k++)
{
attempt[3] = alphabet[k];
for (int l = 0; l < alphabet.length(); l++)
{
attempt[4] = alphabet[l];
if (attempt == passwd)
{
cout << "Match" << endl;
stop = true;
return NULL;
}
if (stop == true)
{
return NULL;
}
}
}
}
}
}
delete th_arg;
return NULL;
}
// Single sequential execution
void single_thread()
{
thread_arg th_arg;
th_arg.start_index = 0;
th_arg.end_index = 61;
auto start = chrono::steady_clock::now();
string attempt = "aaaaa";
bool flag = true;
// Check all combinations
for (int h = th_arg.start_index; h <= th_arg.end_index && flag; h++)
{
attempt[0] = alphabet[h];
for (int i = 0; i < alphabet.length() && flag; i++)
{
attempt[1] = alphabet[i];
for (int j = 0; j < alphabet.length() && flag; j++)
{
attempt[2] = alphabet[j];
for (int k = 0; k < alphabet.length() && flag; k++)
{
attempt[3] = alphabet[k];
for (int l = 0; l < alphabet.length(); l++)
{
attempt[4] = alphabet[l];
if (attempt == passwd) // Stop if match
{
cout << "Match" << endl;
flag = false;
break;
}
}
}
}
}
}
auto end = chrono::steady_clock::now();
cout << "Single Thread: " << chrono::duration_cast<chrono::milliseconds>(end-start).count() /
(float)1000 << " seconds\n";
return;
}
void two_threads()
{
// Divide work and create threads
auto start = chrono::steady_clock::now();
pthread_t workers[2];
thread_arg *arg = new thread_arg;
arg->start_index = 0;
arg->end_index = 30;
pthread_create(&workers[0], NULL, runner, arg);
arg = new thread_arg;
arg->start_index = 31;
arg->end_index = 61;
pthread_create(&workers[1], NULL, runner, arg);
for (int i = 0; i < 2; i++)
{
pthread_join(workers[i], NULL);
}
auto end = chrono::steady_clock::now();
cout << "Two Threads: " << chrono::duration_cast<chrono::milliseconds>(end-start).count() /
(float)1000 << " seconds\n";
}
void three_threads()
{
auto start = chrono::steady_clock::now();
pthread_t workers[3];
// Divide work and create threads
thread_arg *arg = new thread_arg;
arg->start_index = 0;
arg->end_index = 19;
pthread_create(&workers[0], NULL, runner, arg);
arg = new thread_arg;
arg->start_index = 20;
arg->end_index = 40;
pthread_create(&workers[1], NULL, runner, arg);
arg = new thread_arg;
arg->start_index = 41;
arg->end_index = 61;
pthread_create(&workers[2], NULL, runner, arg);
for (int i = 0; i < 3; i++)
{
pthread_join(workers[i], NULL);
}
auto end = chrono::steady_clock::now();
cout << "Three Threads: " << chrono::duration_cast<chrono::milliseconds>(end-start).count() /
(float)1000 << " seconds\n";
}
void four_threads()
{
auto start = chrono::steady_clock::now();
pthread_t workers[4];
// Divide work and create threads
thread_arg *arg = new thread_arg;
arg->start_index = 0;
arg->end_index = 15;
pthread_create(&workers[0], NULL, runner, arg);
arg = new thread_arg;
arg->start_index = 16;
arg->end_index = 30;
pthread_create(&workers[1], NULL, runner, arg);
arg = new thread_arg;
arg->start_index = 31;
arg->end_index = 45;
pthread_create(&workers[2], NULL, runner, arg);
arg = new thread_arg;
arg->start_index = 46;
arg->end_index = 61;
pthread_create(&workers[3], NULL, runner, arg);
for (int i = 0; i < 4; i++)
{
pthread_join(workers[i], NULL);
}
auto end = chrono::steady_clock::now();
cout << "Four Threads: " << chrono::duration_cast<chrono::milliseconds>(end-start).count() /
(float)1000 << " seconds\n";
}
Q2:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define SIZE 9
#define NUM_OF_THREADS 9
#define NUM_OF_GRIDS 9
int sudoku[SIZE][SIZE] = {{6,2,4,5,3,9,1,8,7},
{5,1,9,7,2,8,6,3,4},
{8,3,7,6,1,4,2,9,5},
{1,4,3,8,6,5,7,2,9},
{9,5,8,2,4,7,3,6,1},
{7,6,2,3,9,1,4,5,8},
{3,7,1,9,5,6,8,4,2},
{4,9,6,1,8,2,5,7,3},
{2,8,5,4,7,3,9,1,6}};
int col_status[SIZE], row_status[SIZE], grid_status[SIZE];
typedef struct Grid {
int i;
int j;
} Grid;
int row_checker(void *param);
int column_checker(void *param);
int grid_checker(void *param);
int main(int argc, char *argv[])
{
// Check Rows - Threads for each Row
pthread_t workers[NUM_OF_THREADS];
pthread_attr_t attrs[NUM_OF_THREADS];
// Create Threads
for (int i = 0; i < NUM_OF_THREADS; i++)
{
pthread_attr_init(&attrs[i]);
pthread_create(&workers[i], &attrs[i], row_checker, i);
}
// Wait for threads
for (int i = 0; i < NUM_OF_THREADS; i++)
{
int status;
pthread_join(workers[i], &status);
row_status[i] = status;
}
for (int i = 0; i < NUM_OF_THREADS; i++)
{
if (row_status[i] == 1)
{
printf("Not Valid\n");
return 0;
}
}
// Check Columns - Threads for each column
// Create Threads
for (int i = 0; i < NUM_OF_THREADS; i++)
{
pthread_attr_init(&attrs[i]);
pthread_create(&workers[i], &attrs[i], column_checker, i);
}
// Wait for threads
for (int i = 0; i < NUM_OF_THREADS; i++)
{
int status;
pthread_join(workers[i], &status);
col_status[i] = status;
}
// Check if any of the columns were invalid
for (int i = 0; i < NUM_OF_THREADS; i++)
{
if (col_status[i] == 1)
{
printf("Not Valid\n");
return 0;
}
}
// Grid Checking - Threads for each grid
// Create threads
Grid *val = malloc(sizeof(Grid));
val->i = 0, val->j = 0;
pthread_attr_init(&attrs[0]);
pthread_create(&workers[0], &attrs[0], grid_checker, val);
val = malloc(sizeof(Grid));
val->i = 0, val->j = 3;
pthread_attr_init(&attrs[1]);
pthread_create(&workers[1], &attrs[1], grid_checker, val);
val = malloc(sizeof(Grid));
val->i = 0, val->j = 6;
pthread_attr_init(&attrs[2]);
pthread_create(&workers[2], &attrs[2], grid_checker, val);
val = malloc(sizeof(Grid));
val->i = 3, val->j = 0;
pthread_attr_init(&attrs[3]);
pthread_create(&workers[3], &attrs[3], grid_checker, val);
val = malloc(sizeof(Grid));
val->i = 3, val->j = 3;
pthread_attr_init(&attrs[4]);
pthread_create(&workers[4], &attrs[4], grid_checker, val);
val = malloc(sizeof(Grid));
val->i = 3, val->j = 6;
pthread_attr_init(&attrs[5]);
pthread_create(&workers[5], &attrs[5], grid_checker, val);
val = malloc(sizeof(Grid));
val->i = 6, val->j = 0;
pthread_attr_init(&attrs[6]);
pthread_create(&workers[6], &attrs[6], grid_checker, val);
val = malloc(sizeof(Grid));
val->i = 6, val->j = 3;
pthread_attr_init(&attrs[7]);
pthread_create(&workers[7], &attrs[7], grid_checker, val);
val = malloc(sizeof(Grid));
val->i = 6, val->j = 6;
pthread_attr_init(&attrs[8]);
pthread_create(&workers[8], &attrs[8], grid_checker, val);
// Wait for threads to join
for (int i = 0; i < NUM_OF_THREADS; i++)
{
int status;
pthread_join(workers[i], &status);
grid_status[i] = status;
}
// Check if any of the threads were invalid
for (int i = 0; i < NUM_OF_THREADS; i++)
{
if (grid_status[i] == 1)
{
printf("Not Valid\n");
return 0;
}
}
printf("Valid\n");
}
int row_checker(void *param)
{
int row = (int)param, flag = 1;
int check[SIZE] = {0,0,0,0,0,0,0,0,0};
for (int j = 0; j < SIZE; j++)
{
check[sudoku[row][j] - 1] = 1; // Check if 1-9 exist in row
}
for (int i = 0; i < SIZE; i++)
{
if (check[i] == 0)
{
flag = 0;
break;
}
}
// Invalid
if (flag == 0)
{
return 1;
}
return 0;
}
int column_checker(void *param)
{
int column = (int)param, flag = 1;
int check[SIZE] = {0,0,0,0,0,0,0,0,0};
for (int i = 0; i < SIZE; i++)
{
check[sudoku[i][column] - 1] = 1; // Check if 1-9 exist in column
}
for (int i = 0; i < SIZE; i++)
{
if (check[i] == 0)
{
flag = 0;
break;
}
}
// Invalid
if (flag == 0)
{
return 1;
}
return 0;
}
int grid_checker(void *param)
{
Grid *grid_index = (Grid *) param;
int flag = 1;
int check[SIZE] = {0,0,0,0,0,0,0,0,0};
for (int i = grid_index->i; i < grid_index->i + 3; i++)
{
for (int j = grid_index->j; j < grid_index->j + 3; j++)
{
check[sudoku[i][j]- 1] = 1; // Check if 1-9 exist in Grid
}
}
free(grid_index);
for (int i = 0; i < SIZE; i++)
{
if (check[i] == 0)
{
flag = 0;
break;
}
}
// Invalid
if (flag == 0)
{
return 1;
}
return 0;
}
Q3:
First Fit
212KB is put in 500KB partition.
417KB is put in 600KB partition.
112KB is put in 288KB partition. (288KB created from 500KB – 212KB = 288KB)
426KB must wait for a partition to free up.
Best Fit
212KB is put in 300KB partition.
417KB is put in 500KB partition.
112KB is put in 200KB partition.
426KB is put in 600KB partition.
Worst Fit
212KB is put in 600KB partition.
417KB is put in 500KB partition.
112KB is put in 388KB partition. (388KB created from 600KB – 212KB = 388KB)
426KB must wait for a partition to free up.
Best fit makes the most efficient use of memory in this example.
Q4:
Question # 5:
Why page sizes are usually powers of 2?
Page sizes are usually powers of 2 because it simplifies memory management and ensures
that memory can be allocated, accessed, and managed efficiently.
When a computer represents an address as a number, it stores it as binary bits. When
converting a linear address to page: offset, it is most efficient to break the address into X
page bits and Y offset bits, rather than perform arithmetic on the address to calculate the
page number and offset ¹. Because each bit position represents a power of 2, splitting an
address between bits results in a page size that is a power of 2.
For example, if the page size is 4 (a power of 2), then 4 in binary is 100, and integer division
and modulus can be computed using special 'shortcuts': you can strip the last two binary
digits to divide, and you can keep only the last two binary digits for modulus. This allows the
memory hardware to extract the page number and byte offset in parallel, without
performing any arithmetic operations [1][2].
Question No 6:
Consider the following page reference string:
1, 2, 3, 4, 1, 2, 3, 7, 6, 3, 2, 1, 2, 3, 6, 2, 1, 5, 6, 2.
How many page faults would occur for the following replacement algorithms, assuming
one, two, three, four, five, six, or seven frames? Remember all frames are initially empty,
so your first unique pages will all cost one fault each.
a) LRU replacement
b) FIFO replacement
c) Optimal replacement
LRU replacement:
FIFO Replacement Algorithm:
Optimal Replacement Algorithm:
Question # 7:
a) Compare symmetric and asymmetric encryption schemes, and discuss the
circumstances under which a distributed system would use one or the other.
Encryption is a technique used to protect data from being deciphered by unauthorized
individuals. There are two main types of encryptions: symmetric and asymmetric.
Symmetric encryption uses a single secret key for both encryption and decryption. The
sender and receiver share the same key, which is used to encrypt and decrypt the data. This
method is faster than asymmetric encryption, but it requires that the sender and receiver
have a secure way to exchange the key.
Asymmetric encryption also known as public key cryptography, uses two keys: a public key
and a private key. The public key is used to encrypt the data, while the private key is used to
decrypt it. The public key can be shared with anyone, while the private key must be kept
secret. This method is slower than symmetric encryption, but it eliminates the need for a
secure key exchange.
In a distributed system, the choice between symmetric and asymmetric encryption depends
on the specific use case. Symmetric encryption is generally used when the sender and
receiver are known to each other and have a secure way to exchange the key. Asymmetric
encryption is used when the sender and receiver are not known to each other or do not
have a secure way to exchange the key.
For example, in a peer-to-peer network where nodes communicate with each other,
asymmetric encryption can be used to establish a secure channel between two nodes that
have never communicated before. Once the secure channel is established, symmetric
encryption can be used for subsequent communication.
In summary, symmetric encryption is faster but requires a secure key exchange, while
asymmetric encryption is slower but eliminates the need for a secure key exchange. The
choice between the two depends on the specific use case in a distributed system [3].
b) Make a list of six security concerns for a bank’s computer system. For each item on
your list, state whether this concern relates to physical, human, or operating-system
security
1. Unauthorized access: This is when someone gains access to the bank's computer
system without permission. This is a human security concern, as it involves people
accessing the system who should not be able to.
2. Malware: Malware is software that is designed to harm a computer system. This is
an operating-system security concern, as it involves protecting the system from
malicious software.
3. Phishing: Phishing is when someone tries to trick a user into giving away sensitive
information, such as login credentials. This is also a human security concern, as it
involves people being tricked into giving away information.
4. Denial of service attacks: Denial of service attacks are when someone tries to make
a computer system unavailable to users. This is an operating-system security
concern, as it involves protecting the system from being overwhelmed by requests.
5. Insider threats: Insider threats are when someone with authorized access to the
system misuses that access. This is a human security concern, as it involves people
who are authorized to access the system abusing that access.
6. Physical theft: Physical theft is when someone steals a computer or other device
that contains sensitive information. This is a physical security concern, and it involves
protecting the physical devices that contain sensitive information. [4]
References:
[1] - stackoverflow.com
[2] - lxadm.com
[3] - techrepublic.com
[4] - alert-software.com
Download