Operating system -- process synchronization

Experiment 2 process synchronization
1, Purpose of the experiment:
Master basic synchronization algorithms and understand the essence of classical process synchronization problems; Learn to use the process synchronization mechanism of Linux and master the use methods of relevant API s; Can use the semaphore mechanism and adopt a variety of synchronization algorithms to realize the philosopher dining program without deadlock.
2, Experimental platform:
Virtual machine: VMware 9up
Operating system: Ubuntu 12.04up
Editor: Gedit | Vim
Compiler: Gcc
3, Experiment content:
(1) Based on the dining model of philosophers, five processes are created in the Linux console environment, and a semaphore set (5 semaphores, initial value is 1) is created with semget function to simulate the thinking and dining behavior of philosophers: when each philosopher is hungry, first pick up the left-hand chopsticks, and then pick up the right-hand chopsticks; Chopsticks are critical resources. Define a mutually exclusive semaphore for each chopstick; If you want to get the chopsticks, you need to do P operation on the semaphore first, and release the chopsticks after use to do V operation on the semaphore.
Pseudo code Description:
semaphore chopstick[5]={1,1,1,1,1};
• the activities of the ith philosopher can be described as:
do{
printf("%d is thinking\n",i);
printf("%d is hungry\n",i);
wait(chopstick[i]); // Take the left chopsticks
wait(chopstick[(i+1) % 5]); // Take the right chopsticks
printf("%d is eating\n",i);
signal(chopstick[i]); // Put left chopsticks
signal(chopstick[(i+1) % 5]); // Put right chopsticks
...
}while[true];

Run the group of processes and observe whether the process can run all the time. If it stalls, what happens? And analyze the reasons.

If you can't run all the time, there will be a process deadlock, because five processes are created, and they will compete with each other. Once all five processes get their left chopsticks at the same time, they will fall into waiting because they can't get their right chopsticks, which will lead to a deadlock.

(2) The following methods can be adopted to solve the dining problem of philosophers: A. only when the left and right chopsticks of philosophers are available, they are allowed to pick up chopsticks for dinner; b. At most four philosophers are allowed to take the chopsticks on the left at the same time, which can finally ensure that at least one philosopher can eat; c. It is stipulated that odd numbered philosophers first pick up the chopsticks of his left hand, and then pick up the chopsticks of his right hand, while even numbered philosophers first pick up the chopsticks of his right hand, and then pick up the chopsticks of his left hand. Method a is given in the example program. Please use methods B and C to write a philosopher meal program that will not deadlock.
Method b:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/wait.h>
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *_buf;
};


#define ERR_EXIT(m) \
do { \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)
//Get mutex semaphore
void wait_mutex(int mutex)
{
struct sembuf sb={0,-1,0};
semop(mutex,&sb,1);//Operate on mutually exclusive semaphores
}

//Get chopsticks
void wait_v(int semid,int num)
{
struct sembuf sb={num,-1,0};
semop(semid,&sb,1);
}
//Release chopsticks
void signal_p(int semid,int num)
{
struct sembuf sb={num,1,0};
semop(semid,&sb,1);
}

//Release mutex
void signal_mutex(int semid0)
{
struct sembuf sb={0,1,0};
semop(semid0,&sb,1);
}
//ph function
void ph(int num,int semid,int semid0)
{
int left=num;
int right=(num+1)%5;
for(;;)
{
printf("%d is thinking\n",num);
sleep(1);
printf("%d is hungry\n",num);
sleep(1);
//wait operation, control up to 4 people to eat
wait_mutex(semid0);//mutex 
wait_v(semid,left);
wait_v(semid,right);
printf("%d is eating\n",num);
sleep(1);
//signal operation
signal_p(semid,right);//Release the right chopsticks
signal_p(semid,left);//Release left Tachyon
signal_mutex(semid0);//Release mutex semaphore
}
}
//Main function
int main(int argc,char *argv[])
{
int semid,semid0;
//Create two semaphore sets
semid0=semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
semid=semget(IPC_PRIVATE,5,IPC_CREAT | 0666);
//
union semun su;
su.val=1;
int i;
for(i=0;i<5;i++)
{
//The semctl() system call performs various control operations on a semaphore set (or a single semaphore in the set)
semctl(semid,i,SETVAL,su);
}
//Set the initial value of semid0 semaphore
union semun su0;
su0.val=4;
semctl(semid0,0,SETVAL,su0);
//Create 4 sub processes
int num=0;
pid_t pid;
for(i=1;i<5;i++)
{
pid=fork();
if(pid<0) {ERR_EXIT("fork");}
if(pid==0) {num=i;break;}
}
//What the num first philosopher has to do
ph(num,semid,semid0);
return 0;
}
 

//Method c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/wait.h>
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};


#define ERR_EXIT(m) \
do { \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)

//Get chopsticks
void wait_v(int semid,int num)
{
struct sembuf sb={num,-1,0};
semop(num,&sb,1);
}
//Release chopsticks
void signal_p(int semid,int num)
{
struct sembuf sb={num,-1,0};
semop(num,&sb,1);
}

