/* _POSIX_SOURCE is required. Otherwise, POSIX system calls such as fdopen() cannot be called */
#define _POSIX_SOURCE
#include <stdio.h>
#include <stdlib.h> /*atoi(), exit()*/
#include <sys/types.h> /* fork(), pipe(), getpid(), open() */
#include <sys/wait.h> /* wait() */
#include <unistd.h> /* fork(), pipe(), getpid(), read(), close() */
#include <time.h> /* ctime() */
#include <limits.h> /* PIPE_BUF */
#include <fcntl.h> /* open() */
#include <string.h> /* strlen() */
#define READ_END 0
#define WRITE_END 1
#define LOG_FILE "./log"
int main(int argc, char* argv[]) { /* main() */
int i=0; /* dummy variable */
pid_t pid; /*return value of fork()*/
time_t clock;
int pfd[2]; /* for using pipe() */
int status; /* exit status of child processes */
char current_time[64];
FILE *fp; /* file pointer for pipe */
int fd; /* file descriptor for log file */
/*check params*/
if(argc!=3) { /*incorrect # of params*/
/*show error msg*/
printf("Usage: proj2 [# of CPU-bound processes] ");
printf("[# of I/O-bound processes]\n");
exit(1); /*exit status 1*/
}
/*
* Create a pipe.
*/
if(pipe(pfd) < 0) {
perror("pipe");
exit(2);
}
/* forking CPU-bound processes */
for(i=0; i<atoi(argv[1]); i++) {
/*error if fork() < 0*/
if((pid=fork())<0) {
/*print err msg*/
perror("fork");
exit(3); /*exit status 2*/
}
if(pid==0) { /*a child*/
printf("cpu_child: pid=%d\n", (int)getpid());
/* close the read end */
close(pfd[READ_END]);
/* attach stdout to the pipe */
dup2(pfd[WRITE_END], STDOUT_FILENO);
/* overwrite the image with that of cpu_proc */
execl("./cpu_proc", "cpu_proc", (char *)0);
perror("exec");
exit(0); /*exit successfully*/
} else { /*the parent*/
/*print child pid*/
printf("CPU-bound child %d created.\n", pid);
}
}
/* forking I/O-bound processes */
for(i=0; i<atoi(argv[2]); i++) {
/*error if fork() < 0*/
if((pid=fork())<0) {
/*print err msg*/
printf("fork() failed\n");
exit(2); /*exit status 2*/
}
if(pid==0) { /*a child*/
printf("io_child: pid=%d\n", (int)getpid());
/* close the read end */
close(pfd[READ_END]);
/* attach stdout to the pipe */
dup2(pfd[WRITE_END], STDOUT_FILENO);
/* overwrite the image with that of cpu_proc */
execl("./io_proc", "io_proc", (char *)0);
perror("exec");
exit(0); /*exit successfully*/
} else { /*the parent*/
/*print child pid*/
printf("I/O-bound child %d created.\n", pid);
}
}
/* close the write end */
close(pfd[WRITE_END]);
/* associate a file stream with the read end */
if((fp=fdopen(pfd[READ_END], "r")) == NULL) {
perror("Unable to associate the read end");
exit(4);
}
while(fgets(current_time, PIPE_BUF, fp)) {
printf("current_time = %s", current_time);
if((fd=open(LOG_FILE, O_WRONLY | O_APPEND)) < 0) {
printf("error opening log file\n");
exit(5);
}
if(write(fd, current_time, strlen(current_time))<0) {
printf("error writing log file\n");
perror("log");
exit(6);
}
if(close(fd)) {
printf("error closing file\n");
exit(7);
}
}
fclose(fp);
for(i=0; i<(atoi(argv[1]) + atoi(argv[2])); i++) {
wait(&status);
}
/* exit successfully */
exit(0);
}