Sie sind auf Seite 1von 34

EXPERIMENT – 7

AIM: - Implementation of LRU page replacement policy.


THEORY: -
The LRU algorithm keeps track of the order in which pages are accessed and maintains a list
of pages in memory, ordered from most recently accessed to least recently accessed. 
When a new page needs to be loaded into memory, and there is no free space, the algorithm
scans the list from the beginning and replaces the page that was accessed least recently.
In other words, any page that has been inactive for an extended period is more likely to
remain inactive. As a result, it is preferable to replace that page.
The LRU algorithm works on the principle of locality of reference, which states that
programs tend to access a small portion of memory at any given time. Therefore, pages that
were accessed recently are more likely to be accessed again soon than pages that were
accessed a long time ago.
Advantages of LRU
1. Minimizes the number of page faults: The main advantage of the LRU algorithm is
that it is optimal in the sense that it minimizes the number of page faults that occur. 
2. Optimizes memory usage: The LRU algorithm keeps the pages that are most
frequently accessed in memory, which optimizes memory usage and ensures that
frequently used pages are available quickly.
3. Simple implementation: The LRU algorithm is easy to understand and implement. It
requires only a linked list or a priority queue to keep track of the order in which pages
are accessed.
Disadvantages of LRU
1. Computationally Expensive: It can be computationally expensive to maintain the
access history of each page, especially in systems with a large number of pages. 
2. Performance Issue: It may perform poorly in cases where the access patterns of a
program do not follow the principle of locality of reference.
3. Limited scalability: The LRU algorithm may not be scalable for large-scale systems
because it requires maintaining a linked list or priority queue that can become
prohibitively large.

CODE: -
#include <stdio.h>
//user-defined function
int findLRU(int time[], int n)
{
   int i, minimum = time[0], pos = 0;
   for (i = 1; i < n; ++i)
   {
      if (time[i] < minimum)
      {
minimum = time[i];
pos = i;
      }
   }
   return pos;
}
//main function
int main()
{
   int no_of_frames, no_of_pages, frames[10], pages[30], counter = 0, time[10], flag1,
flag2, i, j, pos, faults = 0;
   printf("Enter number of frames: ");
   scanf("%d", &no_of_frames);
   printf("Enter number of pages: ");
   scanf("%d", &no_of_pages);
 
   printf("Enter reference string: ");
   for (i = 0; i < no_of_pages; ++i)
   {
      scanf("%d", &pages[i]);
   }
   for (i = 0; i < no_of_frames; ++i)
   {
      frames[i] = -1;
   }
   for (i = 0; i < no_of_pages; ++i)
   {
      flag1 = flag2 = 0;
      for (j = 0; j < no_of_frames; ++j)
      {
      if (frames[j] == pages[i])
      {
            counter++;
            time[j] = counter;
            flag1 = flag2 = 1;
            break;
      }
      }
      if (flag1 == 0)
      {
      for (j = 0; j < no_of_frames; ++j)
      {
            if (frames[j] == -1)
            {
            counter++;
            faults++;
            frames[j] = pages[i];
            time[j] = counter;
            flag2 = 1;
            break;
            }
      }
      }
      if (flag2 == 0)
      {
      pos = findLRU(time, no_of_frames);
      counter++;
      faults++;
      frames[pos] = pages[i];
      time[pos] = counter;
      }
      printf("\n");
      for (j = 0; j < no_of_frames; ++j)
      {
      printf("%d\t", frames[j]);
      }
   }
   printf("\nTotal Page Faults = %d", faults);
   return 0;
}

OUTPUT: -
EXPERIMENT – 8
AIM: - Implementation of FIFO page replacement policy.
THEORY: -
FIFO which is also known as First In First Out is one of the types of page replacement
algorithm. The FIFO algorithm is used in the paging method for memory management in an
operating system that decides which existing page needs to be replaced in the queue. FIFO
algorithm replaces the oldest (First) page which has been present for the longest time in the
main memory.
Advantages of FIFO Page Replacement Algorithm
 FIFO page replacement algorithm is commonly known for its simplicity.
 FIFO algorithm is much easy to implement as well as understand.
 Small systems can use the FIFO algorithm efficiently.
