Download as pdf or txt
Download as pdf or txt
You are on page 1of 18

CSEN2253

WEEK – II Processes (I) OS Lab


1. Useful system commands to deal with processes
a) ❯ ps
ps (Process status) can be used to see/list all the running processes.
b) ❯ ps -f
For more information -f (full) can be used along with ps

c) ❯ pidof <proc_name>
For a running program named <proc_name> lists the process ids

Fields described by ps are described as:


UID: User ID that this process belongs to (the person running it)
PID: Process ID
PPID: Parent process ID (the ID of the process that started it)
C: CPU utilization of process
STIME: Process start time
TTY: Terminal type associated with the process
TIME: CPU time is taken by the process
CMD: The command that started this process

There are other options which can be used along with ps command :
-a: Shows information about all users
-x: Shows information about processes without terminals
-u: Shows additional information like -f option
-e: Displays extended information

d) ❯ top
This command is used to show all the running processes within the working environment of
Linux.

e) ❯ kill pid
For processes running in background kill command can be used if it’s pid is known.

f) ❯ bg
A job control command that resumes suspended jobs while keeping them running in the
background

g) ❯ fg
It continues a stopped job by running it in the foreground.

Handed Out: 7th September, 2021


To be turned within: 12th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment II || Page 1 of 10
CSEN2253
OS Lab
2. Creating a process
Creating a process using fork()system call
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main() {
fork();
// fork();
// fork();
printf("hello\n");
return 0;
}

a) Understanding process replication


Question: How many times will hello be printed on uncommenting the lines?

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(){
pid_t pid;
int vble = 101;
printf("Before fork \n");

pid = fork();

printf("pid = %d, process_id = %d, parent_process_id = %d, variable value = %d


\n", pid, getpid(), getppid(), ++vble);//exit(0);
return 0;
}

b) Understanding Memory Space requirements


Question: What value is printed by ++vble and how many times?

Handed Out: 7th September, 2021


To be turned within: 12th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment II || Page 2 of 10
CSEN2253
OS Lab
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

void forkexample() {
pid_t pid;
printf("Before fork \n");
printf("pid = %d, process_id = %d, parent_process_id = %d, \n\n", pid, getpid(),
getppid());

pid = fork(); // replicates current process


printf("After fork \n");

if ( pid == 0) {// child process because return value zero


printf("Hello from Child!\n");
printf("fork = %d, process_id = %d, parent_process_id = %d, \n", pid,
getpid(), getppid());
}

else if (pid > 0) {// parent process because return value non-zero and not -1.
printf("Hello from Parent!\n");
printf("fork = %d, process_id = %d, parent_process_id = %d, \n", pid,
getpid(), getppid());
}

else // return value negative


printf("fork failed");
}

int main()
{
forkexample();
return 0;
}
c) Understanding Parallel Execution of parent and child
fork() On success, the PID of the child process is returned in the parent, and 0 is returned in the child.
On failure, -1 is returned in the parent, no child process is created, and errno is set appropriately.

getpid() returns the process id of the current process

getppid() returns the process id of the parent of the current process

Handed Out: 7th September, 2021


To be turned within: 12th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment II || Page 3 of 10
CSEN2253
OS Lab
3. Orphan Process
Parent does not invoke wait() but executes along with child process. In such a scenario when parent
process terminates before the child process, the child process becomes orphan. Orphan process is a
process that doesn’t have a parent process. This can happen when the parent process terminates due
to some reasons before the completion of the child.
An orphan process gets a new parent. The kernel detects that a process has become orphan and tries
to provide a new parent to the orphan process. In most cases, the new parent is the INIT process, one
with the PID 1. The new parent waits for the completion of the child (orphan process) and then asks the
kernel to clean the PCB of the orphan process.

Parent (pid > 0) Exit

fork

Child (pid > 0)


