os-lab-notes
os-lab-notes
OS lab notes
OS lab notes
whoami
date
cal
man touch
blue directory
white regular text file
red compressed file
green any file/ directory having complete read, write and execute permissions
linux is powerful commnd oriented OS
touch a{1..100}.txt -- for creating 100 files all together
ls a{1..3}.txt
touch comman is basically used to change the timestamp
cp months.txt f1.txt
rm -rf animals (recursively forcefully delete directory)
Root means any system account that has complete system priviledges, complete
permissions to use that system
Ls –a
Ls –i
Ls –d
Ls –l
Man ls
permissions
admin////root
normal///ordinary
read r
write w
execute x
owner u
group g
others o
chmod (ways of changing permissions)
symbolically
Add +
revoke -
numerically/octal
r4
w2
x1
touch tiger
ls 3l tiger
-rw 3rw 3 r41 (1 means links hardlink, soft link)
Chmod u+x tiger (means giving execute to the owner)
Chmod u-w,g-w tiger (revoke write permission from owner and group)
Chmod ug-w tiger (same as above)
Chmod u+w, o-r (give write permission to owner and revoke read permission from others)
Man write –
It is mandatory to use section number with man like <man 2 lseek=. Because if we write man lseek, it will
give details of lseek as a command, but when we write section number it will show lseek as a system call.
3 types-
0 means read
1 means Display on device, write
anything else error
nano write.c
#include <unistd.h>
Int main()
{
write (1, <lovely=, 6);
}
Ctrl + X , then y, then enter
Gcc write.c (compilation)
./a.out (output)
In case I want to create a customized name for file rather than a.out, we can use the
command:
Gcc –o r read.c {r is the alias for read.c}
So it will execute with < ./r> in place of ./a.out
We work with files, so either we read from file or write into file
Option 1 – I m writing in an existing file with some data written into it.
Option 2- I m creating a new file from scratch
EXisting file will take 2 parameters. 1 is path or file name, 2nd is flag – read or write or both
Vim open.c
File descriptor needs a number to be returned whenever a file opens which returns a
number that is associated with that existing file. Fd is an integer
:wq
In case we try to read from a file and write into a file that does not exist.
Open behaves in two ways… it creates the file that doesn’t exist and then opens it!
Pipe sign means whatever is output of left of pipe will be passed as input to whatever written on right
side of pipe.
Overall open will return negative if file doesn’t exist but flag 0_WRONLY will have value 1 if file doesn’t
exist which will pass to O_CREAT.
In case the file exists, and we are writing into the file, the data will overwrite the previous data.
In order to append to the previous data, we will use the flag O_APPEND.
LSEEK
positions of whence
Fseek(fd,-5, SEEK_END) moves 5 positions from End position Backwards, so we ll always use negative
with SEEK_END.
Now in this program we are reading 10 characters from the file and displaying them on the screen. Then
the cursor will move to 10 position, then again read next 10 characters and display on screen.
Read 10 characters and display it on screen. Use lseek to skip 5 characters and the read next 10
characters.
When process calls fork() system call, a child process is created, means it duplicates the parent process.
Purpose of child process- address space is different, time saving by giving extra task to child, so both
processes are running.
fork() returns
<0 failure
Here at last the parent id is different because it is the id of grandparent as no process stands alone.
Processes can execute in any order. In order to make child execute first, we let the parent process wait
by using wait() function. Now parent will wait for termination until child process executes.
Orphan process:
Zombie
19 May 2022
THREADS
Light weight process means it shares the data and the code of the process in which it runs. So thread
takes fewer resources and utilizes the resources of the process.
Whenever a thread is created it executes a function. A function speeds up the operating speed.
Whenever a function executes a thread executes in parallel, once its done it returns the control back to
the process in which its running.
Every process is an individually entity with its own resources like memory, stack, etc, thread always run
inside a process.
Whenever we create a thread, a system call is there : pthread_create, p stands for POSIX which is a
library. <pthread.h> is the associated header fle.
4th – arguments
After the thread is created we don’t want process to come before thread finishes, so we make the
function main to wait. .. using pthread_join
The pointer value that is returned from the thread and given to the program code, but we usually keep it
NULL.
Programs:
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
void *thread_function()
{
printf("test from function\n");
}
int main(){
pthread_t t1;
pthread_create(&t1,NULL,&thread_function, NULL);
pthread_join(t1,NULL);
return 0;
}
Here pthread_t is a data type. [Every thread has its own stack so when its executing its pointing to some
memory location of the stack and the value is passed by address- call by address concept].
If there are multiple thread then we need to use in function in all threads so that the process will wait
until all threads are executed.
Here both the threads t1 and t2 are executing the same function but twice.
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
#include<pthread.h>
void *thread_function()
{
printf("test from function\n");
//sleep(3);
printf("End of function\n");
}
int main(){
pthread_t t1,t2;
pthread_create(&t1,NULL,&thread_function, NULL);
pthread_create(&t2,NULL,&thread_function, NULL);
pthread_join(t1,NULL);
pthread_join(t2,NULL);
return 0;
}
// Program 3: Program to create threads in linux. Thread prints 0-4 while the main process prints
20-24
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<pthread.h>
Sleep is like delay for the function itself. But wait makes other process to wait and join only after the
current thread completes.
RACE condition It is situation where multiple threads try to manipulate or access shared data,
which lead to inconsistencies.
Considering s as a global shared variable, accessed by both threads.. may lead to inconsistent
results. Now the result will depend on which thread executes first and which thread shows the
result first! So synchronization required.
#include<pthread.h>
#include<stdio.h>
#include<unistd.h>
void *fun1();
void *fun2();
int shared=1; //shared variable
int main()
{
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, fun1, NULL);
pthread_create(&thread2, NULL, fun2, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2,NULL);
printf("Final value of shared is %d\n",shared); //prints the last updated value of shared variable
}
void *fun1()
{
int x;
x=shared;//thread one reads value of shared variable
printf("Thread1 reads the value of shared variable as %d\n",x);
x++; //thread one increments its value
printf("Local updation by Thread1: %d\n",x);
void *fun2()
{
int y;
y=shared;//thread two reads value of shared variable
printf("Thread2 reads the value as %d\n",y);
y--; //thread two increments its value
printf("Local updation by Thread2: %d\n",y);
sleep(1); //thread two is preempted by thread 1
shared=y; //thread one updates the value of shared variable
printf("Value of shared variable updated by Thread2 is: %d\n",shared);
}
SYNCHRONIZATION
#include<pthread.h>
#include<stdio.h>
#include<unistd.h>
void *fun1();
void *fun2();
int shared=1; //shared variable
pthread_mutex_t l; //mutex lock
int main()
{
pthread_mutex_init(&l, NULL); //initializing mutex locks
pthread_t thread1, thread2;
pthread_create(&thread1, NULL, fun1, NULL);
pthread_create(&thread2, NULL, fun2, NULL);
pthread_join(thread1, NULL);
pthread_join(thread2,NULL);
printf("Final value of shared is %d\n",shared); //prints the last updated value of shared variable
}
void *fun1()
{
int x;
printf("Thread1 trying to acquire lock\n");
pthread_mutex_lock(&l); //thread one acquires the lock. Now thread 2 will not be able to
acquire the lock //until it is unlocked by thread 1
printf("Thread1 acquired lock\n");
x=shared;//thread one reads value of shared variable
printf("Thread1 reads the value of shared variable as %d\n",x);
x++; //thread one increments its value
printf("Local updation by Thread1: %d\n",x);
sleep(1); //thread one is preempted by thread 2
shared=x; //thread one updates the value of shared variable
printf("Value of shared variable updated by Thread1 is: %d\n",shared);
pthread_mutex_unlock(&l);
printf("Thread1 released the lock\n");
}
void *fun2()
{
int y;
printf("Thread2 trying to acquire lock\n");
pthread_mutex_lock(&l);
printf("Thread2 acquired lock\n");
y=shared;//thread two reads value of shared variable
printf("Thread2 reads the value as %d\n",y);
y--; //thread two increments its value
printf("Local updation by Thread2: %d\n",y);
sleep(1); //thread two is preempted by thread 1
shared=y; //thread one updates the value of shared variable
printf("Value of shared variable updated by Thread2 is: %d\n",shared);
pthread_mutex_unlock(&l);
printf("Thread2 released the lock\n");
}
Before any executions on shared variable, we will apply the lock using pthread_mutex_lock,
and we pass the lock variable as argument.
Second argument is number of processes sharing a semaphore. Here its 0 because it’s the same
process, no inter-process communication is there.