0% found this document useful (0 votes)
4 views21 pages

OS practical Notes

The document provides a comprehensive guide to various Linux commands and system calls related to file and directory manipulation. It covers commands such as ls, cd, mkdir, and system calls like open, read, write, and lseek, along with examples for each. Additionally, it includes code snippets demonstrating the usage of these commands and system calls in C programming.

Uploaded by

yashanbhullar2
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views21 pages

OS practical Notes

The document provides a comprehensive guide to various Linux commands and system calls related to file and directory manipulation. It covers commands such as ls, cd, mkdir, and system calls like open, read, write, and lseek, along with examples for each. Additionally, it includes code snippets demonstrating the usage of these commands and system calls in C programming.

Uploaded by

yashanbhullar2
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 21

Experiment -1 Linux Commands

1. ls (List Directory Contents)

 Purpose: Lists files and directories.


 Example:
o ls — List files.
o ls -l — Detailed list (permissions, size, etc.).

2. cd (Change Directory)

 Purpose: Changes the current directory.


 Example:
o cd Documents — Go to the "Documents" directory.
o cd .. — Move up one directory level.

3. pwd (Print Working Directory)

 Purpose: Displays the full path of the current directory.


 Example:
o pwd — Shows current directory path (e.g., /home/user/Documents).

4. mkdir (Make Directory)

 Purpose: Creates a new directory.


 Example:
o mkdir new_folder — Creates "new_folder".

5. rmdir (Remove Directory)

 Purpose: Removes an empty directory.


 Example:
o rmdir old_folder — Deletes "old_folder" if empty.

6. cp (Copy)

 Purpose: Copies files or directories.


 Example:
o cp file1.txt file2.txt — Copies "file1.txt" to "file2.txt".

7. mv (Move or Rename)

 Purpose: Moves or renames files.


 Example:
o mv file1.txt new_folder/ — Moves "file1.txt" to "new_folder".
o mv oldname.txt newname.txt — Renames a file.

8. rm (Remove)

 Purpose: Removes files or directories.


 Example:
o rm file.txt — Deletes "file.txt".
o rm -r folder — Deletes a folder and its contents.

9. touch (Create Empty File)


 Purpose: Creates an empty file or updates the timestamp.
 Example:
o touch newfile.txt — Creates "newfile.txt".

10. cat (Concatenate and Display)

 Purpose: Displays file content.


 Example:
o cat file.txt — Shows content of "file.txt".

11. head (Display Beginning of File)

 Purpose: Shows the first few lines of a file.


 Example:
o head -n 5 file.txt — Displays the first 5 lines.

12. tail (Display End of File)

 Purpose: Displays the last few lines of a file.


 Example:
o tail -n 10 file.txt — Displays the last 10 lines.

13. grep (Search Text in Files)

 Purpose: Searches for a pattern in files.


 Example:
o grep "hello" file.txt — Searches for "hello" in the file.

14. chmod (Change File Permissions)

 Purpose: Changes file permissions.


 Example:
o chmod 755 file.txt — Sets full permissions for the owner, read-execute for others.

15. chown (Change File Ownership)

 Purpose: Changes file ownership.


 Example:
o chown user:group file.txt — Changes ownership of the file.

16. ln (Create Links Between Files)

 Purpose: Creates hard or symbolic links.


 Example:
o ln -s /path/to/file linkname — Creates a symbolic link to a file

3. File Manipulation with System Calls

File Manipulation :- Means there are different types of operation that we can perform in the file.
Example – we create file , delete file, write some content in file , Some update inside the file.

System calls : - System call is a way for a user program to request services from O.S. since user program or instruction cannot directly interact
with hardware or the kernel.
A file descriptor is just a number assigned by the system when you open a file.

How to compile and Run file


Firstly check the GCC installed in your system or not gcc --version

Install the GCC

sudo apt install gcc –y


sudo apt update //for update.

gcc readfile.c -o readfile //Command to compile file

./readfile to executable file.

Gcc Calls the GNU C Compiler to compile C programs.


readfile.c The source code file (your C program).
-o Tells the compiler to specify an output file name.
readfile The name of the output executable file.

Here some common system calls :

1. open() – Open a File

Purpose: Opens a file for reading, writing, or both.

Example:

Int fd = open("file.txt", O_CREAT | O_WRONLY, 0644);