Disadvantages of FIFO Page Replacement Algorithm
 FIFO algorithm in os uses an additional ==Queue== data structure.
 It suffers from ==Belady's anomaly== problem i.e when the number of page frames
increases, more memory is given to processes, but instead of decreasing, the number
of page faults increases.

CODE: -
#include<stdio.h> 
int main()
{
    int incomingStream[] = {4, 1, 2, 4, 5};
    int pageFaults = 0;
    int frames = 3;
    int m, n, s, pages;
    pages = sizeof(incomingStream)/sizeof(incomingStream[0]);
    printf("Incoming \t Frame 1 \t Frame 2 \t Frame 3");
    int temp[frames];
    for(m = 0; m < frames; m++)
    {
        temp[m] = -1;
    }
for (m = 0; m < pages; m++)
    {
        s = 0;
        for(n = 0; n < frames; n++)
        {
            if(incomingStream[m] == temp[n])
            {
                s++;
                pageFaults--;
            }
        }
        pageFaults++;
        if((pageFaults <= frames) && (s == 0))
        {
            temp[m] = incomingStream[m];
        }
        else if(s == 0)
        {
            temp[(pageFaults - 1) % frames] = incomingStream[m];
        }
        printf("\n");
        printf("%d\t\t\t",incomingStream[m]);
        for(n = 0; n < frames; n++)
        {
            if(temp[n] != -1)
                printf(" %d\t\t\t", temp[n]);
            else
                printf(" - \t\t\t");
        }
    }
    printf("\nTotal Page Faults:\t%d\n", pageFaults);
    return 0;
}

OUTPUT: -
EXPERIMENT – 9
AIM: - Implementation of OPTIMAL page replacement policy.
THEORY: -
The optimal page replacement algorithm is used to reduce these page faults. It uses the
principle that- "when a page is called by the system and it is not available in the frames, the
frame which is not in demand for the longest future time is replaced by the new page".
Advantages Of Optimal Page Replacement Algorithm:
Following are the advantages of the Optimal page replacement algorithm:
 Least page fault occurs as this algorithm replaces the page that is not going to be used
for the longest time in the future.
 In this algorithm, Belady's Anomaly (the number of page faults increases when we
increase the number of frames in secondary storage) does not occur because this
algorithm uses a 'stack-based algorithm' for page replacement.
 Data structure used in this algorithm is easy to understand.
 The page that will not be in demand in the future time is replaced by a new page in
the frames.
Disadvantages Of Optimal Page Replacement Algorithm:
Following are the disadvantages of the optimal page replacement algorithm:
 This algorithm is limited to some specific operating systems. All OS cannot use this.
 Detecting error in this algorithm is not so easy.
 Sometimes, the page which is used recently is replaced which takes much time.
 This algorithm is difficult to implement because the operating system can't predict the
future reference strings.

CODE: -
#include <stdio.h>
// This function checks if current strea item(key) exists in any of the frames or not
int search(int key, int frame_items[], int frame_occupied)
{
    for (int i = 0; i < frame_occupied; i++)
        if (frame_items[i] == key)
            return 1;
    return 0;
}
void printOuterStructure(int max_frames){
    printf("Stream ");
    for(int i = 0; i < max_frames; i++)
        printf("Frame%d ", i+1);
}
void printCurrFrames(int item, int frame_items[], int frame_occupied, int max_frames){
    // print current reference stream item
    printf("\n%d \t\t", item);
    // print frame occupants one by one
    for(int i = 0; i < max_frames; i++){
        if(i < frame_occupied)
            printf("%d \t\t", frame_items[i]);
        else
            printf("- \t\t");
    }
}
// This Function helps in finding frame that will not be used
// for the longest period of time in future in ref_str[0 ... refStrLen - 1]
int predict(int ref_str[], int frame_items[], int refStrLen, int index, int frame_occupied)
{
    // For each current occupant in frame item
    // we try to find the frame item that will not be referenced in 
    // for the longest in future in the upcoming reference string
    int result = -1, farthest = index;
    for (int i = 0; i < frame_occupied; i++) {
        int j;
        for (j = index; j < refStrLen; j++) 
        { 
            if (frame_items[i] == ref_str[j]) 
            { 
                if (j > farthest) {
                    farthest = j;
                    result = i;
                }
                break;
            }
        }
        // If we find a page that is never referenced in future,
        // return it immediately as its the best
        if (j == refStrLen)
            return i;
    }
    // If none of the frame items appear in reference string
    // in the future then we return 0th index. Otherwise we return result
    return (result == -1) ? 0 : result;
}
  