//What scientists have to do
void ph(int semid,int num)
{
for(;;)//Dead cycle
{
//Judge whether the number of philosophers is odd or even
//The odd number applies for the left chopsticks first, and the even number applies for the right chopsticks first
if(num%2!=0)
{//Judge odd numbers
printf("%d is thinking\n",num);
sleep(1);
printf("%d is hungry\n",num);
sleep(1);
//wait operation
wait_v(semid,num);
wait_v(semid,(num+1)%5);
printf("%d is eating\n",num);
sleep(1);
//signal operation
signal_p(semid,(num+1)%5);
signal_p(semid,num);
}
if(num%2==0)
{//Judge even number
printf("%d is thinking\n",num);
sleep(1);
printf("%d is hungry\n",num);
sleep(1);
//wait operation
wait_v(semid,(num+1)%5);
wait_v(semid,num);
//signal operation
signal_p(semid,num);
signal_p(semid,(num+1)%5);
}
}
}
int main(int argc,char *argv[])
{
int semid;
//Create 5 semaphores
semid=semget(IPC_PRIVATE,5,IPC_CREAT | 0666);
union semun su;
su.val=1;
int i;
for(i=0;i<5;i++)
{
//Note that the second parameter is also an index
semctl(semid,i,SETVAL,su);
}
//Create 4 sub processes
pid_t pid;
int num=5;
for(i=0;i<4;i++)
{
pid=fork();
if(pid<0) { ERR_EXIT("fork");}
if(pid==0) { num=i;break;}
}
//What philosophers do
ph(semid,num);
return 0;
}

(3) Design the program to realize the synchronization and mutual exclusion of Producer / consumer processes (threads). In this program, four processes (or threads) are created to simulate producers and consumers to realize the synchronization and mutual exclusion of processes (threads).

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/wait.h>
#define N 2 / / number of consumers or producers
#define M 10 / / number of buffers
int buff[M] = {0}; // The buffer is initialized to 0 and there is no product at the beginning
int in = 0;   // Where the producer places the product
int out = 0; // Where consumers take products
int full_sem,empty_sem;// Synchronous semaphore, which prevents producers from releasing products when they are full, and prevents consumers from consuming when there is no product
int mutex;
union semun
{
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
};
#define ERR_EXIT(m) \
do { \
perror(m); \
exit(EXIT_FAILURE); \
} while(0)

/* Print buffer */
void print()
{
	int i;
	for(i = 0; i < M; i++)
	   printf("%d ", buff[i]);
	printf("\n");
}
//Get chopsticks
void wait_v(int semid)
{

struct sembuf sb={0,-1,0};
semop(semid,&sb,1);
}
//Release chopsticks
void signal_p(int semid)
{
struct sembuf sb={0,1,0};
semop(semid,&sb,1);
}
//Release mutex
void signal_mutex(int semid0)
{
struct sembuf sb={0,1,0};
semop(semid0,&sb,1);
}
//Get mutex semaphore
void wait_mutex(int mutex)
{
struct sembuf sb={0,-1,0};
semop(mutex,&sb,1);//Operate on mutually exclusive semaphores
}

/* Producer method */ 
void product(int semid,int num,int full_sem,int empty_sem,int mutex){
 int id = ++num;
 while(1){
  sleep(1);
 //printf("%d", full_sem);

 wait_v(empty_sem); 
 //printf("empty bit \ t");
 
 wait_mutex(mutex);
 in = in % M;
 printf("product%d in %d. like: \t", id, in);

 buff[in] = 1;  
 print();  
 ++in;

 signal_mutex(mutex);
  signal_p(full_sem); 
 //printf("plus \ n");
 }
}

/* Consumer approach */
void prochase(int semid,int num,int full_sem,int empty_sem,int mutex){
  int id = ++num;
 
 while(1){
 sleep(1);
 wait_v(full_sem);
 //printf("something \ t");

 wait_mutex(mutex);
 
  out = out % M;
   printf("prochase%d out %d. like: \t", id, out);
   buff[out] = 0;
   print();
   ++out;
 
 signal_mutex(mutex);
 signal_p(empty_sem);
 // printf("minus \ n");
 }
}
int main(int argc,char *argv[])
{
int full_sem,empty_sem;// Synchronous semaphore, which prevents producers from releasing products when they are full, and prevents consumers from consuming when there is no product
int mutex;
full_sem=semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
empty_sem=semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
union semun su;
su.val=M;
semctl(empty_sem,0,SETVAL,su);
union semun su4;
su4.val=0;
semctl(full_sem,0,SETVAL,su4);
mutex = semget(IPC_PRIVATE,1,IPC_CREAT | 0666);
union semun su1;
su1.val=1;
semctl(mutex,0,SETVAL,su1);
int semid1,semid2;
semid1=semget(IPC_PRIVATE,N,IPC_CREAT | 0666);
semid2=semget(IPC_PRIVATE,N,IPC_CREAT | 0666);
union semun su2;
su2.val=1;
int i;
for(i=0;i<N;i++)
{
//Note that the second parameter is also an index
semctl(semid1,i,SETVAL,su2);
semctl(semid2,i,SETVAL,su2);
}

int num1=0;
pid_t pid1;
//int num2 = 0;
pid_t pid2;
//int j;

// Create N producer threads
for(i=1;i<=N;i++)
{
	pid1=fork();
	if(pid1<0) {ERR_EXIT("fork");}
	if(pid1==0) {num1=i;
	printf("product%d creation \n", num1);
	product(semid1,num1,full_sem,empty_sem,mutex);
	break;}
	else{num2=i;
	printf("prochase%d creation \n", num2);
	prochase(semid2,num2,full_sem,empty_sem,mutex);
	}
}return 0;
}

I don't have enough practice and don't want to write. Let's go. I don't know what the hell it is after running for a while,

Tags: Linux Operation & Maintenance Operating System

Posted on Fri, 03 Dec 2021 09:10:25 -0500 by climbjm