O_CREAT → Create the file if it doesn’t exist.

O_WRONLY → Open for writing only.

0644 → Set file permissions.

2. close() – Close a File

Purpose: Closes an open file to free system resources.

Example:

close(fd);

Always close files after use to prevent memory issues.

3. read() – Read Data from a File

Purpose: Reads data from a file into memory.

Example:

char buffer[100];
read(fd, buffer, 100);

Reads 100 bytes from fd (file descriptor) into buffer.


4. write() – Write Data to a File

Purpose: Writes data from memory to a file.

Example:

write(fd, "Hello, System Call!", 20);

Writes 20 characters to the file.

5. lseek() – Move the File Pointer

Purpose: Moves the reading/writing position in a file.

Example:

lseek(fd, 10, SEEK_SET);

Moves 10 bytes forward from the start of the file.

Useful for editing specific parts of a file.

6. unlink() – Delete a File


Purpose: Removes a file from the system.
Example:

unlink("file.txt");

Deletes file.txt permanently.

7. rename() – Rename a File

Purpose: Changes a file’s name.

Example:

rename("old.txt", "new.txt");

Renames old.txt to new.txt


8. stat() – Get File Information

Purpose: Fetches file details like size, permissions, and last modified time.

Example:

struct stat fileStat;


stat("file.txt", &fileStat);
printf("File size: %ld bytes\n", fileStat.st_size);

Shows the file size in bytes.

9. chmod() – Change File Permissions

Purpose: Modifies who can read, write, or execute a file.


Example:

chmod("file.txt", 0777);

Makes file.txt readable, writable, and executable by everyone.

10. chown() – Change File Owner

Purpose: Changes the owner of a file.

Example:

chown("file.txt", 1001, 1001);

Changes owner and group to user ID 1001.

11. link() – Create a Hard Link

Purpose: Creates another name (link) for a file.

Example:

link("file.txt", "file_link.txt");

Now file_link.txt points to the same data as file.txt.


12. symlink() – Create a Soft Link (Shortcut)

Purpose: Creates a symbolic link (shortcut) to another file.

Example:

symlink("file.txt", "file_symlink.txt");

file_symlink.txt behaves like a shortcut to file.txt.

Example for open , create file and write in system call

#include <fcntl.h> // For open()


#include <unistd.h> // For read(), write(), close()