void optimalPage(int ref_str[], int refStrLen, int frame_items[], int max_frames)
{
    // initially none of the frames are occupied
    int frame_occupied = 0;
    printOuterStructure(max_frames);
    // Here we traverse through reference string
    // and check for miss and hit.
    int hits = 0;
    for (int i = 0; i < refStrLen; i++) {
        // If found already in the frame items : HIT
        if (search(ref_str[i], frame_items, frame_occupied)) {
            hits++;
            printCurrFrames(ref_str[i], frame_items, frame_occupied, max_frames);
            continue;
        }
        // If frames are empty then current reference string item in frame
        if (frame_occupied < max_frames){
            frame_items[frame_occupied] = ref_str[i];
            frame_occupied++;
            printCurrFrames(ref_str[i], frame_items, frame_occupied, max_frames);
        }else {
            int pos = predict(ref_str, frame_items, refStrLen, i + 1, frame_occupied);
            frame_items[pos] = ref_str[i];
            printCurrFrames(ref_str[i], frame_items, frame_occupied, max_frames);
        }
    }
    printf("\n\nHits: %d\n", hits);
    printf("Misses: %d", refStrLen - hits);
}
  
// Driver Function
int main()
{
    // int ref_str[] = {9, 0, 5, 1, 0, 3, 0, 4, 1, 3, 0, 3, 1, 3};
    int ref_str[] = {7, 0, 1, 2, 0, 3, 0, 4, 2, 3, 0, 3, 2, 1, 2, 0, 1, 7, 0, 1};
    int refStrLen = sizeof(ref_str) / sizeof(ref_str[0]);
    int max_frames = 3;
    int frame_items[max_frames];
    optimalPage(ref_str, refStrLen, frame_items, max_frames);
    return 0;
}
OUTPUT: -
EXPERIMENT – 10
AIM: - Implementation of FIRST FIT algorithm for memory management.
THEORY: -
First-Fit Allocation is a memory allocation technique used in operating systems to allocate
memory to a process. In First-Fit, the operating system searches through the list of free
blocks of memory, starting from the beginning of the list, until it finds a block that is large
enough to accommodate the memory request from the process. Once a suitable block is
found, the operating system splits the block into two parts: the portion that will be allocated
to the process, and the remaining free block.
Advantages of First-Fit Allocation include its simplicity and efficiency, as the search for a
suitable block of memory can be performed quickly and easily. Additionally, First-Fit can
also help to minimize memory fragmentation, as it tends to allocate memory in larger blocks.
Disadvantages of First-Fit Allocation include poor performance in situations where the
memory is highly fragmented, as the search for a suitable block of memory can become time-
consuming and inefficient. Additionally, First-Fit can also lead to poor memory utilization, as
it may allocate larger blocks of memory than are needed by a process.
Overall, First-Fit Allocation is a widely used memory allocation technique in operating
systems, but its effectiveness may vary depending on the specifics of the system and the
workload being executed.

