كتابة برنامج بلغة c باستخدام استدعاءات نظام لينكس لحل مسألة عشاء الفلاسفة باستخدام السيمافورات لحل مشكلة تزامن الاجرائيات ضمن نظام لينكس.
الأوامر والاستدعاءات :
fork() , getpid(), semget() , semop() , semctl()
مسألة عشاء الفلاسفة تنص على مايلي:
يجلس خمسة فلاسفة في حلقة حول طاولة, عليها 4 كراسي وأمام كل منها طبق لا ينتهي محتواه، وهناك شوكة بين كل صحنين، أي أن أمام كل فيلسوف شوكتان: واحدة على يمينه وأخرى على يساره.
يقضي الفيلسوف حياته في التفكير وتناول الطعام من الطبق ، وليتمكن من تناول الطعام يحتاج إلى تناول الشوكتين ليتمكن من الأكل. وبعد الانتهاء من الأكل، ينظف الفيلسوف الشوكتين ويعيدهما إلى مكانهما جاهزتين للاستخدام من جديد .
اكتب برنامج يقوم بما يلي:
حل المسألة ل 5 فلاسفة و4 كراسي خمسة شوك.
استخدم السيمافورات , بشرط أن يجلس الفيلسوف قبل طلب الشوكة و الأكل .
اكتب تقرير توضح به خوارزمية الحل و عمل البرنامج .
لقد كتبت بكل خبرتي بالسيمافورات ولكن لم استطع الحل بالشكل الكامل فيمكنك بحكم خبرتك :
<تعدل الملف البرمجي التالي لتتحقق الطلبات التي في الاعلى>
#include<errno.h>
#include<math.h>
#include<signal.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/time.h>
#define FALSE 0
#define TRUE 1
#define NPHIL 4 //عدد الفلاسفة يعدل الى خمسة
#define NCHOPSTICKS NPHIL //عدد الشوك هو نفس عدد الفلاسفة
#define AVG_THINK 2.5 // زمن التفكير بدون أكل حالة الانتظار
#define AVG_EAT 1.5 //زمن الاكل حالة العمل
#define DURATION 30 //الزمن الذي تحدث بعده المقاطعة
typedef union semun{
int val; //حقل لتاسيس السيمافور على الصفر او الواحد
struct semid_ds *buf;
ushort *array;
}SEM_UNION;
static int alarm_flag=FALSE;
/*------print error mesage and terminate a process------*/
void error(const char *msg)
{
fflush(stdout);
printf( "%s %d %s\n", msg ,errno,strerror(errno));
exit(0);
}
/*******signal the semaphore*******/
void my_signal(int s)//التابع الذي يعمل عملية السيغنل
//نمرر له رقم السيمافور الذي اريد ان اعمل عليه سغنل
{
int status;
struct sembuf sb;
sb.sem_num=0;//السيمافور الاول بالمصفوفة
sb.sem_op=1;//رفع )سيغنال
sb.sem_flg=SEM_UNDO;//عندما تجد مشكلةمثل بطئ الكومبيوتر) حرر السيمافور
status=semop(s,&sb,1);//s=semid
if(status<0)
{ error("In my wait,semaphore failed");}
}
/********wait on semaphore*******/
void my_wait(int s)
{
int status;
struct sembuf sb;
sb.sem_num=0;
sb.sem_op=-1;//wait1
sb.sem_flg=SEM_UNDO;
status=semop(s,&sb,1);
if(status<0)
{ error("In my wait,semaphore failed");}
}
/********think *******///خارج المعالج
void think(int phil)//نمرر له رقم الفيلسوف
{
int duration=drand48()*1000000.0*AVG_THINK;//للتحويل الى ميكرو ثانية
printf("phil %d (proc %d) thinking %d microseconds\n",phil,getpid(), duration);
usleep(duration);
}
void eat(int phil)//داخل المعالج
{
int duration=drand48()*1000000.0*AVG_EAT;
printf("phil %d (proc %d) eating %d microseconds\n",phil,getpid(), duration);
usleep(duration);
}
/*****timer*****/
void alarm_handler(sig,code,scp)
int sig;
int code;
struct sigcontext *scp;
{
alarm_flag=TRUE;
}
void set_sig_handler()
{
struct sigaction act;
act.sa_handler=alarm_handler;
#if defined_FreeBSD_
act.sa_mask=0;
#endif
act.sa_flags=SA_RESTART|SA_RESETHAND;
sigaction(SIGUSR1, &act,(struct sigaction *) NULL);
}
/******creat process*********/
int create_philososphers(const int n,int child[])//تابع انشاء الاجرائيات حيث نولد اجراء اب وهو سيولد اربع اجرائيات وجميع الاجرائيات تمثل الفلاسفة
{ //n=5
int i,status;
for (i=0;i<n;++i)
{
child=0;
}
printf("creating %d philosophers\n",n);
for(i=0;i<n;++i)
{
status=fork();
if(status<0)
{
error("failed to creat philosopher \n");}
else if(status==0)//نحن بالابن رجع ابناء
{return i-1;
}
else{ child[i-1]=status;}//نحنبالاب خزن بيايدي للابن pid
}
return -1;
}
/**********Main program*********/
int main( int argc,char *argv[])
{
int child[NPHIL],
chopstick[NCHOPSTICKS],i,status, philosopher_id=0 , left,right;//الشوكة اليمين واليسار
SEM_UNION arg;//لتاسيس السيمافور//from union
key_t k;//لربط السيمافورات
for(i=0;i<=NCHOPSTICKS;++i)
{
k=ftok(argv[0],i);//لتوليد الكي لخمس سيمافورات الشوك
printf("\n",argv[0],k);
chopstick=semget(k,1,IPC_CREAT);//1 لكل شوكة سيمافور وحيد//IPC_CREAT becouse creat new key !!!
printf("chopstick[%d] is %d\n",i,chopstick);
if(chopstick<0)
{error("bad sem creat");
}
arg.val=1;//نأسس السيمافورات على قيمة 1
status=semctl(chopstick,0,SETVAL,arg);
if(status<0)
{error("couldnt itinalize sem counter to 1");}
}
/*********creat semaphores******/
philosopher_id=create_philososphers(NPHIL,child);
if(philosopher_id==-1)
{
sleep(DURATION);
for(i=0;i<NPHIL;++i)
{
kill(child,SIGUSR1);
}
for(i=0;i<NPHIL;++i)
{
status=wait((int *)0);
if(status<0)
{
error("wait erorr detected");
}
}
for(i=0;i<NCHOPSTICKS;i++)
{
status=semctl(chopstick,0,IPC_RMID,0);
if(status<0)
{error("bad remove sem");}
}
}
else
{
left=philosopher_id;
right=(philosopher_id +1)%NPHIL;
set_sig_handler();
while(!alarm_flag)
{
think(philosopher_id);
if(philosopher_id & 0x1)
{
my_wait(chopstick);
printf("phil %d picked up left chopstick %d\n",philosopher_id,getpid(),left);
my_wait(chopstick);
printf("phil %d picked up right chopstick %d\n",philosopher_id,getpid(),right);
}
else
{
my_wait(chopstick);
printf("phil %d picked up right chopstick %d\n",philosopher_id,getpid(),right);
my_wait(chopstick);
printf("phil %d picked up left chopstick %d\n",philosopher_id,getpid(),left);
}
eat(philosopher_id);
if(philosopher_id & 0x1)
{
my_signal(chopstick);
printf("phil %d put down left chopstick %d\n",philosopher_id,getpid(),left);
my_signal(chopstick);
printf("phil %d put down right chopstick %d\n",philosopher_id,getpid(),right);
}
else
{
my_signal(chopstick);
printf("phil %d put down right chopstick %d\n",philosopher_id,getpid(),right);
my_signal(chopstick);
printf("phil %d put down left chopstick %d\n",philosopher_id,getpid(),left);
}
}
}
}