In this program, mulproc.c , I am trying to run the executables from two programs I made (one counts the amount of alphabetic characters in a file and the other one counts five specific special characters). I am trying to make a parent process (just mulproc.c in this case) that runs these two programs each in their own child process, so just create two child processes from a parent basically. The two programs each have their own output, but around their respective outputs, I also want to output two messages for each, indicating when it starts and when it ends. However, I am getting incorrect and varying outputs with each different attempt (I do not want to post them all here). Outputs of my two programs are even being written in between each other, so I believe I may be utilizing the waitpid() function incorrectly. Whats more is I am having trouble printing out the correct child processes PID's in the parent process. Please ignore the two "Child Process" number labels for debugging purposes being out of place. Here is mulproc.c ...
#include <stdio.h>
#include "count.h"
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <stdbool.h>
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
int main( int argc, char *argv[] )
{
pid_t pid1;
pid_t pid2;
int status1;
int status2;
pid1 = fork();
if ( pid1 < 0 )
{
perror( "ERROR! Fork failed!" );
exit(1);
}
if ( pid1 == 0 )
{
// CHILD PROCESS CODE
printf( "\nChild Process 2:\npid :%d\nppid:%d\n\n", getpid(), getppid() );
printf( "CHILD <PID: %d> process is executing testspecial program!\n", getpid() );
char *specialchar[] = { "./testspecial" , NULL };
execv( specialchar[0], specialchar );
}
if ( pid1 > 0 )
{
pid2 = fork();
if ( pid2 == 0 )
{
// ANOTHER CHILD PROCESS CODE
printf( "\nChild Process 1:\npid :%d\nppid:%d\n\n", getpid(), getppid() );
printf( "CHILD <PID: %d> process is executing testalphabet program!\n", getpid() );
char *alphabetchar[] = { "./testalphabet" , NULL };
execv( alphabetchar[0], alphabetchar );
}
else if ( pid2 > 0 )
{
// PARENT PROCESS CODE
printf( "\nParent Process:\npid:%d\nppid :%d\n", getpid(), getppid() );
// if child1 terminated...
if ( waitpid( pid1, &status1, 0 ) == pid1 )
{
printf( "CHILD <PID: %d> process has done with testalphabet program! See the results above!\n", getpid() );
}
// if child2 terminated...
if ( waitpid( pid2, &status2, 0 ) == pid2 )
{
printf( "CHILD <PID: %d> process has done with testspecial program! See the results above!\n", getpid() );
}
}
}
return 0;
}
and here is just ONE of the incorrect outputs...
Parent Process:
pid:3166
ppid :3149
Child Process 1:
pid :3168
ppid:3166
CHILD <PID: 3168> process is executing testalphabet program!
Child Process 2:
pid :3167
ppid:3166
CHILD <PID: 3167> process is executing testspecial program!
A -> 0
B -> 0
C -> 0
D -> 0
E -> 0
F -> 0
G -> 0
H -> 3
I -> 0
J -> 0
K -> 0
L -> 0
M -> 0
N -> 0
O -> 0
P -> 0
Q -> 0
, -> 1
R -> 0
S -> 0
T -> 0
. -> 1
U -> 0
: -> 1
V -> 0
; -> 1
W -> 0
! -> 1
X -> 0
Y -> 0
Z -> 3
a -> 0
b -> 0
c -> 0
d -> 0
e -> 0
f -> 0
g -> 0
h -> 3
i -> 0
j -> 0
k -> 0
CHILD <PID: 3166> process has done with testalphabet program! See the results above!
l -> 0
m -> 0
n -> 0
o -> 0
p -> 0
q -> 0
r -> 0
s -> 0
t -> 0
u -> 0
v -> 0
w -> 0
x -> 0
y -> 0
z -> 0
CHILD <PID: 3166> process has done with testspecial program! See the results above!
I WANT the output to look something like this...
CHILD <PID: 3168> process is executing testalphabet program!
A -> 0
B -> 0
C -> 0
...
...
...
x -> 0
y -> 0
z -> 0
CHILD <PID: 3168> process has done with testalphabet program! See the results above!
CHILD <PID: 3167> process is executing testspecial program!
, -> 1
. -> 1
: -> 1
; -> 1
! -> 1
CHILD <PID: 3167> process has done with testspecial program! See the results above!
Really really appreciate it if anyone could clear up my mistakes here...I am brand new to using system calls like these, so hopefully I am not messing up too much in this instance.
If you don't want the processes to run in parallel, then you have to wait for the first one to finish before launching the second one. So written in pseudo-code, rather than do this:
pid1 = launch_proc1();
pid2 = launch_proc2();
waitpid(pid1);
waitpid(pid2);
You have to do:
pid1 = launch_proc1();
waitpid(pid1);
pid2 = launch_proc2();
waitpid(pid2);
How to translate the pseudocode into proper c is left as an exercise to the reader.
EDIT: Some clarification on launc_procX
:
launc_procX
is supposed to implement the fork
/exec
combo.
int launc_proc1()
{
int pid = fork();
if ( pid < 0 )
{
perror( "ERROR! Fork failed!" );
exit(EXIT_FAILURE);
}
else if (pid == 0)
{
// CHILD PROCESS CODE
printf( "\nChild Process 2:\npid :%d\nppid:%d\n\n", getpid(), getppid() );
printf( "CHILD <PID: %d> process is executing testspecial program!\n", getpid() );
char *specialchar[] = { "./testspecial" , NULL };
execv( specialchar[0], specialchar );
// Handle failure of exec (this is important !!!!!)
perror( "ERROR! exec failed!" );
exit(EXIT_FAILURE);
}
// because execv is supposed to never return,
// only parent is able to reach this point
return pid;
}
Naturally you can combine launch_proc1
and launch_proc2
into a single int launch_proc(const char *cmd)