CODE: -
#include<stdio.h>
void main()
{
int bsize[10], psize[10], bno, pno, flags[10], allocation[10], i, j;
for(i = 0; i < 10; i++)
{
flags[i] = 0;
allocation[i] = -1;
}
printf("Enter no. of blocks: ");
scanf("%d", &bno);
printf("\nEnter size of each block: ");
for(i = 0; i < bno; i++)
scanf("%d", &bsize[i]);
printf("\nEnter no. of processes: ");
scanf("%d", &pno);
printf("\nEnter size of each process: ");
for(i = 0; i < pno; i++)
scanf("%d", &psize[i]);
for(i = 0; i < pno; i++) //allocation as per first fit
for(j = 0; j < bno; j++)
if(flags[j] == 0 && bsize[j] >= psize[i])
{
allocation[j] = i;
flags[j] = 1;
break;
}
//display allocation details
printf("\nBlock no.\tsize\t\tprocess no.\t\tsize");
for(i = 0; i < bno; i++)
{
printf("\n%d\t\t%d\t\t", i+1, bsize[i]);
if(flags[i] == 1)
printf("%d\t\t\t%d",allocation[i]+1,psize[allocation[i]]);
else
printf("Not allocated");
}
}
OUTPUT: -
EXPERIMENT – 11
AIM: - Implementation of BEST FIT algorithm for memory management.
THEORY: -
Best-Fit Allocation is a memory allocation technique used in operating systems to allocate
memory to a process. In Best-Fit, the operating system searches through the list of free blocks
of memory to find the block that is closest in size to the memory request from the process.
Once a suitable block is found, the operating system splits the block into two parts: the
portion that will be allocated to the process, and the remaining free block.
Advantages of Best-Fit Allocation include improved memory utilization, as it allocates the
smallest block of memory that is sufficient to accommodate the memory request from the
process. Additionally, Best-Fit can also help to reduce memory fragmentation, as it tends to
allocate smaller blocks of memory that are less likely to become fragmented.
Disadvantages of Best-Fit Allocation include increased computational overhead, as the
search for the best-fit block of memory can be time-consuming and requires a more complex
search algorithm. Additionally, Best-Fit may also result in increased fragmentation, as it may
leave smaller blocks of memory scattered throughout the memory space.
Overall, Best-Fit Allocation is a widely used memory allocation technique in operating
systems, but its effectiveness may vary depending on the specifics of the system and the
workload being executed.

CODE: -
#include<stdio.h>
void main()
{
int fragment[20],b[20],p[20],i,j,nb,np,temp,lowest=9999;
static int barray[20],parray[20];
printf("\n\t\t\tMemory Management Scheme - Best Fit");
printf("\nEnter the number of blocks:");
scanf("%d",&nb);
printf("Enter the number of processes:");
scanf("%d",&np);
printf("\nEnter the size of the blocks:-\n");
for(i=1;i<=nb;i++)
{
printf("Block no.%d:",i);
scanf("%d",&b[i]);
}
printf("\nEnter the size of the processes :-\n");
for(i=1;i<=np;i++)
{
printf("Process no.%d:",i);
scanf("%d",&p[i]);
}
for(i=1;i<=np;i++)
{
for(j=1;j<=nb;j++)
{
if(barray[j]!=1)
{
temp=b[j]-p[i];
if(temp>=0)
if(lowest>temp)
{
parray[i]=j;
lowest=temp;
}
}
}
fragment[i]=lowest;
barray[parray[i]]=1;
lowest=10000;
}
printf("\nProcess_no\tProcess_size\tBlock_no\tBlock_size\tFragment");
for(i=1;i<=np && parray[i]!=0;i++)
printf("\n%d\t\t%d\t\t%d\t\t%d\t\t%d",i,p[i],parray[i],b[parray[i]],fragment[i]);
}

OUTPUT: -
EXPERIMENT – 12
AIM: - Implementation of WORST FIT algorithm for memory management.
THEORY: -
In this allocation technique, the process traverses the whole memory and always search for
the largest hole/partition, and then the process is placed in that hole/partition. It is a slow
process because it has to traverse the entire memory to search the largest hole. 
Here is an example to understand Worst Fit-Allocation – 

