I have a program with a pipe and fork. it is not fully running the program can i
ID: 1813110 • Letter: I
Question
I have a program with a pipe and fork. it is not fully running the program can i please have assitance. the program is listed below:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#define MAX_STR 256
#define MAX_LINE 64
#define MAX_PROCS 256
#define BLOCK 0
#define READY 1
#define RUNNING 2
#define DEBUG true
#define true 1
#define false 0
#define MAX_PRIORITY 4
#define CLASS_0 0
#define CLASS_1 1
#define CLASS_2 2
#define CLASS_3 3
#define REPORT
struct Cpu
{
int pc;
int pid;
int value;
int t_slice;
int t_remain;
};
struct Proc
{
int pid;
int ppid;
int pc;
int value;
int priority;
int state;
int t_start;
int t_used;
char fname[MAX_STR];
char prog[MAX_LINE][MAX_STR];
};
typedef struct Que {
int pid;
struct Proc proc;
struct Que *next;
} QUE;
struct TA_TIME{
int times[MAX_PROCS];
int count;
};
char buffer[BUFSIZ];
int quantum[4];
QUE *insert_head(QUE **p, int pid)
{
QUE *n = (QUE *) malloc(sizeof(QUE));
if (n == NULL) return NULL;
n->next = *p;
*p = n;
n->pid = pid;
return n;
}
QUE *enqueue(QUE **p, int pid)
{
QUE *tail = *p;
if(*p == NULL)
return insert_head(p, pid);
while(tail->next != NULL)
tail = tail->next;
QUE *n = (QUE *) malloc(sizeof(QUE));
if (n == NULL)
return NULL;
n->next = tail->next;
tail->next = n;
n->pid = pid;
return n;
}
int dequeue(QUE **p){
int pid = -1;
if (*p != NULL){
printf("DEQ(pid =%d) ", (*p)->proc.pid);
pid = (*p)->pid;
QUE *n = *p;
*p = n->next;
free(n);
return pid;
}else{
printf("cannot remove, because queue is empty ");
return pid;
}
}
struct Proc create_proc(int pid, int ppid, int priority, int pc, int value,
int t_start, int t_used, char *fname){
static struct Proc proc;
proc.pid = pid;
proc.ppid = ppid;
proc.priority = priority;
proc.pc = pc;
proc.value = value;
proc.t_start = t_start;
proc.t_used = t_used;
strcpy(proc.fname, fname);
readProgram(proc.fname, proc.prog);
return proc;
}
struct Proc dup_proc(struct Proc *pp, int new_pid,
int dup_times, int current_time){
static struct Proc cp;
cp.pid = new_pid;
cp.ppid = pp->pid;
cp.priority = pp->priority;
cp.pc = pp->pc;
cp.value = pp->value;
cp.t_start = current_time;
cp.t_used = 0;
strcpy(cp.fname, pp->fname);
readProgram(cp.fname, cp.prog);
return cp;
}
void show(QUE *n, struct Proc pcbTable[]){
struct Proc proc;
if (n == NULL){
printf("queue is empty ");
return ;
}
while (n != NULL){
proc = pcbTable[n->pid];
printf("pc, pid, ppid, priority, value, start time, CPU time used so far ");
printf("%2d, %3d, %3d, %8d, %5d, %10d, %3d ",
proc.pc, proc.pid, proc.ppid, proc.priority,
proc.value, proc.t_start, proc.t_used);
n = n->next;
}
printf(" ");
return;
}
void show_by_priority(QUE *n, struct Proc pcbTable[], int priority){
struct Proc proc;
int count = 0;
while (n != NULL){
if(pcbTable[n->pid].priority == priority){
proc = pcbTable[n->pid];
printf("pc, pid, ppid, priority, value, start time, CPU time used so far ");
printf("%2d, %3d, %3d, %8d, %5d, %10d, %3d ",
proc.pc, proc.pid, proc.ppid, proc.priority,
proc.value, proc.t_start, proc.t_used);
count++;
}
n = n->next;
}
if (count == 0){
printf("queue is empty ");
return ;
}
printf(" ");
return;
}
void cpu2proc(struct Cpu *cpu, struct Proc *proc){
proc->pc = cpu->pc;
proc->pid = cpu->pid;
proc->value = cpu->value;
proc->t_used = cpu->t_remain;
return;
}
void proc2cpu(struct Proc *proc, struct Cpu *cpu){
cpu->pc = proc->pc;
cpu->pid = proc->pid;
cpu->value = proc->value;
cpu->t_slice = quantum[proc->priority];
if(proc->t_used > 0){
printf("Blocked process was assigned to CPU. ");
cpu->t_remain = proc->t_used;
}else{
printf("New process was assigned to CPU. ");
cpu->t_remain = cpu->t_slice;
}
return;
}
void set_next_priority(struct Proc *p){
if(p->priority == CLASS_3){
p->priority = CLASS_3;
}else{
p->priority += 1;
}
return;
}
int calc_ta_time(int current_time, struct Proc *p){
return current_time - p->t_start;
}
double calc_ta_time_avg(struct TA_TIME ta){
int i;
int total = 0;
for(i=0; i<ta.count; i++){
total += ta.times[i];
}
if(ta.count == 0){
return 0;
}else{
return total/ta.count;
}
}
int readProgram(char *fname, char prog[][MAX_STR]){
FILE *fp;
char buff[MAX_STR], *pp;
int x, y, i, j;
for(x=0;x<MAX_LINE;x++){
for(y=0;y<MAX_STR;y++){
prog[x][y] = '';
}
}
fp = fopen(fname, "r");
if(fp == NULL){
printf("Can't open the file: '%s' ", fname);
exit(1);
}
i=0;
printf("Read '%s' program: ", fname);
while(1){
pp = fgets(buff, MAX_STR, fp);
// delete ' ' character if exists.
j=0;
while(buff[j] != ''){
if(buff[j] == ' ') buff[j] = '';
j++;
}
strcpy(prog[i], buff);
if(pp == NULL){
break;
}
printf("%3d: '%s' ", i, buff);
i++;
}
fclose(fp);
return(0);
}
char **split(int *n, char *string)
{
char **array=NULL;
char *p=string;
char *s;
for(*n=0; (s = strtok(p, " ")) != NULL; (*n)++) {
array = (char**)realloc(array, sizeof(char*) * (*n+1));
array[*n] = s;
p = NULL;
}
return array;
}
void copy(FILE *fin, FILE *fout)
{
while (fgets(buffer, BUFSIZ, fin) != NULL) {
fputs(buffer, fout);
fflush(fout);
}
}
void commanderProcess(int wfd)
{
FILE *fp = fdopen(wfd, "w");
int status;
char cmd[MAX_STR];
if (fp == NULL) {
perror("parent: fdopen");
exit(3);
}
copy(stdin, fp);
fclose(fp);
if(wait(&status) == -1) {
perror("wait");
exit(4);
}
}
void reporterProcess(int wfd, struct Proc pcbTable[], int time, struct TA_TIME ta,
QUE *s_run, QUE *s_ready, QUE *s_block){
int i;
printf("********************************************* ");
printf("The current system state is as follows: ");
printf("********************************************* ");
printf("CURRENT TIME: %d ", time);
printf("AVERAGE TURN AROUND TIME: %f. ", calc_ta_time_avg(ta));
printf(" ");
printf("RUNNING PROCESS: ");
show(s_run, pcbTable);
printf(" ");
printf("BLOCKED PROCESSES: ");
printf("Queue of blocked processes: ");
show(s_block, pcbTable);
printf(" ");
printf("PROCESSES READY TO EXECUTE: ");
for(i=0; i<MAX_PRIORITY; i++){
printf("Queue of processes with priority %d: ", i);
show_by_priority(s_ready, pcbTable, i);
}
close(wfd);
exit(3);
}
void processManagerProcess(int rfd, char *init_program)
{
FILE *fp = fdopen(rfd, "r");
int fd[2];
char **cmd;
int c, n;
int pid_count;
int arg;
int i,x,y;
int err_flg = false;
int wait4unblocking = false;
struct TA_TIME ta;
struct Proc temp_Proc;
int temp_value;
int temp_pid;
char temp_fname[MAX_STR];
int temp_index;
int current_time;
struct Cpu cpu;
struct Proc pcbTable[MAX_PROCS];
QUE *ready_states;
QUE *blocked_states;
QUE *running_states;
quantum[CLASS_0] = 1;
quantum[CLASS_1] = 2;
quantum[CLASS_2] = 4;
quantum[CLASS_3] = 8;
pid_count = 0;
ta.count = 0;
ta.times[0] = 0;
current_time = 0;
cpu.pc = 0;
cpu.pid = 0;
cpu.value = 0;
cpu.t_slice = quantum[CLASS_0];
cpu.t_remain = cpu.t_slice;
pcbTable[cpu.pid] = create_proc(pid_count++, -1, CLASS_0, cpu.pc, cpu.value,
current_time, quantum[CLASS_0]-current_time,
init_program);
ready_states = NULL;
blocked_states = NULL;
running_states = NULL;
enqueue(&running_states, cpu.pid);
while (fgets(buffer, BUFSIZ, fp) != NULL) {
printf("Command = %s",buffer);
if(!strcmp(buffer, "Q ") || !strcmp(buffer, "q ")){
if(wait4unblocking == true){
printf("Only blocked processes remain, so waiting for unblocking. ");
printf(" ");
printf("> ");
fflush(stdout);
continue;
}
printf("End of one unit of time. ");
printf("Instruction = '%s' ", pcbTable[cpu.pid].prog[cpu.pc]);
if(!strcmp(pcbTable[cpu.pid].prog[cpu.pc], "")){
printf("Instructions unexpectedly finished, so exit forcefully with printing. ");
sprintf(cmd[0], "E");
err_flg = true;
}else{
cmd = split(&n, pcbTable[cpu.pid].prog[cpu.pc]);
}
current_time++;
cpu.pc++;
cpu.t_remain--;
if(!strcmp(cmd[0], "S")){
printf("Set the value of the integer variable to %d. ", atoi(cmd[1]));
temp_value = cpu.value;
cpu.value = atoi(cmd[1]);
printf("CPU value: %d -> %d ", temp_value, cpu.value);
}else if(!strcmp(cmd[0], "A")){
printf("Add %d to the value of the integer variable. ", atoi(cmd[1]));
temp_value = cpu.value;
cpu.value += atoi(cmd[1]);
printf("CPU value: %d -> %d ", temp_value, cpu.value);
}else if(!strcmp(cmd[0], "D")){
printf("Subtract %d from the value of the integer variable. ", atoi(cmd[1]));
temp_value = cpu.value;
cpu.value -= atoi(cmd[1]);
printf("CPU value: %d -> %d ", temp_value, cpu.value);
}else if(!strcmp(cmd[0], "B")){
printf("Block this simulated process. ");
dequeue(&running_states);
cpu2proc(&cpu, &pcbTable[cpu.pid]);
printf("Running Process(pid=%d) was blocked. ", cpu.pid);
enqueue(&blocked_states, cpu.pid);
}else if(!strcmp(cmd[0], "E")){
printf("Terminate this simulated process. ");
dequeue(&running_states);
printf("pid=%d is Terminated. ", cpu.pid);
ta.times[ta.count++] = calc_ta_time(current_time, &pcbTable[cpu.pid]);
}else if(!strcmp(cmd[0], "F")){
printf("Create %d new simulated process(es). ", atoi(cmd[1]));
arg = atoi(cmd[1]);
cpu2proc(&cpu, &pcbTable[cpu.pid]);
pcbTable[pid_count++] = dup_proc(&pcbTable[cpu.pid], pid_count,
arg, current_time);
enqueue(&ready_states, pid_count-1);
printf("Created a process(pid=%d). ", pid_count-1);
cpu.pc += arg;
}
else if(!strcmp(cmd[0],"R")){
printf("Replace the program of the simulated process with the program in the file '%s'. ", cmd[1]);
strcpy(temp_fname, cmd[1]);
cpu.pc = 0;
cpu.value = 0;
readProgram(temp_fname, pcbTable[cpu.pid].prog);
printf("Replaced the current program with the program in '%s' file. ", temp_fname);
}else{
printf("Unknown Instruction. ");
printf("Exited by error. ");
return;
}
if(ready_states == NULL){
if(running_states != NULL){
printf("No ready processes, so continue to run the current process. ");
}else if(blocked_states != NULL){
printf("Only blocked processes remain, so waiting for unblocking. ");
wait4unblocking = true;
}else{
if(err_flg == false) printf("Program was successfully executed. ");
printf(" ");
printf("=== RESULT === ");
if (pipe(fd)) {
perror("pipe");
} else if ((temp_pid = fork()) == -1) {
perror("fork");
} else if (temp_pid == 0) {
close(fd[0]);
if(DEBUG) cpu2proc(&cpu, &pcbTable[cpu.pid]);
reporterProcess(fd[1], pcbTable, current_time, ta,
running_states, ready_states, blocked_states);
} else {
close(fd[1]);
while(i=(read(fd[0],&c,1)) > 0); // Pipe Synchronization
}
printf("=== END OF SYSTEM === ");
return;
}
}else if(running_states == NULL){ // When process was blocked or terminated.
printf("There are no process running, so assign the first process in the queue to CPU. ");
temp_pid = dequeue(&ready_states);
proc2cpu(&pcbTable[temp_pid], &cpu);
enqueue(&running_states, temp_pid);
printf("Assigned: cpu <--- pcbTable[%d] ", temp_pid);
}else if(cpu.t_remain <= 0) { // When quantum expired
printf("Quantum was expired, so assign the first process in the queue to CPU. ");
set_next_priority(&pcbTable[cpu.pid]);
printf("Pid(%d)'s priority class was raised to %d. ",
cpu.pid, pcbTable[cpu.pid].priority);
cpu2proc(&cpu, &pcbTable[cpu.pid]);
enqueue(&ready_states, cpu.pid);
temp_pid = dequeue(&running_states);
proc2cpu(&pcbTable[dequeue(&ready_states)], &cpu);
enqueue(&running_states, cpu.pid);
printf("Swithed: cpu(%d) <--> pid(%d) ", temp_pid, cpu.pid);
}else if(cpu.t_remain > 0){
printf("cpu time is still remained, so continue to run the current process. ");
}else{
printf("Unknown condition to schedule. ");
}
free(cmd);
}else if(!strcmp(buffer, "U ") || !strcmp(buffer, "u ")){
printf("Unblock the first simulated process in blocked queue. ");
temp_index = dequeue(&blocked_states);
if(temp_index == -1){
printf("There are no states in blocked queue. ");
}else{
printf("pid=%d moves from blocked queue to ready queue. ", temp_index);
enqueue(&ready_states, temp_index);
wait4unblocking = false;
}
}else if(!strcmp(buffer, "P ") || !strcmp(buffer, "p ")){
printf("Print the current state of the system. ");
if (pipe(fd)) {
perror("pipe");
} else if ((temp_pid = fork()) == -1) {
perror("fork");
} else if (temp_pid == 0) {
close(fd[0]);
if(DEBUG) cpu2proc(&cpu, &pcbTable[cpu.pid]);
reporterProcess(fd[1], pcbTable, current_time, ta,
running_states, ready_states, blocked_states);
} else {
close(fd[1]);
while(i=(read(fd[0],&c,1)) > 0);
}
}else if(!strcmp(buffer, "help ")){
printf("
The following commands are accepted:
Q:End of one unit of time
- CPU consumes 1 instruction from programs, and execute it.
U: Unblock the first simulated process in blocked queue
- If there is a blocked process, move its state from Blocked toReady.
P: Print the current state of the system.
- The state include PC, PID, PPID, Priority, Value, Time, etc.
T: Terminate the system after printing the current state.
- The printing is same as 'P' command. ");
}else if(!strcmp(buffer, "T ") || !strcmp(buffer, "t ")){
printf("Print the average turnaround time, and terminate the system. ");
printf("Average turn around time is %f. ", calc_ta_time_avg(ta));
if (pipe(fd)) {
perror("pipe");
} else if ((temp_pid = fork()) == -1) {
perror("fork");
} else if (temp_pid == 0) {
close(fd[0]);
if(DEBUG) cpu2proc(&cpu, &pcbTable[cpu.pid]);
reporterProcess(fd[1], pcbTable, current_time, ta,
running_states, ready_states, blocked_states);
} else {
close(fd[1]);
while(i=(read(fd[0],&c,1)) > 0);
}
printf(" ");
printf("Terminate the system. ");
return;
}else{
printf("Unknown command. ");
}
fputs(buffer, stdout);
printf(" ");
printf("> ");
fflush(stdout);
}
fclose(fp);
}
int argc;
int main(char argc, char *argv[]){
int rv = 0, fd[2], pid;
char fname[MAX_STR];
if(argc != 2){
printf("program failed");
return ;
}
printf("> ");
strcpy(fname, argv[1]);
if (pipe(fd)) {
perror("pipe");
rv = 1;
} else if ((pid = fork()) == -1) {
perror("fork");
rv = 2;
} else if (pid > 0) {
close(fd[0]);
commanderProcess(fd[1]);
} else {
close(fd[1]);
processManagerProcess(fd[0], fname);
}
return rv;
}
Explanation / Answer
Related Questions
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.