I'm very new to using these different types of system calls in linux, Which led me to much confusion. With this, I am only asking for a push in the right direction/a start, not for a completion.
Using fork
, exec
, and wait
, I have read up on them, but that still hasn't really helped me in my situation.
What I have to do is the following,
Print a promt and wait for the user to enter a command with up to four arguments or options. "exit" will stop the program.
Some examples, mkdir blah
, creates the directory and then prompts for a new command, touch blah/this blah/that blah/there
.
I have to call fork
to create a child process to execute the command entered, then call exec
in the child process to make the child become the program that is to be executed (this part confuses me even more), and finally call wait
in the parent process so that the interpreter doesn't print next prompt until command is finished.
What would be the best way to accomplish this? As in, what's the best way to read in the command/arguments/options and then have them executed?
I would assume it would be better to do this is a do..while
with the while
condition being what checks for "exit"
What little I have done, which isn't much, I know.
int main() {
char command[25];
pid_t pid;
int rs;
cout << "Enter command: ";
cin >> command;
while(strcmp(command, "exit") != 0) {
pid = fork();
if (pid == 0) { //child process
rs = execl("echo", command);
} else { // parent process
cout << "Enter a command: ";
cin >> command;
}
}
return 0;
}
A general breakdown of what each of those system calls do:
fork: Forks the current process. Literally when fork is called, execution is paused at the call to fork, and the entire program is copied into a new process space that is a child of the original. Then both processes continue execution from right after the fork call in parallel. You'll need to get the PID in order to tell if the program that is currently being executed is the child or parent.
exec: Pauses execution of current process, wipes over the current process in memory with the designated new program to run. It then runs the new program instead.
wait: Suspends the current process until at least one child process terminates. It is a wrapper around waitpid() which allows you to pause the current process's execution and wait for a change in the state of a child process of the current process (which may be a clone of itself or a new program swapped in by exec)
Here is some code demoing waiting and forking (but no exec) from a class I took at University:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <semaphore.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/wait.h>
const int BUFFER_SIZE = 1000;
void copySegment(int i, int segmentSize, FILE * fin, FILE * fout) {
// Does not need to be shown to prove point
}
int main(int argc, char * argv[]) {
int i;
sem_t * sem;
pid_t pid;
FILE * fin, * fout;
struct stat sbuf;
int fileSize, fileDescriptor, segmentSize;
fin = fopen(argv[1], "r");
fout = fopen("forkcopy.txt", "w");
fileDescriptor = fileno(fin);
fstat(fileDescriptor, &sbuf);
fileSize = sbuf.st_size;
segmentSize = fileSize / 4;
sem = sem_open("sem", O_CREAT | O_EXCL, 0644, 4);
sem_unlink("sem");
for (i = 0; i < 4; i++) {
pid = fork();
if (pid < 0)
printf("Fork error.\n");
else if (pid == 0)
break;
}
if (pid != 0) {
while (pid = waitpid(-1, NULL, 0)) {
if (errno == ECHILD)
break;
}
sem_destroy(sem);
fclose(fin);
fclose(fout);
exit(0);
} else {
sem_wait(sem);
copySegment(i, segmentSize, fin, fout);
sem_post(sem);
exit(0);
}
}