Here Process P1=30K is allocated with the Worst Fit-Allocation technique, so it traverses the
entire memory and selects memory size 400K which is the largest, and hence there is an
internal fragmentation of 370K which is very large and so many other processes can also
utilize this leftover space. 
Advantage:
Since this process chooses the largest hole/partition, therefore there will be large internal
fragmentation. Now, this internal fragmentation will be quite big so that other small
processes can also be placed in that leftover partition. 
Disadvantage:
It is a slow process because it traverses all the partitions in the memory and then selects the
largest partition among all the partitions, which is a time-consuming process.

CODE: -
#include <stdio.h>
void implimentWorstFit(int blockSize[], int blocks, int processSize[], int processes)
{
// This will store the block id of the allocated block to a process
int allocation[processes];
int occupied[blocks];
// initially assigning -1 to all allocation indexes
// means nothing is allocated currently
for(int i = 0; i < processes; i++){
allocation[i] = -1;
}
for(int i = 0; i < blocks; i++){
occupied[i] = 0;
}
// pick each process and find suitable blocks
// according to its size ad assign to it
for (int i=0; i < processes; i++)
{
int indexPlaced = -1;
for(int j = 0; j < blocks; j++)
{
// if not occupied and block size is large enough
if(blockSize[j] >= processSize[i] && !occupied[j])
{
// place it at the first block fit to accomodate process
if (indexPlaced == -1)
indexPlaced = j;
// if any future block is larger than the current block where
// process is placed, change the block and thus indexPlaced
else if (blockSize[indexPlaced] < blockSize[j])
indexPlaced = j;
}
}
// If we were successfully able to find block for the process
if (indexPlaced != -1)
{
// allocate this block j to process p[i]
allocation[i] = indexPlaced;
// make the status of the block as occupied
occupied[indexPlaced] = 1:
// Reduce available memory for the block
blockSize[indexPlaced] -= processSize[i];
}
}
printf("\nProcess No.\tProcess Size\tBlock no.\n");
for (int i = 0; i < processes; i++)
{
printf("%d \t\t\t %d \t\t\t", i+1, processSize[i]);
if (allocation[i] != -1)
printf("%d\n",allocation[i] + 1);
else
printf("Not Allocated\n");
}
}

// Driver code
int main()
{
int blockSize[] = {100, 50, 30, 120, 35};
int processSize[] = {40, 10, 30, 60};
int blocks = sizeof(blockSize)/sizeof(blockSize[0]);
int processes = sizeof(processSize)/sizeof(processSize[0]);
implimentWorstFit(blockSize, blocks, processSize, processes);
return 0;
}

OUTPUT: -

EXPERIMENT – 13
AIM: - Implementation of READER/WRITER problem using semaphore.
THEORY: -
The readers-writers problem relates to an object such as a file that is shared between multiple
processes. Some of these processes are readers i.e., they only want to read the data from the
object and some of the processes are writers i.e. they want to write into the object.
The readers-writers problem is used to manage synchronization so that there are no problems
with the object data. For example - If two readers access the object at the same time there is
no problem. However, if two writers or a reader and writer access the object at the same time,
there may be problems.
To solve this situation, a writer should get exclusive access to an object i.e. when a writer is
accessing the object, no reader or writer may access it. However, multiple readers can access
the object at the same time.
This can be implemented using semaphores. The codes for the reader and writer process in
the reader-writer problem are given as follows −
Reader Process
The code that defines the reader process is given below −
wait (mutex);
rc ++;
if (rc == 1)
wait (wrt);
signal(mutex);
.
. READ THE OBJECT
.
wait(mutex);
rc --;
if (rc == 0)
signal (wrt);
signal(mutex);

Writer Process
The code that defines the writer process is given below:
wait(wrt);
.
. WRITE INTO THE OBJECT
.
signal(wrt);

CODE: -
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>

#define NUM_READERS 5
#define NUM_WRITERS 2

sem_t mutex; // Controls access to the shared resource


sem_t writeBlock; // Ensures exclusive access for writers
int readCount = 0; // Number of readers currently reading

