/
kernal.c
executable file
·355 lines (263 loc) · 9.55 KB
/
kernal.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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
// kernal.c
#include <stdlib.h>
#include <signal.h>
#include <unistd.h> // getpid() definition
#include "rtx.h"
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <stdio.h>
#include <string.h>
// globals
inputbuf * in_mem_p_key; // pointer to structure that is the shared memory
outputbuf * in_mem_p_crt; // pointer to structure that is the shared memory
int in_pid_keyboard; // pid of keyboard child process
int in_pid_crt; // pid of crt child process
caddr_t mmap_ptr_keyboard;
caddr_t mmap_ptr_crt;
int bufsize = BUFFERSIZE;
int fid, fid2, status; //used to create the shared memory
int numOfTicks = 0;
int displayClock = 0;
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
char * sfilename = "keyboardBuffer"; //the name of the keyboard_memory file
char * cfilename = "crtBuffer"; //the name of the crt_memory file
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//**************************************************************************
// routine to clean up things before terminating main program
// This stuff must be cleaned up or we have child processes and shared
// memory hanging around after the main process terminates
//this function should be called in terminate
void cleanup()
{
// terminate child process(es)
kill(in_pid_keyboard,SIGINT);
kill(in_pid_crt,SIGINT);
// remove shared memory segment and do some standard error checks
status = munmap(mmap_ptr_keyboard, bufsize);
if (status == -1){
printf("Bad munmap during cleanup\n");
} else {
printf("Unmapped shared memory for keyboard...\n");
}
status = munmap(mmap_ptr_crt, bufsize);
if (status == -1){
printf("Bad munmap during cleanup\n");
} else {
printf("Unmapped shared memory for CRT...\n");
}
// close the temporary mmap file
status = close(fid);
if (status == -1){
printf("Bad close of temporary mmap file during cleanup\n");
} else {
printf("Closed the file used for shared keyboard...\n");
}
status = close(fid2);
if (status == -1){
printf("Bad close of temporary mmap file during cleanup\n");
} else {
printf("Closed the file used for shared CRT...\n");
}
// unlink (i.e. delete) the temporary mmap file
status = unlink(sfilename);
if (status == -1){
printf("Bad unlink during claeanup.\n");
} else {
printf("Deleted the file used for shared keyboard...\n");
}
status = unlink(cfilename);
if (status == -1){
printf("Bad unlink during claeanup.\n");
} else {
printf("Deleted the file used for shared CRT...\n");
}
}
//**************************************************************************
// routine to call before exitting
// This routine gets called when certain signals occur
void die(int signal)
{
cleanup();
printf( "Ending main process ...\n" );
exit(0);
}
// kbd_handler
// Called by signal SIGUSR1 from keyboard reader process
void kbd_handler(int signum)
{
inputbuf command;
// copy input buffer
if (in_mem_p_key->indata[0] != '\0')
{
strcpy(command.indata,in_mem_p_key->indata);
// we should parse the input string and execute the command given,
// but for now we just echo the input
//
if (!strcmp(command.indata,"t")) {
die(SIGINT);
}
if (!strcmp(command.indata,"cd")) {
//printf("Command Recognized!\n");
int seconds = 0;
int mins = 0;
int hours = 0;
int numLeft = numOfTicks;
hours = numLeft/3600;
numLeft = numLeft%3600;
mins = numLeft/60;
numLeft = numLeft%60;
seconds = numLeft;
printf("Time Elapsed: %.2d:%.2d:%.2d\n",hours,mins,seconds);
displayClock = 1;
}
if (!strcmp(command.indata,"ct")) {
displayClock = 0;
}
if (command.indata[0] == 'c' && command.indata[1] == ' ') {
//for now to set the time, you can only put in one space after
//typing in c and then specify the hh:mm:ss
numOfTicks = 0;
int hour = atoi(&(command.indata[2]));
int min = atoi(&(command.indata[5]));
int sec = atoi(&(command.indata[8]));
printf("%.2d:%.2d:%.2d",hour,min,sec);
numOfTicks = hour*3600 + min*60 + sec;
}
//printf("Keyboard input was: %s\n",command.indata);
in_mem_p_key->ok_flag = 0; // tell child that the buffer has been emptied
}
}
void tick_handler(int signum) {
numOfTicks++;
if (displayClock == 1) {
int seconds = 0;
int mins = 0;
int hours = 0;
int numLeft = numOfTicks;
hours = numLeft/3600;
numLeft = numLeft%3600;
mins = numLeft/60;
numLeft = numLeft%60;
seconds = numLeft;
printf("Time Elapsed: %.2d:%.2d:%.2d\n",hours,mins,seconds);
}
alarm(1);
}
//**************************************************************************
int main()
{
// catch signals so we can clean up everything before exitting
// signals defined in /usr/include/signal.h
// e.g. when we recieved an interrupt signal SIGINT, call die()
sigset(SIGINT,die); // catch kill signals
sigset(SIGBUS,die); // catch bus errors
sigset(SIGHUP,die);
sigset(SIGILL,die); // illegal instruction
sigset(SIGQUIT,die);
sigset(SIGABRT,die);
sigset(SIGTERM,die);
sigset(SIGSEGV,die); // catch segmentation faults
sigset(SIGALRM,tick_handler);
alarm(1);
// signal from keyboard reader is SIGUSR1 (user-defined signal)
// When there is input from the keyboard, call the kbd_handler() routine
sigset(SIGUSR1,kbd_handler);
/* Create a new mmap file for read/write access with permissions restricted
to owner rwx access only */
fid = open(sfilename, O_RDWR | O_CREAT | O_EXCL, (mode_t) 0755 );
if (fid < 0){
printf("Bad Open of mmap file <%s>\n", sfilename);
exit(0);
};
fid2 = open(cfilename, O_RDWR | O_CREAT | O_EXCL, (mode_t) 0755 );
if (fid2 < 0){
printf("Bad Open of mmap file <%s>\n", cfilename);
exit(0);
};
// make the file the same size as the buffer
status = ftruncate(fid, bufsize );
if (status){
printf("Failed to ftruncate the file <%s>, status = %d\n", sfilename, status );
exit(0);
}
status = ftruncate(fid2, bufsize );
if (status){
printf("Failed to ftruncate the file <%s>, status = %d\n", cfilename, status );
exit(0);
}
// pass parent's process id and the file id to child
char childarg1[20], childarg2[20]; // arguments to pass to child process(es)
int mypid = getpid(); // get current process pid
sprintf(childarg1, "%d", mypid); // convert to string to pass to child
sprintf(childarg2, "%d", fid); // convert the file identifier
// now start doing whatever work you are supposed to do
// in this case, do nothing; only the keyboard handler will do work
printf("\nWelcome to the CCI, the OS is at your disposal: \n");
// create the keyboard reader process
// fork() creates a second process identical to the current process,
// except that the "parent" process has in_pid = new process's ID,
// while the new (child) process has in_pid = 0.
// After fork(), we do execl() to start the actual child program.
// (see the fork and execl man pages for more info)
in_pid_keyboard = fork();
if (in_pid_keyboard == 0) // is this the child process ?
{
execl("./keyboard", "keyboard", childarg1, childarg2, (char *)0);
// should never reach here
fprintf(stderr,"kernal: can't exec keyboard, errno %d\n",errno);
cleanup();
exit(1);
};
// pass parent's process id and the file id to child CRT
sprintf(childarg1, "%d", mypid); // convert to string to pass to child
sprintf(childarg2, "%d", fid2); // convert the file identifier
in_pid_crt = fork();
if (in_pid_crt == 0) // is this the child process ?
{
execl("./crt", "crt", childarg1, childarg2, (char *)0);
// should never reach here
fprintf(stderr,"kernal: can't exec crt, errno %d\n",errno);
cleanup();
exit(1);
};
// the parent process continues executing here
// sleep for a second to give the child process time to start
sleep(1);
// allocate a shared memory region using mmap
// the child process also uses this region
mmap_ptr_keyboard = mmap((caddr_t) 0, /* Memory location, 0 lets O/S choose */
bufsize, /* How many bytes to mmap */
PROT_READ | PROT_WRITE, /* Read and write permissions */
MAP_SHARED, /* Accessible by another process */
fid, /* the file associated with mmap */
(off_t) 0); /* Offset within a page frame */
if (mmap_ptr_keyboard == MAP_FAILED){
printf("Parent's memory map has failed for keyboard, about to quit!\n");
die(0); // do cleanup and terminate
};
in_mem_p_key = (inputbuf *) mmap_ptr_keyboard; // pointer to shared memory
// we can now use 'in_mem_p' as a standard C pointer to access
// the created shared memory segment
in_mem_p_key->ok_flag = 0;
// allocate a shared memory region using mmap
// the child process also uses this region
mmap_ptr_crt = mmap((caddr_t) 0, /* Memory location, 0 lets O/S choose */
bufsize, /* How many bytes to mmap */
PROT_READ | PROT_WRITE, /* Read and write permissions */
MAP_SHARED, /* Accessible by another process */
fid2, /* the file associated with mmap */
(off_t) 0); /* Offset within a page frame */
if (mmap_ptr_crt == MAP_FAILED){
printf("Parent's memory map has failed for CRT, about to quit!\n");
die(0); // do cleanup and terminate
};
in_mem_p_crt = (outputbuf *) mmap_ptr_crt; // pointer to shared memory
// we can now use 'in_mem_p' as a standard C pointer to access
// the created shared memory segment
in_mem_p_crt->ok_flag = 0;
while (1);
// should never reach here, but in case we do, clean up after ourselves
cleanup();
exit(1);
} // main