You are on page 1of 10

Ho Chi Minh University of Technology

Faculty of Computer Science and Engineering

Operating Systems
Laboratory Report 2
April 17, 2021

Student’s name: Vu Hoang Hai


Student ID: 1952669
Class: CC01 - CO2017
Date Performed: March 27, 2021
Instructor: Le Thanh Van

1 Processes’ memory regions

1.1 Process insiders


Given the following C program:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int glo_init_data = 99;


int glo_noninit_data;

void print_func () {
int local_data = 9;
printf("Process ID = %d\n", getpid());
printf("Addresses of the process: \n");
printf("1. glo_init_data = %p\n", &glo_init_data);
printf("2. glo_noninit_data = %p\n", &glo_noninit_data);
printf("3. print_func() = %p\n", &print_func);
printf("4. local_data = %p\n", &local_data);
}

int main(int argc, char **argv) {


print_func();
return 0;
}

1
Executing the compiled program on UNIX yields the following:

1.2 Dynamic allocation on UNIX/LINUX system

Given the following C program:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char* argv[]) {


size_t MB = 1024*1024;
size_t maxMB = 0;
void *ptr = NULL;

do {
if(ptr != NULL) {
printf("Bytes of memory checked = %zi \n", maxMB);
memset(ptr, 0, maxMB);
}

maxMB += MB;
ptr = malloc(maxMB);

} while (ptr != NULL);

return 0;
}

2
Executing the compiled program on UNIX yields the following:

1.3 brk() and sbrk() system calls

Adding the following snippet of simple_malloc() function to the above program to


implement a custom malloc() prototype:
void* simple_malloc(size_t size) {
void *p;
p = sbrk(0);

if (sbrk(size) == (void*)-1)
return NULL;
return p;
}

3
2 Process Control Block

2.1 Questions
Given the following C program:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>

int value = 19;

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

if (pid == 0) {
value += 15;
/* A */ printf("PID of child process = %d\n", getpid());
return 0;
}
else if (pid > 0) {
/* B */ wait(NULL);
/* C */ printf("Parent value = %d\n", value);
return 0;
}

a) What will the output be at line A? Does this value not change for every
process execution?

Executing the compiled program on UNIX yields the following:

4
It can be seen that the produced output of line A is the process ID of the child
process when it is successfully created.
This value changes for every execution when fork() is called. This is because the
value in particular is unique to that child process and does not match any active
process ID.

b) What will be the output at line C?

The output at line C will be the parent process’ global value that originally forked
the child process, in this case, the parent process will be holding the value 19.

c) Remove line B from the program. Observe the displayed result onto
screen and give remarks.

When line B is removed from the program, the following is displayed:

The result shows that the printf() function has different order of output. In fact,
two possible outputs could occur when forking a child process. This is because

5
without the wait(NULL), both the parent and child process run concurrently and
the OS will randomly give control to either process.
With the wait(NULL) in place, the parent must wait for the child process to finish
before resuming back to whatever it is doing.

2.2 Write a C program that reads integers listed in this file and stores
them in an array (or linked list). The program then uses the fork()
system call to create a child process.
– Programming code:

6
– Compilation:

2.3 Write a program that uses fork() system calls to create processes whose
relationship is similar to the one showed in the figure.

7
– Programming code:

8
9
– Compilation:

The above program generates the children of processes in accordance to their


parents. Each indentation is a level of the given tree process.
After the last initialization of the last child, the processes start to terminate from
the leaves to the root of the tree.

10

You might also like