void *reader(void *arg) {


int id = *(int *)arg;
while (1) {
// Reader acquiring mutex to update readCount
sem_wait(&mutex);
readCount++;
if (readCount == 1) {
sem_wait(&writeBlock); // First reader blocks writers
}
sem_post(&mutex);

// Reader reading the shared resource


printf("Reader %d is reading.\n", id);
sleep(rand() % 3 + 1);
// Reader releasing mutex to update readCount
sem_wait(&mutex);
readCount--;
if (readCount == 0) {
sem_post(&writeBlock); // Last reader allows writers
}
sem_post(&mutex);
// Reader done reading
printf("Reader %d finished reading.\n", id);
sleep(rand() % 3 + 1);
}
return NULL;
}
void *writer(void *arg) {
int id = *(int *)arg;
while (1) {
// Writer acquiring writeBlock to get exclusive access
sem_wait(&writeBlock);
// Writer writing to the shared resource
printf("Writer %d is writing.\n", id);
sleep(rand() % 3 + 1);
// Writer done writing
printf("Writer %d finished writing.\n", id);
sleep(rand() % 3 + 1);
// Writer releasing writeBlock to allow other readers/writers
sem_post(&writeBlock);
}

return NULL;
}
int main() {
srand(time(NULL));
// Initialize semaphores
sem_init(&mutex, 0, 1);
sem_init(&writeBlock, 0, 1);
// Create reader threads
pthread_t readers[NUM_READERS];
int reader_ids[NUM_READERS];
for (int i = 0; i < NUM_READERS; ++i) {
reader_ids[i] = i;
pthread_create(&readers[i], NULL, reader, &reader_ids[i]);
}
// Create writer threads
pthread_t writers[NUM_WRITERS];
int writer_ids[NUM_WRITERS];
for (int i = 0; i < NUM_WRITERS; ++i) {
writer_ids[i] = i;
pthread_create(&writers[i], NULL, writer, &writer_ids[i]);
}
// Wait for reader threads to finish
for (int i = 0; i < NUM_READERS; ++i) {
pthread_join(readers[i], NULL);
}
// Wait for writer threads to finish
for (int i = 0; i < NUM_WRITERS; ++i) {
pthread_join(writers[i], NULL);
}

// Destroy semaphores
sem_destroy(&mutex);
sem_destroy(&writeBlock);
return 0;
}

OUTPUT: -

EXPERIMENT – 14
AIM: - Implementation of BANKER’S algorithm for deadlock avoidance.
THEORY: -
The banker’s algorithm is a resource allocation and deadlock avoidance algorithm that tests
for safety by simulating the allocation for the predetermined maximum possible amounts of
all resources, then makes an “s-state” check to test for possible activities, before deciding
whether allocation should be allowed to continue.
Advantages
Following are the essential characteristics of the Banker's algorithm:
1. It contains various resources that meet the requirements of each process.
2. Each process should provide information to the operating system for upcoming
resource requests, the number of resources, and how long the resources will be held.
3. It helps the operating system manage and control process requests for each type of
resource in the computer system.
4. The algorithm has a Max resource attribute that represents indicates each process can
hold the maximum number of resources in a system.
Disadvantages
1. It requires a fixed number of processes, and no additional processes can be started in
the system while executing the process.
2. The algorithm does no longer allows the processes to exchange its maximum needs
while processing its tasks.
3. Each process has to know and state their maximum resource requirement in advance
for the system.
4. The number of resource requests can be granted in a finite time, but the time limit for
allocating the resources is one year.