Orphan

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(){
pid_t pid;
if ((pid = fork()) > 0) { // parent process
printf("I am Parent, my ID %d, I have child with ID: %d, My ParentID = %d\n\n",
getpid(), pid, getppid());
exit(10);
}

else if (pid == 0) { // child process


printf("I am Child, my ID %d, MY PARENT ID = %d\n\n",getpid(),getppid());
//getppid() reports different
sleep(4); // child is waiting for some time. by this time parent process
finishes
printf("I am Child, my ID %d, MY PARENT ID =
%d\n\n",getpid(),getppid());//getppid() reports different
exit(0);
}

else printf("Problem in child creation....\n");


}

Handed Out: 7th September, 2021


To be turned within: 12th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment II || Page 4 of 10
CSEN2253
OS Lab
4. Zombie Process
Parent does not invoke wait() but executes along with child process. In such a scenario when child
process terminates before the parent process, it creates a zombie. Zombie process is that process which
has terminated but whose process control block has not been cleaned up from main memory because
the parent process was not waiting for the child. If there are a large number of zombie processes, their
PCBs IN WORST CASE can occupy the whole RAM.

Parent (pid > 0)

fork

Child (pid > 0)


Exit Zombie

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>

int main(){
pid_t pid;
printf("Parent Process Id: %d\n",getpid());
pid=fork();

if (pid==0) { /* child process */


printf("Child Process Id: %d and my Parent Process Id: %d \n",getpid(),
getppid());
exit(0); // child made to exit
}

//parent process
while(1) { //infinite excution
sleep(1);
printf("\nParent Not invoked Wait()!");
}

/* parent will keep waiting without knowledge of child being made to exit.
as a result it still has an entry in the process table even though it has finished
execution.
This creates a resource leak.*/

return 0;
}

Handed Out: 7th September, 2021


To be turned within: 12th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment II || Page 5 of 10
CSEN2253
OS Lab
5. Shared memory space using vfork()

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int globalvble = 10;

int main() {
pid_t returnval;
int localvble = 20;
int childretval; // from child process: user provided return value
int exitstatus, i=0; // parent process : child's exit status

if ((returnval=vfork()) >= 0) { // including actions to be performed by both


parent and child processes
if (returnval == 0) { // inside child
printf("CHILD:: fork() returnValue = %d, My PID = %d, my Parent's ID =
%d\n",returnval,getpid(), getppid()); //globalvble++; localvble++;
while (i < 10) {
printf("CHILD:: i = %d, local vble = %d, global vble =
%d\n\n",i,localvble,globalvble);
++localvble; ++globalvble;
++i;
}
// system("ps afxj");
printf("CHILD:: Enter an exit value (0 to 255) \n");
scanf("%d", &childretval);
printf("CHILD:: Good Bye\n\n");
//exit(0);
exit(childretval);
}

Handed Out: 7th September, 2021


To be turned within: 12th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment II || Page 6 of 10
CSEN2253
OS Lab
else if (returnval > 0) { // inside parent
sleep(2);
printf("PARENT:: My PID = %d, my Child's PID = %d, my parent's PID = %d
\n",getpid(), returnval, getppid());
printf("PARENT:: i = %d, local vble = %d, global vble =
%d\n\n",i,localvble,globalvble);
while (i < 10) {
printf("PARENT:: local vble = %d, global vble =
%d\n\n",localvble,globalvble);
++localvble; ++globalvble;
++i;
}
wait(&exitstatus);
printf("PARENT:: Child's exit code is -> %d \n",WEXITSTATUS(exitstatus));
printf("PARENT:: Good Bye\n\n");
exit(0); // parent process is terminating -- normally
}
} // outer-if complete....
else {
printf ("Child creation error....");
exit(0);
}
}
Predict the output from the print statements.

Handed Out: 7th September, 2021


To be turned within: 12th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment II || Page 7 of 10
CSEN2253
6. wait() ing by the parent
OS Lab
Can avoid unwanted situations like orphan and/or zombie

Wait
Parent (pid > 0) Parent resume

fork

Child (pid > 0)


Exit

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>

int globalvble = 10;

int main() {
pid_t returnval;
int localvble = 20;
int childretval; // from child process: user provided return value
int exitstatus, i=0; // parent process : child's exit status

if ((returnval=fork()) >= 0) { // including actions to be performed by both


parent and child processes
if (returnval == 0) { // inside child
printf("CHILD:: fork() returnValue = %d, My PID = %d, my Parent's ID =
%d\n",returnval,getpid(), getppid()); //globalvble++; localvble++;
while (i < 10) {
printf("CHILD:: i = %d, local vble = %d, global vble =
%d\n\n",i,localvble,globalvble);
++localvble; ++globalvble;
++i;
}
// system("ps afxj");
printf("CHILD:: Enter an exit value (0 to 255) \n");
scanf("%d", &childretval);
printf("CHILD:: Good Bye\n\n");
//exit(0);
exit(childretval);
}

Handed Out: 7th September, 2021


To be turned within: 12th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment II || Page 8 of 10
CSEN2253
OS Lab
else if (returnval > 0) { // inside parent
sleep(2);
printf("PARENT:: My PID = %d, my Child's PID = %d, my parent's PID = %d
\n",getpid(), returnval, getppid());
printf("PARENT:: i = %d, local vble = %d, global vble =
%d\n\n",i,localvble,globalvble);
while (i < 10) {
printf("PARENT:: local vble = %d, global vble =
%d\n\n",localvble,globalvble);
++localvble; ++globalvble;
++i;
}
sleep(2);
wait(&exitstatus);
printf("PARENT:: Child's exit code is -> %d \n",WEXITSTATUS(exitstatus));
printf("PARENT:: Good Bye\n\n");
exit(0); // parent process is terminating -- normally
}
} // outer-if complete....
else {
printf ("Child creation error....");
exit(0);
}
}
Compare the results of the last two programs and state the reason for their difference in behaviour.

7. Classwork
a) Write a program that accepts an integer num as command line argument. In your program create
two processes. One process should report the num! (Factorial of num). The other process should report
the summation of all factorials till num. [eg: if the argument is 5, one process calculates 5!=120, another
process calculates 1!+2!+3!+4!+5!=153]. Each process should report its pid, ppid, and child id.

b) Write a program to create exactly 3 processes. Each process should then display its own pid along
with the pid of the other two processes and tis relation with the other two processes
[grandparent/parent/child, parent/child-parent/child, parent/child/grandchild]. Take care so that
you don’t have any unwanted orphan/zombie process(es). Each process should report its pid, ppid,
and child id.

Handed Out: 7th September, 2021


To be turned within: 12th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment II || Page 9 of 10
CSEN2253
OS Lab
8. Home Assignment
a) Write a program that accepts two integers (low, high) as command line argument. Create two
processes in your program. The first process should calculate the summation of all integers between
(low, high) as sum_res. The second process should evaluate whether sum_res is prime or not.
Each process should report its pid, ppid, and child id.

b) Write a program to create exactly 3 processes. The program should accept two integers (min and
max) as command line arguments. The first process should report the even and odd numbers within
the range of min-max. The second process should report the prime and non-prime numbers within the
range min-max. The third process should report the summation of even numbers and prime numbers
within the range min-max.

Handed Out: 7th September, 2021


To be turned within: 12th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment II || Page 10 of 10
CSEN2253
WEEK – III Threads (I) OS Lab
1. Recall Basics about Threads
What is a Thread?
A thread is a path of execution within a process. A process can contain multiple threads.

Process vs Thread
The primary difference is that threads within the same process run in a shared memory space, while
processes run in separate memory spaces.
Threads are not independent of one another like processes are, and as a result, threads share with other
threads their code section, data section, and OS resources (like open files and signals).

Advantages of Thread over Process


a) Responsiveness: If the process is divided into multiple threads, if one thread completes its
execution, then its output can be immediately returned.
b) Faster context switch: Context switch time between threads is lower compared to process context
switch. Process context switching requires more overhead from the CPU.
c) Resource sharing: Resources like code, data, and files can be shared among all threads within a
process.
d) Communication: Communication between multiple threads is easier, as the threads shares
common address space. while in process we have to follow some specific communication
technique for communication between two processes.
e) Enhanced throughput: If a process is divided into multiple threads, and each thread function is
considered as one job, then the number of jobs completed per unit of time is increased, thus
increasing the throughput of the system.

Types of Threads
There are two types of threads.
User Level Thread
Kernel Level Thread

Linux Thread Basics


Thread operations include thread creation, termination, synchronization (joins,blocking), scheduling, data
management and process interaction.

A thread does not maintain a list of created threads, nor does it know the thread that created it.
All threads within a process share the same address space.

Threads in the same process share:


Process instructions, Most data, open files (descriptors), signals and signal handlers,
current working directory, User and group id

Each thread has a unique:


Thread ID, set of registers, stack pointer, stack for local variables, return addresses
signal mask, priority, Return value

pthread functions return "0" if OK.

Handed Out: 14th September, 2021


To be turned within: 19th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment III || Page 1 of 8


CSEN2253
2. Creating a thread
OS Lab
Creating a process using pthread_create()function
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

/*thread function definition*/


void* threadFunction(void* args)
{
while(1)
{
sleep(1);
printf("I am threadFunction.\n");
}
}
int main()
{
/*creating thread id*/
pthread_t id;
int ret;

/*creating thread*/
ret=pthread_create(&id,NULL,&threadFunction,NULL);
if(ret==0){
printf("Thread created successfully.\n");
}
else{
printf("Thread not created.\n");
return 0; /*return from main*/
}

while(1)
{
sleep(1);
printf("I am main function.\n");
}

return 0;
}

Handed Out: 14th September, 2021


To be turned within: 19th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment III || Page 2 of 8


CSEN2253
OS Lab
SYNOPSIS
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
Compile and link with -pthread.

DESCRIPTION
The pthread_create() function starts a new thread in the calling process. The new thread starts
execution by invoking start_routine(); arg is passed as the sole argument of start_routine().

ARGUMENTS
thread - returns the thread id. (unsigned long int defined in bits/pthreadtypes.h)
attr - Set to NULL if default thread attributes are used. (else define members of the struct
pthread_attr_t defined in bits/pthreadtypes.h)
Attributes include:
• detached state (joinable? Default: PTHREAD_CREATE_JOINABLE.
Other option: PTHREAD_CREATE_DETACHED)
• scheduling policy (real-time?
PTHREAD_INHERIT_SCHED,PTHREAD_EXPLICIT_SCHED,SCHED_OTHER)
• scheduling parameter
• inheritsched attribute (Default: PTHREAD_EXPLICIT_SCHED Inherit from parent thread:
PTHREAD_INHERIT_SCHED)
• scope (Kernel threads: PTHREAD_SCOPE_SYSTEM User threads: PTHREAD_SCOPE_PROCESS
Pick one or the other not both.)
• guard size
• stack address (See unistd.h and bits/posix_opt.h _POSIX_THREAD_ATTR_STACKADDR)
• stack size (default minimum PTHREAD_STACK_SIZE set in pthread.h)

void * (*start_routine) - pointer to the function to be threaded. Function has a single argument:
pointer to void.
*arg - pointer to argument of function. To pass multiple arguments, send a pointer to a structure.

3. Terminating a Threads
Terminating a process using pthread_exit()function
SYNOPSIS
void pthread_exit(void *retval);
Compile and link with -pthread.

DESCRIPTION
The pthread_exit() function terminates the calling thread and returns a value via retval that (if the
thread is joinable) is available to another thread in the same process that calls pthread_join(3).

Handed Out: 14th September, 2021


To be turned within: 19th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment III || Page 3 of 8


CSEN2253
OS Lab
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

// Let us create a global variable to change it in threads


int g = 0;

// The function to be executed by all threads


void *test_thread(void *arg)
{
// Store the value argument passed to this thread
pthread_t thd_id = (pthread_t)arg;

// Let us create a static variable to observe its changes


static int s = 0;
int t = 0;
// Change static and global variables
++s; ++g; ++t;

// Print the argument, static and global variables


printf("Thread ID: %lu, Static: %d, Global: %d, Local: %d\n", thd_id, ++s,
++g, ++t);
pthread_exit(NULL);
}

int main()
{
int i;
pthread_t tid;

// Let us create three threads


for (i = 0; i < 3; i++)
pthread_create(&tid, NULL, test_thread, (void *)tid);

pthread_exit(NULL);
return 0;
}

Handed Out: 14th September, 2021


To be turned within: 19th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment III || Page 4 of 8


CSEN2253
OS Lab
4. Identifying a Thread
Identifying a thread using pthread_self() function and pthread_t *thread.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

// The function to be executed by all threads


void *test_thread(void *arg)
{
// Store the value argument passed to this thread
pthread_t *thd_id = (pthread_t*)arg;
pthread_t sid;
sid = pthread_self();
printf("Hello from new thread %lu got %lu!\n",sid,*thd_id);
pthread_exit(NULL);
}

int main()
{
int i;
pthread_t tid, sid;

// Let us create three threads


for (i = 0; i < 3; i++) {
if (pthread_create(&tid, NULL, test_thread, (void *)&tid)){
perror ("\npthread_create() error");
exit(1);
}
sid = pthread_self();
printf("\n This is thread (%lu): Created new thread (%lu)... \n", sid,
tid);
}
pthread_exit(NULL);
return 0;
}
SYNOPSIS
pthread_t pthread_self(void);
Compile and link with -pthread.

DESCRIPTION
The pthread_self() function returns the ID of the calling thread. This is the same value that is returned
in *thread in the pthread_create(3) call that created this thread.

Handed Out: 14th September, 2021


To be turned within: 19th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment III || Page 5 of 8


CSEN2253
5. Synchronizing Threads
OS Lab
Using pthread_join(), pthread_equal()

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

// The function to be executed by all threads


void *test_thread(void *arg)
{
// Store the value argument passed to this thread
pthread_t *thd_id = (pthread_t*)arg;
pthread_t sid;
sid = pthread_self();
printf("Hello from new thread %lu got %lu!\n",sid,*thd_id);
//pthread_exit(NULL);
}

int main()
{
int i;
pthread_t tid, sid;

// Let us create three threads


for (i = 0; i < 3; i++) {
if (pthread_create(&tid, NULL, test_thread, (void *)&tid)){
perror ("\npthread_create() error");
exit(1);
}
sid = pthread_self();
printf("\n This is thread (%lu): Created new thread (%lu)... \n", sid,
tid);
}
pthread_exit(NULL);
return 0;
}
SYNOPSIS

int pthread_join(pthread_t thread, void **retval);


Compile and link with -pthread.

Handed Out: 14th September, 2021


To be turned within: 19th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment III || Page 6 of 8


CSEN2253
OS Lab
DESCRIPTION
The pthread_join() function waits for the thread specified by thread to terminate. If that thread has
already terminated, then pthread_join() returns immediately. The thread
specified by thread must be joinable.
If retval is not NULL, then pthread_join() copies the exit status of the target thread (i.e., the value that
the target thread supplied to pthread_exit(3)) into the location pointed to by retval. If the target
thread was canceled, then PTHREAD_CANCELED is placed in the location pointed to by retval.
If multiple threads simultaneously try to join with the same thread, the results are undefined. If the
thread calling pthread_join() is canceled, then the target thread will
remain joinable (i.e., it will not be detached).

6. Classwork
a) Write a program that accepts an integer num as command line argument. In your program create
two threads. One thread should report the num! (Factorial of num). The other thread should report the
summation of all factorials till num. [eg: if the argument is 5, one thread calculates 5!=120, another
thread calculates 1!+2!+3!+4!+5!=153]. Each process should report its own id and caller’s id. When a
thread ends, it should display meaningful message.

b) Write a program that accepts two integers (low, high) as command line argument. Create two
threads in your program. The first thread should calculate the summation of all integers between (low,
high) as sum_res. The second thread should evaluate whether sum_res is prime or not. Each process
should report its own id and caller’s id. When a thread ends, it should display meaningful message.

