I am trying to understand fork, sleep... commmands.
I want to do 4 children and one parent operation exactly in this order. Parent> child1> child4> child2> child3.
The tasks of these processes are as I wrote in the code below. In this code I have 1 parent, 3 child and 1 grandson(child4 is a grandson). How can I make transactions in this order? I tried to put a sleep on each if's but the program finished without waiting for input in child2.
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(void)
{
int n1 = fork();
int n2 = fork();
int input;
if (n1 > 0 && n2 > 0) {
int n3=fork();
if(n3==0)
{ //3th child
printf("3th child process id is %d (parent: %d) \n", getpid(),getppid());
if(input == getppid()) {
printf("matched!\n"); }
else {
printf("not matched!\n"); }
printf("program ended\n");
}
else {
printf("parent process id is %d (parent: %d)\n", getpid(),getppid());
sleep(1);
}
}
else if (n1 == 0 && n2 > 0)
{
printf("1th child process id is %d (parent: %d)\n",getpid(),getppid());
FILE * fp;
fp = fopen ("xx.txt", "w+");
printf("file was created...\n");
sleep(1);
}
else if (n1 > 0 && n2 == 0)
{
printf("2th child process id is %d (parent: %d) \n", getpid(),getppid());
printf("Enter a key: \n");
scanf("%d",&input);
FILE * fp;
fp = fopen ("xx.txt", "w+");
fprintf(fp, "%d", input);
printf("input has been written to the txt file!\n");
}
else {
//4th child
printf("4th child grandson process id is %d (parent: %d)\n", getpid(),getppid());
printf("say me password!\n");
}
return (0);
}
You could try something like:
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(void)
{
const size_t nb_child = 3;
size_t children_count = nb_child;
while (children_count > 0) {
int pid = fork();
if (pid == 0) {
printf("child process id is %d (parent: %d) \n", getpid(),getppid());
if (children_count == 1) {
int pid2 = fork();
if (pid2 == 0) {
printf("child process id is %d (parent: %d) \n", getpid(),getppid());
sleep(2);
} else
wait(NULL);
}
return 0;
} else {
//father
}
children_count--;
}
while (children_count != nb_child) {
wait(NULL);
children_count++;
}
return 0;
}
The "difficult" part is to wait for all children before exiting
Related
The program creates a child proccess and the child does the proper work in order to see if its pid is even or odd
And for some reason even if the pid is even i get that it is odd , also the parent waits for child
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main() {
pid_t pid, mypid, cpid;
int flag;
pid = getpid();
printf("Process %d creates new process\n\n", pid);
cpid = fork();
if (cpid == 0) {
cpid=getpid();
printf("\n----[%d] child\n", cpid);
if (cpid % 2 == 0) {
flag = 1;
} else {
flag = 0;
}
exit(0);
} else if (cpid != 0) {
wait(NULL);
mypid = getpid();
printf("\n[%d] parent of [%d]\n", mypid, cpid);
if (flag == 1) {
printf("\nThe child pid is even");
} else if(flag ==0) {
printf("\nThe child pid is odd");
} else {
printf("\nSomething went wrong");
}
} else {
perror("Fork failed");
}
return 0;
}
I have challenge to implement two task using named pipes in C:
Multiple producer - single consumer
Single producer - multiple consumer
I already did single producer - single consumer problem but I'm not sure how can I start solving above tasks, can you advice me in that by recomanding suitable approach and methods?
Here is my single producer - single consument code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
const int dataAmountToProduce = 10;
int value = 0;
int const buforSize = 50;
void processProducer()
{
int savePipe;
while (value < dataAmountToProduce)
{
savePipe = open("pipe", O_WRONLY);
value++;
char str[buforSize];
sprintf(str, "%d", value);
printf("Producer %d produces value: %s\n", getpid(), str);
write(savePipe, str, buforSize);
if (value == dataAmountToProduce)
{
break;
}
}
close(savePipe);
}
void processConsumer()
{
int readPipe;
while (value < dataAmountToProduce)
{
readPipe = open("pipe", O_RDONLY);
char buf[buforSize];
read(readPipe, buf, buforSize);
printf("Consumer %d consumes value: %s\n", getpid(), buf);
value = atoi(buf);
if (value == dataAmountToProduce)
{
break;
}
}
close(readPipe);
}
main()
{
mkfifo("pipe", 0600);
if (fork() == 0)
{
printf("Creating producer process %d\n", getpid());
processProducer();
printf("Producer process %d finished work\n", getpid());
exit(0);
}
if (fork() == 0)
{
printf("Creating consumer process %d\n", getpid());
processConsumer();
printf("Consumer process %d finished work\n", getpid());
exit(0);
}
wait(NULL);
printf("Both child processes of process %d finished work.\n", getpid());
exit(0);
}
OK, I found a solution myself in both cases I added this block to producer method:
if (value == valuesAmountToProduce)
{
printf("Producent process %d sent END signal\n", getpid());
for (int i = 0; i <= amountOfConsumers; i++)
{
write(savePipe, "END", wielkoscBufora);
}
In consumer code I'm checking if passed value is END, if yes then I'm breaking a loop:
if (strcmp(buf, "END") == 0)
{
printf("Consumer process %d recived END signal\n", getpid());
break;
}
And I solved my problem in this way, for multiple producer - single consumer we can omit consumer loop as it is in first code snippet because there will be only one consumer.
Hello I am writing a c program which runs then waits for it to complete then executes an if condition. However after the child process completes it does not execute the rest of code in parent. Any advice would be great. Thanks
AA
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
int main() {
int D, waitVal3, waitVal4;
D = fork();
if(D == 0)
{
execv("DD", 0);
}
if(D != 0)
{
printf("\nPid = %d Code AA: created proccess Pid = %d (code DD)\n", getpid(), D);
}
waitVal3 = (waitVal4);
//NEVER ENTERS THIS CONDITION
printf("WAIT VAL: %d", waitVal3);
if(waitVal3 == D)
{
printf("\nPid = %d Code AA: process Pid = %d terminated\n", getpid(), D);
}
return 0;
}
DD
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
int main (int argc, char *argBB[]) {
int C3, waitVal, waitVal2, ps;
C3 = fork();
if(C3 != 0)
{
printf("\nPid = %d Code DD: created proccess Pid = %d (code CC)\n", getpid(), C3);
}
if( C3 == 0 )
{
execv("CC", 0);
printf("\nexecv failed\n");
exit(0);
}
if(C3 < 0)
{
printf("Fork failed");
exit(1);
}
ps = fork();
if(ps != 0)
{
printf("\nPid = %d Code DD: created proccess Pid = %d (code ps)\n", getpid(), ps);
}
if( ps == 0 )
{
char command[50];
strcpy(command, "ps -u username");
system(command);
exit(11);
kill(ps, SIGKILL);//KILL PROCCESS PS HERE
}
waitVal = wait(waitVal2);
if(waitVal == ps)
{
printf("\nPid= %d Code DD: process Pid = %d terminated\n", getpid(), ps);
printf("\nPid = %d Code DD: killing process Pid = %d\n", getpid(), C3);
kill(C3, SIGKILL);
printf("\nPid= %d Code DD: process Pid = %d terminated\n", getpid(), C3);
printf("\nPid = %d Code DD: terminating\n", getpid());
exit(7);
}
return 0;
}
You didn't call wait() and your execv() was incorrect...
... compare this with your version to check the differences...
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <string.h>
#include <sys/wait.h>
#include <errno.h>
int main() {
char *args[2] = {"DD", NULL};
int D, waitVal3, waitVal4, rc, waitStatus;
D = fork();
if ( D == -1 )
{
printf("fork failed\n");
exit(1);
}
if(D == 0)
{
// ORIG: execv("DD", args);
rc = execv("/some/path/to/DD", args);
printf("execv failed: errno: %d\n", errno);
exit(1);
}
if(D != 0)
{
printf("\nPid = %d Code AA: created proccess Pid = %d (code DD)\n", getpid(), D);
}
waitVal4 = wait(&waitStatus);
waitVal3 = (waitVal4);
//ORIGINALLY - NEVER ENTERS THIS CONDITION
printf("WAIT VAL: %d", waitVal3);
if(waitVal3 == D)
{
printf("\nPid = %d Code AA: process Pid = %d terminated\n", getpid(), D);
}
return 0;
}
I tried to come up with a solution using waitpid() instead of wait().
Why this didn't work?
int main() {
char *args[2] = {"DD", NULL};
int waitVal3, waitVal4, rc, waitStatus;
pid_t D;
D = fork();
if ( D == -1 )
{
printf("fork failed\n");
exit(1);
}
if(D == 0)
{
// ORIG: execv("DD", args);
if( execv("/home/ubuntu/workspace/C/DD", args) == -1 ){
printf("execv failed: errno: %d\n", errno);
exit(1);
}
if( waitpid( D, &waitStatus, 0 ) == -1 ){
printf("Error waiting child process.\n");
exit(1);
};
printf("\nPid = %d Code AA: process Pid = %d terminated\n", getpid(), D);
}
return 0;
}
Observation:
If I put the waitid() statement outside the child process, this works.
The following code worked:
if(D == 0)
{
// ORIG: execv("DD", args);
if( execv("/home/ubuntu/workspace/C/DD", args) == -1 ){
printf("execv failed: errno: %d\n", errno);
exit(1);
}
}
if( waitpid( D, &waitStatus, 0 ) == -1 ){
printf("Error waiting child process.\n");
exit(1);
};
printf("\nPid = %d Code AA: process Pid = %d terminated\n", getpid(), D);
This means that the parent process was able detect the termination of child process in this case. My understanding is that waitpid() should work whether
in child or parent process. I am firm believer that it did work. However, the consequent printf() statement in the child process didn't get executed since the child process got terminated.
I'm trying to create n = 10 child processes and make its execute a peace of code ..
However it creates 14 child processes indifferent of n.
Why is that?
This is the sample code :
#include <stdlib.h>
#include <stdio.h>
int main()
{
printf("It worked! ");
return 0;
}
And this is the main program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
int main (int argc, char *argv[])
{
int n = 10;
pid_t pid;
int status = 0;
int fd2[2];
int i = 0;
while (i < n)
{
/*create the pipe */
if (pipe(fd2) == -1)
{
fprintf(stderr, "Problem at pipe: %s\n", strerror(errno));
exit(1);
}
/*create fork*/
pid = fork();
if (pid == -1)
{
fprintf(stderr, "Problem at fork: %s\n", strerror(errno));
exit(1);
}
else if (pid == 0) /*in child*/
{
close(fd2[0]);
close(1);
dup2(fd2[1], 1);
close(fd2[1]);
execl("sample.bin", "sample.bin", NULL);
fprintf(stderr, "Problem at exec: %s", strerror(errno));
exit(1);
}
/* in parent */
close(fd2[1]);
char line[255];
if (n = read(fd2[0], line, 254))
{
printf("%d The message is: %s\n", i, line);
}
close(fd2[0]);
wait(&status);
i++;
}
return 0;
}
I corrected the code, now the output is what I've expected. And of course another problem was that I used at read the same variable n.
I modified from this:
if (n = read(fd2[0], line, 254))
{
printf("%d The message is: %s\n", i, line);
}
To this:
int m;
while((m = read(fd2[0], line, 254) > 0)
{
printf("%d The message is: %s\n", i, line);
}
I read the following file (file.txt) line by line:
1
-5
6
-8
-33
21
The father sends negative numbers to a process, and sends positive numbers to a second process:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
void Fils1(int *tube1)
{
int n;
int cpt = 0;
close (tube1[1]);
while (read (tube1[0], &n, 1) >0)
{
cpt+=n;
}
printf("Son 1, count : %i \n", cpt);
exit (1) ;
}
void Fils2(int *tube2)
{
int n;
int cpt = 0;
close (tube2[1]);
while (read (tube2[0], &n, 1) >0)
{
cpt+=n;
}
printf("Son 2, count : %i \n", cpt);
exit (1) ;
}
int main(int argc, char *argv[])
{
FILE* file;
int n;
file = fopen (argv[1], "r");
if (file == NULL){
printf("Error open file %s\n", argv[1]);
exit(1);
}
int tube1[2];
int tube2[2];
if (pipe(tube1) != 0)
{
fprintf(stderr, "Error tube 1\n");
return EXIT_FAILURE;
}
if (pipe(tube2) != 0)
{
fprintf(stderr, "Error tube 2\n");
return EXIT_FAILURE;
}
int pid1 = fork();
if(pid1 == 0)
{
printf("Creation of the first son ! \n");
Fils1 (tube1);
}
else
{
int pid2 = fork();
if(pid2 == 0)
{
printf("Creation of the second son ! \n");
Fils2 (tube2);
}
else
{
printf("I'm the father! \n");
close (tube1[0]);
close (tube2[0]);
while (!feof(file))
{
fscanf (file,"%d",&n);
if (n>0)
{
write (tube1[1], &n, 1);
}
else
{
write (tube2[1], &n, 1);
}
}
fclose (file);
if(wait(NULL) == -1)
{
printf("Error wait()\n");
exit(1);
}
}
}
return EXIT_SUCCESS;
}
Each son is counting, and displays it on screen.
When I execute, I have only that :
I'm the father!
Creation of the first son!
Creation of the second son!
When I expect also
Son1, count : 28
Son2, count : 46
The problem is you're not closing the pipes as you should.
Child1 should close tube2 (both ends)
Child2 should close tube1 (both ends);
The parent should close write end (after the while)