-
Notifications
You must be signed in to change notification settings - Fork 0
/
print_server.c
135 lines (111 loc) · 4.35 KB
/
print_server.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "common.h"
#include <unistd.h>
int fd;
int errno;
int shm_exists;
Shared* shared_mem;
int setup_shared_memory(){
//Set the file descriptor fd to the shared mem
//the memory will have the size only of the specified object
//->Only create the shared memory if it does not exists
fd = shm_open(t_shm, O_CREAT | O_RDWR | O_EXCL, S_IRWXU);
if(errno == EEXIST){
printf("Shared memory already exists, opening instead of creating\n");
shm_exists = 1;
fd = shm_open(t_shm, O_RDWR, S_IRWXU);
}
if(fd == -1){
//Check failed memory assignment
printf("Could not open or create share memory\n");
exit(1);
}
ftruncate(fd, sizeof(Shared));
return 0;
}
int attach_shared_memory(){
//Attach the shared memory at fd to the process virtual address
shared_mem = (Shared*) mmap(NULL, sizeof(Shared), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if(shared_mem == MAP_FAILED){
printf("mmap() failed\n");
exit(1);
}
printf("Successfully attached shared memory to printer server\n");
return 0;
}
int init_shared_memory(){
int temp;
printf( "Enter the size of the job queue,\nmust be an integer between 0 and 50:\n>");
scanf("%d" , &temp);
while( temp < 1 || temp > 50){
printf( "Invalid input, please enter an integer between 0 and 50\n>" );
scanf("%d" , &temp);
}
//Here init everything in the struct object
shared_mem->qfront = 0;
shared_mem->qrear = 0;
shared_mem->jobcount = 0;
shared_mem->queuesize = temp;
sem_init(&(shared_mem->underflow), 1, 0);// Underflow start at 0
sem_init(&(shared_mem->overflow), 1, temp); // Overflow starts at max
sem_init(&(shared_mem->mutex), 1, 1); // first 1 means shared between processes
printf("Printer server initialized shared memory with a capacity of %d jobs\n",shared_mem->queuesize);
}
void catch_signal( int the_signal ) {
signal( the_signal, catch_signal );
printf( "\nSignal %d received\n", the_signal );
if(the_signal == SIGQUIT || the_signal == SIGINT ){
printf( "Cleaning and exiting\n");
//Clean: Destroy the semaphores and unlink the shared mem
int r=0;
r+=sem_destroy(&(shared_mem->underflow));
r+=sem_destroy(&(shared_mem->overflow));
r+=sem_destroy(&(shared_mem->mutex));
if(r){
printf("Could not destroy semaphores\n");
}else{
printf("Successfully destroyed semaphores\n");
}
if(shm_unlink(t_shm)==-1){
printf("Could not unlink the shared memory\n");
exit(1);
}
printf("Successfully unlinked shared memory\n");
exit(3);
}
}
int main(int argc, char argv[]){
//Set up hooks for cleaning
if ( signal (SIGINT, catch_signal ) == SIG_ERR ){
perror( "SIGINT failed" );
exit (1);
}
if ( signal (SIGQUIT, catch_signal ) == SIG_ERR ){
perror( "SIGQUIT failed" );
exit(1);
}
shm_exists = 0; //var that notes if the shm has to be init
setup_shared_memory(); //Create or open the shared memory
attach_shared_memory();
if(!shm_exists){ //init shm only if first server
init_shared_memory(); //also init the semaphores
}else{
printf("Skipped initialization since using already created shared memory\n");
}
while(1){
int jobnum;
//wait to get the mutex
sem_wait(&shared_mem->underflow);
sem_wait(&shared_mem->mutex);
//execute a print job and print info
jobnum = shared_mem->qrear; //update job number
struct Job currentjob = shared_mem->joblist[shared_mem->qrear%shared_mem->queuesize]; //load the job in a local struct
printf("\n----------\nProcessing job #%d\nJob name: \"%s\"\nJob owner: %d\nJob time: %d\n",shared_mem->qrear, currentjob.name, currentjob.ownerpid, currentjob.time);
shared_mem->qrear++; //update the rear of the job queue (in an array)
shared_mem->jobcount--; //There is one less job in the queue
//Exit the critical region before processing the job (no need to stay in)
sem_post(&shared_mem->mutex);
sem_post(&shared_mem->overflow);
sleep(currentjob.time); //Execute the job
printf("Job #%i done. \n----------\n\n", jobnum);
}
}