int main() {
int fd = open("file.txt", O_CREAT | O_WRONLY, 0644); open() is used to create or . open a file.
"file.txt" → The name of the file.
O_CREAT → Create the file if it doesn’t exist .

O_WRONLY → Opens the file in write-only mode (no reading

0644 → File permission //

write(fd, "Hello, System Call!\n", 21); write(fd, buffer, size) writes data to the file.
fd → File descriptor (the file
to write to).
"Hello, System Call!\n" →
The text to write.
21 → The number of bytes
(characters) to write, including \n.
close(fd); // Close file
return 0;
}

Example read the file in system calls.


#include<stdio.h>
#include <fcntl.h> // For open()
#include <unistd.h> // For read(), write(), close()

int main() {
int fd; // File descriptor

char buffer[100];
// Buffer to store file content, This is an array (temporary storage) to store the file's content while reading.

fd = open("file.txt", O_RDONLY); // Open file in read mode

if (fd < 0) return 1; // If error, exit

// If fd < 0, that means the file couldn’t be opened


return 1; stops the program with an error.

int bytes = read(fd, buffer, sizeof(buffer)); // read(fd, buffer, sizeof(buffer)) reads from the file into buffer.
It stores how many bytes were actually read in the variable bytes.

write(1, buffer, bytes); //write(1, buffer, bytes) writes the read data to the screen.
1 is the file descriptor for the screen to hold data content.

close(fd); // Close file


return 0;
}

OR (If you want to create ,write and read in single program.)

#include <fcntl.h>
#include <unistd.h>

int main() {
int fd;
char buffer[100];

// Create and write to the file


fd = open("file.txt", O_CREAT | O_WRONLY, 0777);
write(fd, "Hello, System Calls!\n", 21);
close(fd);
// Open and read the file
fd = open("file.txt", O_RDONLY);
read(fd, buffer, sizeof(buffer));
write(1, buffer, sizeof(buffer)); // Print to terminal (stdout)
close(fd);
return 0;
}

Example of Lseek

#include <fcntl.h>
#include <unistd.h>

int main() {
int fd = open("file.txt", O_RDWR | O_CREAT, 0644);

//open("file.txt", O_RDWR | O_CREAT, 0644);


 Opens "file.txt".
 O_RDWR → Open for reading and writing.
 O_CREAT → Create the file if it does not exist.
 0644 → Sets file permissions (Owner: Read & Write, Others: Read).
 Returns fd (file descriptor) or -1 if an error occurs //

lseek(fd, 0, SEEK_END); // Move to end of file

//Moves the file pointer to the end of the file.

 lseek(fd, 0, SEEK_END);
 fd → File descriptor of "file.txt".
 0 → Moves 0 bytes from the reference point.
 SEEK_END → Sets position at the end of the file.
 This ensures the next write() appends data at the end.//

write(fd, "XYZ", 3); // Write "XYZ" at the end

// Writes "XYZ" (3 characters) at the end of the file.

 "XYZ" is appended to the existing content.//

close(fd);
return 0;
}

===Delete file In system call=======


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

int main()
{
//FILE *file = fopen("fileum.txt");

unlink("fileum.txt");  file name – “fileum.txt


return 0;
}

====== Rename any file in system call =========

#include <stdio.h>
int main()
{
rename("1.txt", "1new.txt");
return 0;
}

===============Lseek==================
1 Example on lseek.
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int main()
{
int fd;
char buffer[20];

fd = open("testfile.txt", O_RDWR | O_CREAT , 0666);

write(fd, "Hello, world",13);

lseek(fd, 0, SEEK_SET); // lseek() → Moves the file pointer.

read(fd, buffer,13);

lseek(fd,6, SEEK_SET); //SEEK_SET is a constant used in the lseek() function to set the file pointer to a specific position from the beginning of the file.

write(fd, "chatgpt", 7);


close(fd);
return 0;
}
After running the program, testfile.txt will contain:  Hello ,chatgpt

Example -2 on lseek

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
int fd = open("testfile1.txt", O_RDWR | O_CREAT, 0666);
lseek(fd,0, SEEK_END); //SEEK_END → Moves the pointer relative to the end of the file.
write(fd, "Kumar" ,5);
lseek(fd,5,SEEK_END);

close(fd);
return 0;
}

=======Stat========

#include <stdio.h>
#include <sys/stat.h> //#include <sys/stat.h> → Includes file status information functions, such as stat().

int main()
{
struct stat s; //The stat structure stores information about a file, such as:st_size → File size (in bytes).

stat("testfile.txt", &s);
printf("size: %ld bytes\n", s.st_size); //s.st_size contains the file size in bytes
return 0;
}

========chmod============

#include <stdio.h>
#include <sys/stat.h>
int main()
{
chmod("testfile.txt", 0777); // Set full read, write, execute permissions
printf("Permissions changed.\n");
return 0;
}
=====Hard Link (link() system call)=======

#include <unistd.h>

int main() {
link("original.txt", "hardlink.txt");
return 0;
}

=======Symbolic (Soft) Link (symlink() system call)======

#include <unistd.h>

int main() {
symlink("original.txt", "symlink.txt");
return 0;
}

4. Directory Manipulation using System Calls

Function Description Header


mkdir() Create a new directory <sys/stat.h>
rmdir() Remove a directory <unistd.h>
chdir() Change the current working directory <unistd.h>
getcwd() Get the current working directory <unistd.h>
opendir() Open a directory <dirent.h>
readdir() Read a directory <dirent.h>
closedir() Close a directory <dirent.h>

Open and Read Directory (opendir(), readdir(), closedir())

#include <stdio.h>

#include <dirent.h>

int main() {

DIR *d = opendir("."); //that is used to open directory in c.

struct dirent *e; // that is the pointer which is declare e to store directory entry , in c programming.

while ((e = readdir(d)) != NULL)

printf("%s\n", e->d_name); // e->d_name struct dirent member (field) that store file and folder name.

closedir(d);

}
Change Directory (chdir())

#include <unistd.h>