CODE: -
#include <stdio.h>
int main()
{
// P0, P1, P2, P3, P4 are the Process names here
int n, m, i, j, k;
n = 5; // Number of processes
m = 3; // Number of resources
int alloc[5][3] = { { 0, 1, 0 }, // P0 // Allocation Matrix
{ 2, 0, 0 }, // P1
{ 3, 0, 2 }, // P2
{ 2, 1, 1 }, // P3
{ 0, 0, 2 } }; // P4
int max[5][3] = { { 7, 5, 3 }, // P0 // MAX Matrix
{ 3, 2, 2 }, // P1
{ 9, 0, 2 }, // P2
{ 2, 2, 2 }, // P3
{ 4, 3, 3 } }; // P4
int avail[3] = { 3, 3, 2 }; // Available Resources
int f[n], ans[n], ind = 0;
for (k = 0; k < n; k++) {
f[k] = 0;
}
int need[n][m];
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++)
need[i][j] = max[i][j] - alloc[i][j];
}
int y = 0;
for (k = 0; k < 5; k++) {
for (i = 0; i < n; i++) {
if (f[i] == 0) {
int flag = 0;
for (j = 0; j < m; j++) {
if (need[i][j] > avail[j]){
flag = 1;
break;
}
}
if (flag == 0) {
ans[ind++] = i;
for (y = 0; y < m; y++)
avail[y] += alloc[i][y];
f[i] = 1;
}
}
}
}

int flag = 1;
for(int i=0;i<n;i++)
{
if(f[i]==0)
{
flag=0;
printf("The following system is not safe");
break;
}
}
if(flag==1)
{
printf("Following is the SAFE Sequence\n");
for (i = 0; i < n - 1; i++)
printf(" P%d ->", ans[i]);
printf(" P%d", ans[n - 1]);
}
return (0):
}
OUTPUT: -

EXPERIMENT – 15
AIM: - Implementation of DINING PHILOSOPHER problem.
THEORY: -
The dining philosopher's problem is the classical problem of synchronization which says that
Five philosophers are sitting around a circular table and their job is to think and eat
alternatively. A bowl of noodles is placed at the center of the table along with five chopsticks
for each of the philosophers. To eat a philosopher needs both their right and a left chopstick.
A philosopher can only eat if both immediate left and right chopsticks of the philosopher is
available. In case if both immediate left and right chopsticks of the philosopher are not
available then the philosopher puts down their (either left or right) chopstick and starts
thinking again.

CODE: -
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

#define NUM_PHILOSOPHERS 5
#define NUM_EATING_ITERATIONS 3

pthread_mutex_t forks[NUM_PHILOSOPHERS];
pthread_t philosophers[NUM_PHILOSOPHERS];
void *philosopher(void *arg) {
int id = *(int *)arg;
int left_fork = id;
int right_fork = (id + 1) % NUM_PHILOSOPHERS;
for (int i = 0; i < NUM_EATING_ITERATIONS; ++i) {
// Thinking
printf("Philosopher %d is thinking.\n", id);
sleep(rand() % 3 + 1);
// Pick up left fork
pthread_mutex_lock(&forks[left_fork]);
printf("Philosopher %d picked up left fork.\n", id);
// Pick up right fork
pthread_mutex_lock(&forks[right_fork]);
printf("Philosopher %d picked up right fork.\n", id);

// Eating
printf("Philosopher %d is eating.\n", id);
sleep(rand() % 3 + 1);
// Put down right fork
pthread_mutex_unlock(&forks[right_fork]);
printf("Philosopher %d put down right fork.\n", id);
// Put down left fork
pthread_mutex_unlock(&forks[left_fork]);
printf("Philosopher %d put down left fork.\n", id);
}
return NULL;
}
int main() {
srand(time(NULL));
// Initialize forks mutexes
for (int i = 0; i < NUM_PHILOSOPHERS; ++i) {
pthread_mutex_init(&forks[i], NULL);
}
// Create philosopher threads
int philosopher_ids[NUM_PHILOSOPHERS];
for (int i = 0; i < NUM_PHILOSOPHERS; ++i) {
philosopher_ids[i] = i;
pthread_create(&philosophers[i], NULL, philosopher, &philosopher_ids[i]);
}
// Wait for philosopher threads to finish
for (int i = 0; i < NUM_PHILOSOPHERS; ++i) {
pthread_join(philosophers[i], NULL);
}

// Destroy forks mutexes


for (int i = 0; i < NUM_PHILOSOPHERS; ++i) {
pthread_mutex_destroy(&forks[i]);
}
return 0;
}

OUTPUT: -

Das könnte Ihnen auch gefallen