7. Home Assignment
a) Write a multi-threaded program such that it creates 10 more threads. Each thread should print Hello
from nth thread along with the argument received from the main thread. Each thread should return
its own id and a unique value to main using pthread_exit(). Main thread should be able to print
this returned message identifying which thread ended within its own thread.
i) Synchronize it such that all 10 threads are created first and then all of them are terminated.
Eg: 0 MAIN
1 created
2 created
3 created
.
.
.
.
10 created
1 ended
2 ended
3 ended
.
.
.
.
10 ended
MAIN ended

Handed Out: 14th September, 2021


To be turned within: 19th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment III || Page 7 of 8


CSEN2253
ii)
OS Lab
Synchronize it such that one is created and ends before the next one is created (till all 10 are
created and terminated)
Eg: 0 MAIN
1 created
1 ended
2 created
2 ended
3 created
3 ended
.
.
.
.
10 created
10 ended
MAIN ended

iii) Synchronize it such that a pair is created at a time and terminated in the reverse order of how
they were created.

Eg: 0 MAIN
1 created
2 created
2 ended
1 ended
3 created
4 created
4 ended
3 ended
.
.
.
.
9 created
10 created
10 ended
9 ended
MAIN ended

Handed Out: 14th September, 2021


To be turned within: 19th September, 2021 Dept. of CSE, HIT-K, Spring 2021

Assignment III || Page 8 of 8

You might also like