int main() {

chdir("/home");

Create Directory (mkdir())

#include <sys/stat.h>

int main() {

mkdir("newdir", 0777);

Remove Directory (rmdir())

#include <unistd.h>

int main() {

rmdir("newdir");

Get Current Directory (getcwd())

#include <stdio.h>

#include <unistd.h>

int main() {

char path[100];

getcwd(path, sizeof(path));

printf("%s\n", path);

Question - C Program to Demonstrate the Use of getcwd, chdir, and rmdir System Calls.

#include <stdio.h>
#include <unistd.h>
int main() {
char cwd[1024];

// Get current directory, change to /home, and print the new directory
if (getcwd(cwd, sizeof(cwd)) && printf("Current dir: %s\n", cwd) && chdir("/home") == 0 && getcwd(cwd, sizeof(cwd))
&& printf("New dir: %s\n", cwd) == 0 && rmdir("empty_directory") == 0) {
printf("Removed empty directory.\n");
} else {
printf("Error occurred.\n");
}
return 0;
}

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

int main() {
char cwd[1024];

// Get current directory, change to /home, and print the new directory
if (getcwd(cwd, sizeof(cwd)) && printf("Current dir: %s\n", cwd) && chdir("/home") == 0 && getcwd(cwd, sizeof(cwd))
&& printf("New dir: %s\n", cwd) == 0 && rmdir("empty_directory") == 0) {
printf("Removed empty directory.\n");
} else {
printf("Error occurred.\n");
}

return 0;
}
#include <stdio.h>
#include <unistd.h>

int main() {
char cwd[1024];

// Get current directory, change to /home, and print the new directory
if (getcwd(cwd, sizeof(cwd)) && printf("Current dir: %s\n", cwd) && chdir("/home") == 0 && getcwd(cwd, sizeof(cwd))
&& printf("New dir: %s\n", cwd) == 0 && rmdir("empty_directory") == 0) {
printf("Removed empty directory.\n");
} else {
printf("Error occurred.\n");
}

return 0;
}

5. Process Management using System Calls

Process Management is an important function of the operating system that helps in creating,exeuting, controlling and ,
executing, controlling and terminating processes.

Process Management is a key function of the OS that controls process creation, execution, and termination.

fork() Creates a new process


exec() Replaces current process with another program
wait() Makes the parent process wait for the child process
exit() Terminates a process
getpid() Returns the Process ID (PID) of the current process
getppid() Returns the Parent Process ID (PPID)
kill() Terminates a process forcefully
nice() Sets process priority

fork()-Creating a New Process


 fork() is used to create a new child process from the parent process.
 The child process is an exact copy of the parent process

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

int main() {
fork(); // Create a child process

printf("Process ID: %d\n", getpid());


return 0;
}

exec() – Replacing a Process


 exec() is used to replace the current process with another program.
 Example: Running the ls -l command from a C program.

#include <stdio.h>
#include <unistd.h>
int main() {
printf("Executing 'ls -l' command..\n");
execl("/bin/ls", "ls", "-l", NULL);
printf("exec() failed!\n"); // This will execute only if exec fails
return 1;
}

getpid() & getppid() – Getting Process ID

 getpid() returns the process ID (PID) of the current process.


 getppid() returns the parent process ID (PPID).

#include <stdio.h>
#include <unistd.h>
int main() {
printf("Current Process ID: %d\n", getpid());
printf("Parent Process ID: %d\n", getppid());
return 0;
}
sleep() – Delaying Execution

 sleep(seconds) pauses execution for the given time.

#include <stdio.h>
#include <unistd.h>
int main() {
printf("Sleeping for 3 seconds...\n");
sleep(3);
printf("Process woke up!\n");
return 0;
}

exit() – Terminating a Process

 exit() is used to terminate a process safely.


 Used to terminate the current process.
 Directly exits the program without sending any signal.

#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Process is terminating...\n");
exit(0); // Successful termination, 0 indicates successful termination.
}

wait() – Waiting for Child Process

 wait() makes the parent wait until the child process finishes execution.
 Without wait(), the parent may finish first, leaving the child as an orphan process.
 If pid > 0, we are in the parent process.
 If pid == 0, we are in the child process.
 If pid < 0, an error occurred (not handled in this code).

#include <stdio.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
int pid = fork();
if(pid>0) //If pid > 0, this is the parent process.
{
wait(NULL); //makes the parent wait for the child to complete before proceeding.
printf("child process completed\n");
}
else
{
printf("child process running\n");
}
return 0;
}

nice() – Changing Process Priority

 nice(value) adjusts the priority of a process.


 Lower value → Higher priority.

#include <stdio.h>
#include <unistd.h>
int main() {
int priority = nice(5); // Increases priority value
printf("New priority: %d\n", priority);
return 0;
}

Kill()
 Used to terminate another process.
 Sends a signal to the target process to stop it.
 Can forcefully terminate a process using kill(pid, SIGKILL);.

#include <signal.h>
#include <unistd.h>
#include <stdio.h>

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

if (pid == 0) { // Child process


printf("Child running with PID: %d\n", getpid());
sleep(5); // Sleep so parent can kill it
printf("Child process exiting...\n");
} else { // Parent process
sleep(2);
printf("Killing child process...\n");
kill(pid, SIGKILL); // Forcefully terminate the child process
}
return 0;
}

6- Creation of Multithreaded Processes using PThread Library

A Thread is smallest unit of execution in a Process. Process can have multiple threads ,Threads can help the program
run faster by doing multiple things at once.

Single thread = One task at a time.

Multiple threads = Multiple tasks at the same time to improve performance by utilizing cpu efficiently. make programs
faster and more responsive.
pthread stands for POSIX (Portable Operating System Interface) Threads, which is a library used in C and C++
programming to allow a program to run multiple threads at the same time.

POSIX provides facilities for:

 File operations (like opening, reading, writing files)


 Process management (starting, stopping programs)
 Thread management (running tasks at the same time)
 Input/Output (I/O) operations (like printing things to the screen)

Compilation and execute threads.


gcc pthread_create.c –o pthread_create -pthread

-pthread: This is flag , It tells the compiler to include pthread support when compiling the program.

Where is the Main Thread Created?

When we run a C program, the operating system automatically creates the main thread. This thread runs
inside the main() function. So, in a C program, the main thread is the thread that executes the main()
function.

How to Identify the Main Thread?

We can use the pthread_self() function to check which thread is the main thread.
#include <stdio.h>
#include <pthread.h>

int main() {
printf("Main Thread ID: %lu\n", pthread_self());
return 0;
}
Commonly used library functions related to POSIX threads (pthread) :-
1. pthread_create () - Create a new thread

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

void* thread_function(void* arg) {


printf("Thread is running\n");
return NULL;
}
int main() {
pthread_t thread_id;

// Create the thread


pthread_create(&thread_id, NULL, thread_function, NULL);

printf("Created thread ID: %lu\n", thread_id);


//lu -> print for Unsigned long integer with format specifier.

// Wait for the thread to finish


pthread_join(thread_id, NULL);

printf("Main thread completed\n");

return 0; }
2- pthread_join - Wait for termination of a specific thread
Syntax - int pthread_join(pthread_t thread, void **retval);

3 - pthread_exit()

 pthread_exit() is a command that makes the current thread stop running.


 It doesn't stop the entire program, just the thread that calls it.

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

// Function the thread will run


void* thread_function(void* arg) {
printf("Thread is running!\n");

// Stop the thread here


pthread_exit(NULL);

// This will NOT run


printf("This won't be printed!\n");
}

int main() {
pthread_t thread_id;

// Create the thread


pthread_create(&thread_id, NULL, thread_function, NULL);

// Wait for the thread to finish


pthread_join(thread_id, NULL);

printf("Main thread is done!\n");


return 0;}

4 - pthread_cancel()

It is used to cancel another thread that is running.

It asks the target thread to stop. However, it doesn’t immediately stop the thread, it will stop when
it,reaches a cancellation point (a safe point where it can stop).

#include <pthread.h>
#include <stdio.h>
#include <unistd.h> // For sleep()

void* thread_function(void* arg) { // Function that the thread will run


printf("Thread is running!\n");
sleep(5); // Simulate work by sleeping for 5 seconds
printf("Thread finished!\n");
return NULL;
}

int main() {
pthread_t thread_id;

pthread_create(&thread_id, NULL, thread_function, NULL); // Create the thread

sleep(2); // Wait for 2 seconds

pthread_cancel(thread_id); // Cancel the thread after 2 seconds

pthread_join(thread_id, NULL); // Wait for the thread to finish

printf("Main thread done!\n");


return 0;}

[&thread_id-This is a pointer to a pthread_t variable that will store the thread ID of the newly
created thread.
NULL, it means the thread will use the default attributes.
thread_function -This is a pointer to the function that the new thread will execute.
Null – argument passed to the thread_funtion)]

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

