Solutions

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 8

Faculty of Architecture and Engineering,

System Programming in Linux


Asst. Prof. Dr. Tolga YIRTICI
2023-2024 Fall Semester

Exercise Solutions

1) Write a program to display the process id of the program and the parent process id of
the program.

#include <iostream>
#include <unistd.h>

int main() {
pid_t pid = getpid(); // Get the process ID
pid_t parent_pid = getppid(); // Get the parent process ID

std::cout << "Process ID (PID): " << pid << std::endl;


std::cout << "Parent Process ID (PPID): " << parent_pid << std::endl;

return 0;
}

2) What is the command for displaying process id of the programs using command line?
How do you kill a process using command line?

ps aux | grep program_name or pgrep program_name


kill -9 PID

3) Write a program to create a child process and display its PID.

#include <iostream>
#include <unistd.h>

int main() {
pid_t child_pid = fork();

if (child_pid == -1) {
std::cerr << "Fork failed." << std::endl;
return 1;
}

if (child_pid == 0) {
// This code is executed in the child process.
std::cout << "Child Process PID: " << getpid() << std::endl;
} else {
// This code is executed in the parent process.
std::cout << "Parent Process PID: " << getpid() << std::endl;
std::cout << "Child Process PID: " << child_pid << std::endl;
}

return 0;
}

4) Write a program that creates a child process and in that child process, executes the ls
command with the options that shows;

a. All files
b. Readable by humans
c. Shows the symbolic links

#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main() {
pid_t child_pid = fork();

if (child_pid == -1) {
std::cerr << "Fork failed." << std::endl;
return 1;
}

if (child_pid == 0) {
// This code is executed in the child process.

// Define the arguments for the ls command


const char* command = "ls";
const char* option1 = "-la";
const char* option2 = nullptr;

// Execute the "ls" command with specific options using execl


execl("/bin/ls", command, option1, option2);

// If execl fails, an error will be printed to stderr


std::cerr << "Failed to execute ls." << std::endl;
return 1;
} else {
// This code is executed in the parent process.

// Wait for the child process to complete


int status;
waitpid(child_pid, &status, 0);

if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {


std::cout << "Child process (ls) executed successfully." << std::endl;
} else {
std::cerr << "Child process (ls) failed." << std::endl;
}
}

return 0;
}

5) Write a program that generates 1000000 random integers and sums up the odd
numbers that are generated. Use multiple threads to do complete this.

#include <iostream>
#include <vector>
#include <thread>
#include <random>
#include <mutex>

const int NUM_THREADS = 4;


const int NUM_INTEGERS = 1000000;

std::vector<int> randomIntegers(NUM_INTEGERS);
std::mutex sumMutex;
long long oddSum = 0;

void generateRandomIntegers(int start, int end) {


std::random_device rd;
std::default_random_engine generator(rd());
std::uniform_int_distribution<int> distribution(1, 1000);

for (int i = start; i < end; ++i) {


randomIntegers[i] = distribution(generator);
}
}

void sumOddIntegers(int start, int end) {


long long localSum = 0;
for (int i = start; i < end; ++i) {
if (randomIntegers[i] % 2 != 0) {
localSum += randomIntegers[i];
}
}

std::lock_guard<std::mutex> lock(sumMutex);
oddSum += localSum;
}

int main() {
std::vector<std::thread> threads;

for (int i = 0; i < NUM_INTEGERS; ++i) {


randomIntegers[i] = 0;
}

for (int i = 0; i < NUM_THREADS; ++i) {


threads.emplace_back(generateRandomIntegers, i * (NUM_INTEGERS /
NUM_THREADS), (i + 1) * (NUM_INTEGERS / NUM_THREADS));
}

for (std::thread& t : threads) {


t.join();
}

threads.clear();

for (int i = 0; i < NUM_THREADS; ++i) {


threads.emplace_back(sumOddIntegers, i * (NUM_INTEGERS / NUM_THREADS), (i +
* (NUM_INTEGERS / NUM_THREADS));
}

for (std::thread& t : threads) {


t.join();
}

std::cout << "Sum of odd numbers: " << oddSum << std::endl;

return 0;
}

6) Write a C++ program that creates two processes using fork(), where one process prints
"Parent Process" and the other prints "Child Process." Ensure that the parent process
waits for the child process to complete before exiting.

#include <iostream>
#include <unistd.h>
#include <sys/wait.h>

int main() {
pid_t pid = fork();

if (pid < 0) {
std::cerr << "Fork failed." << std::endl;
return 1;
} else if (pid == 0) {
// Child process
std::cout << "Child Process" << std::endl;
} else {
// Parent process
int status;
wait(&status); // Wait for the child process to complete
std::cout << "Parent Process" << std::endl;
}

return 0;
}

7) Write a C++ program that creates a producer-consumer scenario using threads. Create
two threads, one for the producer and one for the consumer. The producer should
generate and store a sequence of integers in a shared buffer, and the consumer should
retrieve and print these integers. Implement synchronization to ensure that the
producer doesn't produce when the buffer is full, and the consumer doesn't consume
when the buffer is empty.

#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>

const int BUFFER_SIZE = 5;


std::vector<int> buffer;
std::mutex mtx;
std::condition_variable producerCV, consumerCV;

void producer() {
for (int i = 1; i <= 10; ++i) {
std::unique_lock<std::mutex> lock(mtx);
producerCV.wait(lock, [] { return buffer.size() < BUFFER_SIZE; });
buffer.push_back(i);
std::cout << "Produced: " << i << std::endl;
consumerCV.notify_one();
}
}
void consumer() {
for (int i = 0; i < 10; ++i) {
std::unique_lock<std::mutex> lock(mtx);
consumerCV.wait(lock, [] { return !buffer.empty(); });
int item = buffer.back();
buffer.pop_back();
std::cout << "Consumed: " << item << std::endl;
producerCV.notify_one();
}
}

int main() {
std::thread producerThread(producer);
std::thread consumerThread(consumer);

producerThread.join();
consumerThread.join();

return 0;
}

8) Write a C++ program that simulates a parallel matrix multiplication using multiple
threads. Create two matrices and multiple worker threads to calculate the product
matrix. Implement synchronization to ensure that each thread operates on distinct
portions of the result matrix without conflicts.

#include <iostream>
#include <vector>
#include <thread>
#include <mutex>

const int N = 3; // Matrix size


const int NUM_THREADS = 2; // Number of worker threads

std::vector<std::vector<int>> matrixA = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};


std::vector<std::vector<int>> matrixB = {{9, 8, 7}, {6, 5, 4}, {3, 2, 1}};
std::vector<std::vector<int>> result(N, std::vector<int>(N, 0));
std::mutex mtx;
void matrixMultiply(int startRow, int endRow) {
for (int i = startRow; i < endRow; ++i) {
for (int j = 0; j < N; ++j) {
for (int k = 0; k < N; ++k) {
std::lock_guard<std::mutex> lock(mtx);
result[i][j] += matrixA[i][k] * matrixB[k][j];
}
}
}
}

int main() {
std::vector<std::thread> threads;

for (int i = 0; i < NUM_THREADS; ++i) {


int startRow = i * (N / NUM_THREADS);
int endRow = (i + 1) * (N / NUM_THREADS);
threads.emplace_back(matrixMultiply, startRow, endRow);
}

for (std::thread& t : threads) {


t.join();
}

// Print the result matrix


for (const auto& row : result) {
for (int val : row) {
std::cout << val << " ";
}
std::cout << std::endl;
}

return 0;
}

You might also like