I want to fork 3 child processes and have each process execute a function and busy wait until they are complete. The 3rd process is a countdown timer so once the runtime reaches 0 I will use an IPC to tell the other processes to exit. I have written the functions besides the IPC part and they run individually but I can't get fork() to create the 3 child processes to each execute a specific function.
int main(int argc, char *argv[]) {
pid_t child_onepid, child_twopid, child_threepid, pid;
for (i = 0; i < 3; ++i) {
pid = fork();
if (pid) {
continue;
} else if (pid == 0 && i == 0) {
show_time();
} else if (pid == 0 && i == 1) {
show_uptime();
} else if (pid == 0 && i == 2) {
show_timer(runtime);
} else {
printf("fork error\n");
exit(1);
}
}
return EXIT_SUCCESS;
}
This is my output
Time: 06/28/2014 18:55:57PM
Timer: 00:09
>Timer: 00:09
6:55pm up 171 day(s), 10:49, 17 users, load average: 0.34, 0.38, 0.43
6:55pm up 171 day(s), 10:49, 17 users, load average: 0.34, 0.38, 0.43
Your code looks fine to me, except your error test will never hit because the if(pid) will trigger on -1.
Besides that, are you supper sure that your functions are not returning and then going around their own copy of the for loop, that would explain the output... so I added some break to make sure of that.
But I've not tested the code.
int main(int argc, char *argv[]) {
pid_t pid;
for (int i = 0; i < 3; ++i) {
pid = fork();
if (pid == -1) {
perror("fork error\n");
exit(EXIT_FAILURE);
} else if (pid > 0)
continue;
} else if (i == 0) {
show_time();
break;
} else if (i == 1) {
show_uptime();
break;
} else if (i == 2) {
show_timer(runtime);
break;
}
}
return EXIT_SUCCESS;
}
Related
I'm trying to make 3 kinds of processes(1 proc1, 4 proc2 and 5 proc3) and make them run at the same time. I wrote some code, but there seems to be no overlapping, even with sleep() function, i.e. processes always run in same sequence. I'm wondering if this is a correct way to create multiple processes.
int main() {
setbuf(stdout, NULL);
setbuf(stderr, NULL);
int pid;
pid = fork();
if(pid < 0) {
fprintf(stderr, "Fork error.");
exit(2);
} else if(pid == 0){ //Child
proc1();
exit(0);
} else { //Parent
for(int i=0; i<4; i++) {
int child2ID = fork();
if(child2ID == 0) {
proc2();
exit(0);
}
}
for(int i=0; i<5; i++) {
int child3ID = fork();
if(child3ID == 0) {
proc3();
exit(0);
}
}
}
while(wait(NULL)) {
if(errno == ECHILD)
break;
}
return 0;
}
I am required to create a process tree with relationships expressed as in the picture.
The problem is I must create all "nodes" in the order of the alphabet. I have gotten this far but my order is not consistent. I believe I am using waitpid incorrectly?
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char **argv)
{
pid_t pidA, pidB, pidC, pidD, pidE, pidF, pidG, pidI;
pidA = fork();
if (pidA < 0)
{
perror("A");
exit(1);
}
else if (pidA == 0)
{
printf("%d: A\n", getpid());
pidB = fork();
if (pidB < 0)
{
perror("B");
exit(1);
}
else if (pidB == 0)
{
printf("%d: B\n", getpid());
waitpid(pidD, NULL, 0);
pidE = fork();
if (pidE < 0)
{
perror("E");
exit(1);
}
else if (pidE == 0)
{
printf("%d: E\n", getpid());
waitpid(pidG, NULL, 0);
pidI = fork();
if (pidI < 0)
{
perror("E");
exit(1);
}
else if (pidI == 0)
{
printf("%d: I\n", getpid());
}
else
{
;
}
}
else
{
pidF = fork();
if (pidF < 0)
{
perror("F");
exit(1);
}
else if (pidF == 0)
{
printf("%d: F\n", getpid());
}
else
{
;
}
}
}
else
{
pidC = fork();
if (pidC < 0)
{
perror("B");
exit(1);
}
else if (pidC == 0)
{
printf("%d: C\n", getpid());
waitpid(pidF, NULL, 0); // !
pidG = fork();
if (pidG < 0)
{
perror("G");
exit(1);
}
else if (pidG == 0)
{
printf("%d: G\n", getpid());
}
else
{
;
}
}
else
{
pidD = fork();
if (pidD < 0)
{
perror("B");
exit(1);
}
else if (pidD == 0)
{
printf("%d: D\n", getpid());
}
else
{
;
}
}
}
}
else
{
;
}
return 0;
}
Output is not consistent so I think this part wouldn't help much.
5644: A
5645: B
5646: C
5647: D
5648: G
5650: F
5649: E
5651: I
The principal problem here is that waitpid only suffices for synchronization when all of the processes are linearly related (i.e., parent process, child process, "grandchild" process, etc.).
However, your processes, as exhibited by the diagram, are not linearly related. You can see this issue arise when you call waitpid(pidD, NULL, 0); from within the B process. Not only is pidD not defined in this context but the D process is not a child of the B process and so waitpid is inappropriate.
#EOF makes a good point that trying to run multiple processes in series defeats the purpose of having multiple processes. However, if you just want to do this exercise as a fun brain teaser, I'd recommend setting up pipes in the original process and then closing the write end when the appropriate process wants to signal that it has exited. The process that is waiting for the first process to end can call select on the read end.
I am trying to create a daemon that forks two processes that will run infinitely to check time and receive messages between processes. When I run the program without the steps to create a daemon it all works fine. However once I try to create a daemon, it seems the child processes I fork become zombies.
This is the output of ps -ajx
2678 3628 3628 2678 pts/2 3628 S+ 1000 0:00 ./assignment_daemon
3628 3629 3629 3629 ? -1 Zs 1000 0:00 [assignment_daem] <defunct>
And here is the C code,
int main()
{
int pid = fork();
if(pid > 0)
{
printf("Parent process..\n");
sleep(10);
exit(EXIT_SUCCESS);
}
else if (pid == 0)
{
printf("Child process..\n");
if(setsid() < 0)
{
exit(EXIT_FAILURE);
}
umask(0);
if(chdir("/") < 0)
{
exit(EXIT_FAILURE);
}
int x;
for(x = sysconf(_SC_OPEN_MAX); x>=0;x--)
{
close(x);
}
openlog("assignment_daemon", LOG_PID|LOG_CONS,LOG_USER);
syslog(LOG_INFO,"assignment_daemon started...");
int SIZE = 2;
pid_t child_pids[SIZE];
int num_of_children = SIZE;
for(int i = 0; i < num_of_children; i++)
{
if((child_pids[i] = fork()) < 0)
{
perror("Error: failed to fork!\n");
syslog(LOG_ERR,"failed to fork...");
exit(EXIT_FAILURE);
}
else if(child_pids[i] == 0){
if(i == 0)
{
syslog(LOG_INFO,"Forked message_server...");
//run message server
char * argv_list[] = {"message_queue_server",NULL};
execv("./assignment_queue_server",argv_list);
}
if(i == 1)
{
syslog(LOG_INFO,"Forked time_check...");
//run time check
char * argv_list[] = {"time_check_process",NULL};
execv("./time_check_process",argv_list);
}
}
}
int status;
pid_t pid;
while(num_of_children > 0)
{
pid = wait(&status);
printf("Child %d exited with status 0x%x\n",pid,status);
syslog(LOG_INFO,"child has exited...");
num_of_children--;
}
syslog(LOG_INFO,"assignment_daemon ended...");
}
return 0;
}
Any help would be appreciated.
Thanks.
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
}
}
I'm trying to write a small program that forks processes from a single parent. Currently my code does this a few times but then the children create more child processes, which I want to eliminate.
int main() {
pid_t c;
for (int i = 0; i < 5; i++) {
c = fork();
if(c < 0) {
perror("fork");
exit(1);
}
else if( c > 0 ) {
printf("parentID = %d, childID = %d\n", getppid(i), getpid(i));
}
}
}
I'm not sure how to modify it so that fork is only forking from the parent though.
EDIT: thanks for the help, got the solution:
int main() {
pid_t c;
for (int i = 0; i < 5; i++) {
c = fork();
if(c < 0) {
perror("fork");
exit(1);
}
else if( c > 0 ) {
printf("parentID = %d, childID = %d\n", getppid(i), getpid(i));
}
else {
exit(0);
}
}
}
nothing in the posted code is recognizing the child (0 == pid)
so a child hits (and skips) the two 'if' statements.
hits the end of the loop,
branches back to the top of the loop, calls fork()....etc.
Suggest: adding
elseif( 0 == pid )
{ // then child ...
exit( EXIT_SUCCESS );
}
The child process does not enter any part of the if block, and just loops back to the top of the for loop creating more children. Also, the if (n > 0) block gets run for the parent, not the child, since fork returns 0 to the parent and the child's pid to the parent.
Change if (n > 0) to if (n == 0), and call exit() at the bottom of the block to prevent the child from continuing. Also, getpid() and getppid() don't take any arguments.
int main() {
pid_t c;
for (int i = 0; i < 5; i++) {
c = fork();
if(c < 0) {
perror("fork");
exit(1);
}
else if( c == 0 ) {
printf("parentID = %d, childID = %d\n", getppid(), getpid());
exit(0); // <-- here
}
}
}