void* thread_function(void* arg) {


static int value = 42; // Static so it stays valid after function returns
return &value; // Return pointer to the value
}

int main() {
pthread_t thread;
int* result;

pthread_create(&thread, NULL, thread_function, NULL);


pthread_join(thread, (void**)&result); // Get pointer from thread

printf("Value returned from thread: %d\n", *result);

return 0;
}

Create a pthread program to find the length of strings passed to the thread function.

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

// Thread function to find string length


void* find_length(void* arg) {
char* str = (char*)arg;
static int len; // static to return pointer
len = strlen(str);
return &len;
}

int main() {
pthread_t thread;
char str[] = "Hello, pthread!";
int* length;

pthread_create(&thread, NULL, find_length, str); // Pass string to thread


pthread_join(thread, (void**)&length); // Get returned length

printf("Length of string: %d\n", *length);


return 0;
}

Experiment 7: Process Synchronization using Semaphore/ Mutex


To compile process synchronization use –lpthread flag.

Synchronization

 Coordination of concurrent threads/processes to ensure orderly execution.


 Prevents inconsistent access to shared resources.

Race Condition

 Occurs when multiple threads/processes access shared resources without proper synchronization.
 Leads to unpredictable or incorrect results due to timing issues.

Semaphore

Definition: synchronization establish between processes or threads, semaphore is abstract data type.
Types:

 Binary Semaphore (0 or 1) – like a mutex.


 Counting Semaphore – allows access to multiple instances.

