How can I have 3 processes running in parallel? Is this solution below correct?
In my solution I put some code to see the time elapsed and I think this is tunning in sequential mode. I need to put pid1, pid2 and pid3 running at the same time.
pid = fork();
if(pid == 0) {
//code...
exit(EXIT_SUCCESS);
} else if(pid > 0) {
pid1 = fork();
if(pid1 == 0) {
//pid1 code...
exit(EXIT_SUCCESS);
} else if(pid1 > 0) {
waitpid(pid1, &status, 0);
} else {
printf("Fork error %d.\n", errno);
}
pid2 = fork();
if(pid2 == 0) {
//pid2 code...
exit(EXIT_SUCCESS);
} else if(pid2 > 0) {
waitpid(pid2, &status, 0);
} else {
printf("Fork error %d.\n", errno);
}
pid3 = fork();
if(pid3 == 0) {
//pid3 code...
exit(EXIT_SUCCESS);
} else if(pid3 > 0) {
waitpid(pid3, &status, 0);
} else {
printf("Fork error %d.\n", errno);
}
waitpid(pid, &status, 0);
}
You keep waiting for one child to complete before you launch the next. Try something like:
for (int i = 0; i < 3; ++i)
{
pid = fork();
if (pid < 0)
error
if (pid == 0)
{
child does thing
exit
}
}
for (int i = 0; i < 3; ++i)
{
wait(&status);
}
EDIT
So just change your code to something like this and wait at the end.
if (pid2 == 0)
{
//pid2 code...
exit(EXIT_SUCCESS);
}
else
if (pid2 < 0)
{
printf("Fork error %d.\n", errno);
}
//....same outline for 3, etc.
Check out my wrap program, specifically the code for wrapc. It forks itself twice, execs one child into wrap, reads, writes to wrap, then reads back in the other child.
Your question is somewhat vague -- are you seeing 3 processes running in parallel or not?
the way your code is written you are exiting the child processes straight away.
Related
I'm trying to pipe two different processes to implement the terminal's functionality "|".
I need the new child to execute a command itself, and fork another process to execute a different command using the first process's output, then output the final process's results on the terminal.
Here's my code, I keep the original parent untouched because I need to continue executing the other parts of my program afterwards.
int exec_pipe(char **args, int index, int *i, char**** jobs){
int fd1[2];
pid_t pid, wpid;
int status;
int savedStdOut = dup(1);
int savedStdIn = dup(fileno(stdin));
if (pipe(fd1)==-1)
{
fprintf(stderr, "Pipe Failed" );
return 1;
}
pid = fork();
if (pid < 0)
{
fprintf(stderr, "fork Failed" );
return 1;
}else if (pid == 0)
{
// Child process
close(fd1[0]);
dup2(fd1[1], 1);
printf("%s\n", args[index - 1]);
if (execvp(args[0], args) == -1)
{
printf("command not found\n");
}
int childId = fork();
if(childId < 0){
fprintf(stderr, "fork Failed" );
return 1;
}else if(childId == 0){
// child of child of parent
fdopen(fd1[1], "r");
dup2(fd1[1], savedStdOut);
if (execvp(args[index + 1], args) == -1)
{
printf("command not found\n");
}
exit(EXIT_FAILURE);
}else {
// parent of child of child of parent
do
{
wpid = waitpid(pid, &status, WUNTRACED);
} while (!WIFEXITED(status) && !WIFSIGNALED(status)); // wait for child until it's exited or been killed
fdopen(savedStdIn, "r");
close(fd1[0]);
close(fd1[1]);
}
}else{
// Parent process
do
{
wpid = waitpid(pid, &status, WUNTRACED);
} while (!WIFEXITED(status) && !WIFSIGNALED(status)); // wait for child until it's exited or been killed
}
return 1;
}
I'm getting a "No such file or directory" error with the program ending with exit code 9.
Solved it based on some comments, thanks all!
int fd1[2];
pid_t pid;
// allocate two pipe sets
if (pipe(fd1) < 0)
{
perror("Failed to create pipe.");
return EXIT_FAILURE;
}
// launch first child process.
if ((pid = fork()) < 0)
{
perror("Failed to fork child(1)");
return EXIT_FAILURE;
}
if (pid == 0)
{
// child
// stdout = fd1(write)
if(strcmp(args[0], args[index - 1]) == 0)
{
dup2(fd1[WRITE], STDOUT_FILENO);
close(fd1[READ]);
close(fd1[WRITE]);
execlp(args[0], args[0], (char*) NULL);
fprintf(stderr, "failed to execute '%s'\n", args[0]);
exit(1);
}else{
dup2(fd1[WRITE], STDOUT_FILENO);
close(fd1[READ]);
close(fd1[WRITE]);
execlp(args[0], args[0], args[index - 1], (char*) NULL);
fprintf(stderr, "failed to execute '%s'\n", args[0]);
exit(1);
}
}else
{
// parent
// fork once more.
if ((pid = fork()) < 0)
{
perror("Failed to fork child(2)");
return EXIT_FAILURE;
}
if (pid == 0)
{
// child of child
// stdin = fd1(read)
dup2(fd1[READ], STDIN_FILENO);
close(fd1[WRITE]);
close(fd1[READ]);
execlp(args[index + 1], args[index + 1], (char*) NULL);
fprintf(stderr, "failed to execute '%s'\n", args[index + 1]);
exit(1);
}else{
int status;
close(fd1[READ]);
close(fd1[WRITE]);
waitpid(pid, &status, 0);
}
}
I have a function in C which creates a child process and makes it run execvp.
int Execute(char **arg)
{
pid_t pid;
int status;
if ((pid=fork()) == 0)
{
execvp(arg[0],arg);
perror("Execvp error");
exit(1);
}
else if (pid > 0)
{
waitpid(pid, &status, 0);
}
else
{
perror("Fork error");
exit(2);
}
}
Now I want to alter the function to actually run execvp several times (for example 5), and make the parent process wait for all the children to finish. Tried wrapping it all in for loop, but execvp gets executed just once. I know that basically execvp 'replaces' the current program code, but have no idea whether the iteration does not go on.
Thank you for your help!
First, loop around the process creation collecting the child PIDs
pid_t pid[5];
int i;
for (i = 0; i < 5; i++) {
if ((pid[i]=fork()) == 0) {
execvp(arg[0],arg);
perror("Execvp error");
_exit(1);
}
if (pid[i] < 0) {
perror("Fork error");
}
}
Second, loop around the waitpid call for every valid PID.
for (i = 0; i < 5; i++) {
if (pid[i] > 0) {
int status;
waitpid(pid[i], &status, 0);
if (status > 0) {
// handle a process sent exit status error
}
} else {
// handle a proccess was not started
}
}
pid_t pid;
if ((pid == fork()) == 0){
if (execvp(arg[0], arg) < 0) {
printf("%s: Command not found.\n", arg[0]);
exit(0);
}
}
if (background == 0 )
{
int status;
if (waitpid(pid, &status, 0) < 0)
printf("waitfg: waitpid error");
while(waitpid(-1, 0, WNOHANG) >= 0){}
}
else
{
printf("%d %s", pid, cmdline);
}
I have this code for my program and I am trying to have the parent reap all child processes and the problem is that it is still not reaping. I am trying to use the code:
while(waitpid(-1, 0, WNOHANG) >= 0){}
in order to reap but it seems to not get rid of the zombie process. What am I supposed to do to reap instead then
Also I am not sure if I am doing background right here.
Your code is wrong:
pid_t pid;
if ((pid == fork()) == 0){ // PROBLEM HERE
if (execvp(arg[0], arg) < 0) {
printf("%s: Command not found.\n", arg[0]);
exit(0);
}
}
you compare pid which isn't initialized with result of fork() => Undefined behavior (and after, you compare the result of this comparison with 0)
You should replace if ((pid == fork()) == 0){ by if ((pid = fork()) == 0){
I am making my own shell in C. This is my basic code for running a process:
pid_t childpid;
int status;
int ret = 0;
if (strcmp(line[0], "exit") == 0) {
return;
}
childpid = fork();
if (childpid >= 0) {
if (childpid == 0) {
ret = execvp(line[0], &line[0]);
if (ret == -1) {
printf("ERROR\n");
exit(0);
}
exit(ret);
} else {
waitpid(childpid, &status, 0);
ret = WEXITSTATUS(status);
}
} else {
perror("fork");
exit(-1);
}
Where line is a "string array" holding the commands to run.
Now say I want to run a background process - I have to use sigset. A parent doesn't wait for a backgrounded child process, right? How do I handle this without the child becoming a background process?
I'm trying to implement a subshell in C. I already have a normal shell, which looks like this:
int status;
pid = fork();
if (pid < 0) {
exit(1);
}
else if (pid == 0) {
if (execvp(node->command.program, node->command.argv) < 0) {
exit(1);
}
}
else {
waitpid(pid, &status, 0);
}
I'm trying to figure out how a subshell works, and how it differs from the code above.
Thanks in advance.