Functions:

Function Description Syntax


sem_init Initialize semaphore int sem_init(sem_t *sem, int pshared, unsigned int value);
sem_wait Wait (decrement/block) int sem_wait(sem_t *sem);
sem_post Signal (increment/unblock) int sem_post(sem_t *sem);
sem_destroy Destroy semaphore int sem_destroy(sem_t *sem);

Usage: Manages critical sections, prevents race conditions.

Mutex (Mutual Exclusion)

Definition: Ensures exclusive access to a shared resource – synchronization establish between threads.

Types:

 Recursive Mutex: Same thread can lock multiple times.


 Non-recursive Mutex: Deadlocks if locked multiple times by the same thread.

Functions:

Function Description Syntax


pthread_mutex_init Initialize mutex int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr);
pthread_mutex_lock Lock mutex (wait) int pthread_mutex_lock(pthread_mutex_t *mutex);
pthread_mutex_unlock Unlock mutex int pthread_mutex_unlock(pthread_mutex_t *mutex);
pthread_mutex_destroy Destroy mutex int pthread_mutex_destroy(pthread_mutex_t *mutex);

Usage: Ensures mutual exclusion, protects shared data, prevents simultaneous access.

Avoid Race condition using semaphore.

#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>

int x = 0;
sem_t sem; // Declare a semaphore

void* task() {
sem_wait(&sem); // Acquire lock (enter critical section)
x = x + 1;

sem_post(&sem); // Release lock (exit critical section)


return NULL;
}
int main() {
sem_init(&sem, 0, 1); // Initialize semaphore with value 1

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


x = 0; // Reset before each run

pthread_t a, b;
pthread_create(&a, NULL, task, NULL);
pthread_create(&b, NULL, task, NULL);
pthread_join(a, NULL);
pthread_join(b, NULL);

if (x != 2) {
printf("Race condition detected! x = %d\n", x); ;
} else {
printf(" x = %d\n", x);
}
}

sem_destroy(&sem); // Cleanup

return 0;

Simulating race condition

#include<stdio.h>
#include<pthread.h>
int x=0;
void* task()
{
x=x+1;
}
int main()
{
int i;
for (i = 0; i < 1000; i++) {
x = 0; // Reset before each run

pthread_t a,b;
pthread_create(&a,NULL,task,NULL);
pthread_create(&b,NULL,task,NULL);
pthread_join(a,NULL);
pthread_join(b,NULL);
if (x != 2) {
printf("Race condition found x = %d\n", x);
} else {
printf(" x = %d\n", x);
} }
return 0;
}

You might also like