how to synchronize two process - c

Hello I'm struggling right now with C language and process so basically I've just learnt about pipe and I want to use them just to exercise myself on it, so I want to try a code that basically use two child and 1 father, by one child the user enter some number then this child send those numbers to the other child and then this second child send them to the father who show them.
here my code so far
`
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
int main(int argc, char const *argv[])
{
pid_t son1;
pid_t son2;
int Pipe1[2];
int pipe2[2];
int sent=0;
int sent2=0;
int recive=0;
int recive2=0;
int j=0;
int mem[3];
if (pipe(Pipe1)==-1)
{
printf("error pipe1");
exit(0);
}
if (pipe(pipe2)==-1)
{
printf("error pipe2");
exit(0);
}
son1=fork();
if (son1==0)
{
close(Pipe1[0]);
//close(pipe2[0]);
//close(pipe2[1]);
printf("i'am the child 1\n");
for (int i = 0; i < 3; i++)
{
printf("type your number \n");
scanf("%d",&sent);
write(Pipe1[1],&sent,sizeof(int));
}
close(Pipe1[1]);
}
son2=fork();
if (son2==0)
{
close(Pipe1[1]);
close(pipe2[0]);
printf("i'am the son number 2 \n");
recive=read(Pipe1[0],&sent,sizeof(int));
while(recive == sizeof(int))
{
printf("nb reçu %d \n",sent);
mem[j]=sent;
recive= read(Pipe1[0],&sent,sizeof(int));
j++;
}
close(Pipe1[0]);
for (int p = 0; p < 3; p++)
{
sent2=mem[p];
printf("sent2 %d",sent2);
write(pipe2[1],&sent2,sizeof(int));
}
close(pipe2[1]);
when i run this code it does work but not how i expect, the commmunication between children work but not between child 2 and the father actualy if you look at the second part of the code of son2 "mem[]" value is not the same before close(pipe[1]) and after and this is why the comunication is mestup but i realy dont know how the value can change.. if someone can explain me it will be really kind of him
`

You create two pipes in the parent which are shared with the children, and the children do not share a pipe with each other. The easiest thing is probably to move the 2nd pipe to the child and have it fork the 2nd child:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int main(void) {
int parent_child[2];
if(pipe(parent_child) == -1) {
printf("pipe failed\n");
exit(1);
}
if(!fork()) {
close(parent_child[0]);
int child_grand_child[2];
if(pipe(child_grand_child) == -1) {
printf("pipe failed\n");
exit(1);
}
printf("child write\n");
write(child_grand_child[1], "1", 1);
if(!fork()) {
char buf[1];
ssize_t n = read(child_grand_child[0], buf, sizeof buf);
printf("grand child read\n");
write(parent_child[1], buf, n);
exit(0);
}
close(parent_child[1]);
wait(&(int) {0});
exit(0);
}
close(parent_child[1]);
char buf[1];
ssize_t n = read(parent_child[0], buf, sizeof buf);
printf("parent read %*s\n", n, buf);
wait(&(int) {0});
}
which outputs:
child write
grand child read
parent read 1

Related

C communicate parent and child to increase and print counter

I am trying to write a program so that the parent and child process can communicate back and forth between each other. The parent process and the child process ought to print the values from 1-100 where each process prints the value incrementing it by 1 each time. Now the issue I face is that, I know nothing much about pipes. What I gather from reading materials online is that I can use a pipe to read and write values. I have leveraged this to print something in the child process, and send back something to the parent. Now, I am not sure how to get the parent to return to the child after printing for itself? I know my code is probably all wrong, but I am really not sure what I should do.
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, const char * argv[]) {
int fd[2];
if (pipe(fd)== -1){
printf("An error occured while opening the pipe\n");
}
int id = fork();
int i = 0;
if (id == 0){
close(fd[0]);
printf("In child: %d", i);
i ++;
write(fd[1], &i, sizeof(int));
close(fd[1]);
} else {
wait(NULL);
close(fd[1]);
int y;
read(fd[0],&y, sizeof(int));
close(fd[0]);
}
}
To keep it simple, it's up to you to check return values and handle errors. This will only do it between 0 - 9 and you will have to expand the mathematics.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[])
{
int pipefd_1[2];
int pipefd_2[2];
pid_t cpid;
pipe(pipefd_1);
pipe(pipefd_2);
cpid = fork();
if (cpid == 0) { /* Child reads from pipe 1, writes to pipe 2*/
char cval[] = {'0'};
close(pipefd_1[1]); /* Close unused write and read ends */
close(pipefd_2[0]);
while (atoi(cval) != 9) {
read(pipefd_1[0], cval, 1);
printf("Child print %d\n", atoi(cval));
cval[0] += 1;
write(pipefd_2[1], cval, 1);
}
} else {
char cval[] = {'0'}; /* Parent writes buf to pipe 1 */
close(pipefd_1[0]); /* Close unused read end */
close(pipefd_2[1]);
while (atoi(cval) != 9) {
write(pipefd_1[1], cval, 1);
read(pipefd_2[0], cval, 1);
printf("Parent print %d\n", atoi(cval));
cval[0] += 1;
}
}
}
Output

How to get return value from child process to parent?

I'm supposed to return the sum of first 12 terms of Fibonacci series from child process to parent one but instead having 377, parent gets 30976.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
pid_t childpid;
int i, fib_sum=0, fib1=1, fib2=1, temp, status;
childpid=fork();
if(childpid!=0)
{
wait(&status);
fprintf(stderr, "%d\n", status);
}
else
{
for(i=1; i<=12; i++)
{
temp=fib1;
fib_sum=fib1+fib2;
fib1=fib_sum;
fib2=temp;
}
fprintf(stderr, "%d\n", fib_sum);
return fib_sum;
}
}
What am I doing wrong?
I'm supposed to return the sum of first 12 terms of Fibonacci series
from child process to parent one but instead having 377, parent gets
30976.
Process exit status is limited in value, therefore it is not the best way to communicate a value between child and parent.
One of the solution is to pass the calculated value using pipes.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
pid_t childpid;
int i, fib_sum=0, fib1=1, fib2=1, temp, status;
int fd[2];
int val = 0;
// create pipe descriptors
pipe(fd);
childpid = fork();
if(childpid != 0) // parent
{
close(fd[1]);
// read the data (blocking operation)
read(fd[0], &val, sizeof(val));
printf("Parent received value: %d\n", val);
// close the read-descriptor
close(fd[0]);
}
else // child
{
// writing only, no need for read-descriptor:
close(fd[0]);
for(i=1; i<=12; i++)
{
temp = fib1;
fib_sum = fib1+fib2;
fib1 = fib_sum;
fib2 = temp;
}
// send the value on the write-descriptor:
write(fd[1], &fib_sum, sizeof(fib_sum));
printf("Child send value: %d\n", fib_sum);
// close the write descriptor:
close(fd[1]);
return fib_sum;
}
}
Test:
Child send value: 377
Parent received value: 377
If you can't use pipes, which would be the optimal solution here, you could save the result to a file that the parent would read from. Pass the name of the file to save the result to from parent to child. In your child process, you would do:
int main(int argc, char *argv[])
{
int fib_sum=0;
if (argc <= 1)
{
print_usage();
return 1;
}
//... calculate fib_sum
FILE *f = fopen(argv[1], "w");
if (f == NULL)
{
printf("Error opening file!\n");
return 1;
}
fprintf(f, "%d", fib_sum);
return 0;
}
Then in your parent process:
int n = 0;
FILE* f;
//... spawn child and wait
FILE *f = fopen(file_name, "r");
fscanf(f, "%d", &n);

two child process communicating through named pipe

I have main program which creates two children and one named pipe(FIFO). Each children executes a program called “sendSignal" via execv(). One of the argument of the “sendSignal” is the FIFO in the main program.
The children are going to send signal to each other. It decided with an argument in the main (in variable firstShooter)program which signal shoot first.
I want to know how these two children can send each other their pid through this named pipe.
Following is the main program:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
/* this program should be provided with 2 arguments */
int main(int argc, char **argv)
{
char str1[15];
char str2[15];
char fileDescriptor[15];
char *my_args[4];
char *myfifo = "myfifo";
int fd, pipeCheck;
pid_t pid1, pid2, wid;
/* If the user does not provide the argument to determin which child is firing first */
if(argc != 2)
{
fprintf(stderr,"%s: 2 arguments needed, got %d\n",argv[0],argc-1);
exit(1);
}
/* create the FIFO (named pipe) */
pipeCheck = mkfifo(myfifo, 0666);
/* check if the named pipe was created properly if not output an error */
if(pipeCheck == -1)
{
fprintf(stderr, "%s: Error creating named pipe: %s\n",argv[0], strerror(errno));
exit(1);
}
pid1 = fork();
if (pid1 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid1 == 0)
{
my_args[0] = "sendSignal";
my_args[1] = argv[1];
my_args[2] = myfifo; // the named pipe as arguemnt
my_args[3] = NULL;
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by first child...");
exit(-1);
}
pid2 = fork();
if(pid2 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid2 == 0)
{
my_args[0] = "sendSignal";
my_args[1] = argv[1];
my_args[2] = myfifo; // named pipe as arguemnt
my_args[3] = NULL;
// printf("this is converted = %s\n",my_args[1]);
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by second child...");
exit(-1);
}
close(fd);
unlink(myfifo);
wid = wait(NULL);
return 0;
}
here is the sendSignal:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
void sig_handler(int signo)
{
if(signo == SIGUSR1)
printf("signal received\n");
}
int main(int argc, char **argv)
{
char abspath[256] = "";
getcwd(abspath, 256);
strrchr(abspath, '/');
if(signal(SIGUSR1,sig_handler) == SIG_ERR)
printf("\n Cannot catch the signal\n");
char *myfifo = "myfifo";
int firstShooter = atoi(argv[1]); //define the first process to send the signal
int fd;
char str1[15];
char str2[15];
char pid1[15];
char pid2[15];
fd = open(argv[2],O_RDWR);
if(firstShooter == 1)
{
sprintf(pid1,"%d",getpid());
write(fd,pid1,sizeof(pid1));
}
if(firstShooter == 2)
{
sprintf(pid2,"%d",getpid());
write(fd,pid2,sizeof(pid2));
}
read(fd,str1,sizeof(str2));
read(fd,str2,sizeof(str2));
close(fd);
printf("str1 = %s\n",str1);
printf("str2 = %s\n",str2);
return 0;
}
Both of your children processes got the same arguments:
my_args[0] = "sendSignal";
my_args[1] = argv[1];
my_args[2] = myfifo; // the named pipe as argument
my_args[3] = NULL;
firstShooter parameter doesn't make sense as process cannot identify itself as first or second.
I suggest to add one more parameter - process index. sendSignal function logic can be modified this way:
char pid1[15];
char pid2[15];
int processIndex = atoi(argv[3]);
fd = open(argv[2],O_RDWR);
if (processIndex == firstShooter)
{
// Send firstShooter PID
sprintf(pid1,"%d",getpid());
write(fd,pid1,sizeof(pid1));
// Got the other PID
read(fd,pid2,sizeof(pid2));
}
else
{
// Got the firstShooter PID
read(fd,pid1,sizeof(pid1));
// Send the other PID
sprintf(pid2,"%d",getpid());
write(fd, pid2, sizeof(pid2));
}
close(fd);
printf("pid1 = %s\n",pid1);
printf("pid2 = %s\n",pid2);
There are some issues in the way you have implemented.
1.Calling two fork() in the main program will be creating more than two child processes.(3 child processes). So give a condition to check that you are calling the next fork in the context of the parent itself.
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
/* this program should be provided with 2 arguments */
int main(int argc, char **argv)
{
int * status;
char str1[15];
char str2[15];
char fileDescriptor[15];
char *my_args[4];
char *myfifo = "myfifo";
int fd, pipeCheck;
pid_t pid1, pid2, wid;
/* If the user does not provide the argument to determin which child is firing first */
if(argc != 2)
{
fprintf(stderr,"%s: 2 arguments needed, got %d\n",argv[0],argc-1);
exit(1);
}
/* create the FIFO (named pipe) */
pipeCheck = mkfifo(myfifo, 0666);
/* check if the named pipe was created properly if not output an error */
if(pipeCheck == -1)
{
fprintf(stderr, "%s: Error creating named pipe: %s\n",argv[0], strerror(errno));
exit(1);
}
pid1 = fork();
if (pid1 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid1 == 0)//child
{
// printf("pid1=0\n");
printf("i am child 1 %d\n",getpid());
my_args[0] = "sendSignal";
my_args[1]=malloc(6);
sprintf(my_args[1] , "%d", getpid());
//my_args[1]="1";
printf("p%s\n",my_args[1]);
my_args[2] = myfifo; // the named pipe as arguemnt
my_args[3] ="1";
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by first child...");
exit(-1);
}
else if(pid1>0)// parent
{
// printf("pid1 %d",pid1);
waitpid(pid1,&status,WIFEXITED(status));
pid2 = fork();
// printf("p:%d",pid2);
if(pid2 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid2 == 0)
{
printf("i am child 2 %d\n",getpid());
my_args[0] = "sendSignal";
my_args[1]=malloc(6);
sprintf(my_args[1] , "%d", getpid());
my_args[2] = myfifo; // named pipe as arguemnt
my_args[3] = "2";
// printf("this is converted = %s\n",my_args[1]);
execv("sendSignal",my_args);
fprintf(stderr,"sendSignal cannot be executed by second child...");
exit(-1);
}
printf("done\n");
}
close(fd);
wait(NULL);
fd=open("fifo1", O_RDONLY);
char * space=(char *)malloc(6);
read(fd,space,6);
printf("from fifo1 %s",space);
fd=open("fifo2", O_RDONLY);
//char * space=(char *)malloc(6);
read(fd,space,6);
printf("from fifo2 %s",space);
//unlink(myfifo);
wid = wait(NULL);
unlink(myfifo);
return 0;
}
2. The two child process are accessing the same pipe. Pipe is for one way communication with an end for reading and another for writing. So create two pipes each for a process. I would suggest better not to go for pipes.

2 way pipe communication. cant spend from child

I can't get this basic communication to work.
All I want to do, is send information via the child's stdout to the parents file descriptor.
I am getting a seg fault.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define READ 0
#define WRITE 1
int main(void){
int fdRead[2];
int pid, i, num;
FILE* output;
char mystring [100];
char c;
pid = fork();
if(pid){
FILE * read;
close(fdRead[WRITE]);
read = fdopen(fdRead[READ], "r");
fgets(mystring,100, read);
printf("parent %d",mystring );
} else {
/* child */
dup2(fdRead[WRITE], STDOUT_FILENO);
close(fdRead[READ]);
close(fdRead[WRITE]);
printf("child" );
}
exit(0);
}
Your code does nothing about pipe.
Code for communicating between parent and child processes using pipe looks as follows
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define READ 0
#define WRITE 1
int main(void){
int pipefd[2];
pid_t pid;
int i, num;
if (pipe(pipefd)<0) { /* create pipe */
perror("pipe");
exit(-1);
}
char mystring [100];
char c;
pid = fork();
if(pid<0){
perror("fork");
exit(-1);
} else if (pid=1) { /* parent */
char *mystring = "message to child";
write(pipefd[WRITE],mystring,strlen(mystring);
sleep(1); /* wait for child read message */
char buf[128]; /* buffer to receive data from child */
read(pipefd[READ],buf, sizeof buf);
close(pipefd[READ]);
close(pipefd[WRITE]);
printf("Returned from child %s",buf );
return 0;
} else { /* child */
char *s="send from child: ";
char buf[128];
read(pipefd[READ],buf, sizeof buf);
write(pipefd[WRITE],s,strlen(s));
close(pipefd[READ]);
close(pipefd[WRITE]);
return 0;
}
}

Using Pipes in C

I wrote the following code to help me understand how pipes work in C.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
struct sum_ {
int a;
int b;
};
int main (void) {
int pipe1[2];
int pid;
struct sum_ sum;
if ( (pipe(pipe1) != 0)){
printf("pipe(): %d %s\n", errno, strerror(errno));
exit(1);
}
pid = fork();
if (pid == -1) {
printf("fork(): %d %s\n", errno, strerror(errno));
exit(1);
}
else if (pid == 0) { // Child
close(pipe1[0]);
sleep(5);
sum.a = read(pipe1[0], &sum.a, sizeof(sum.a));
printf("Your number was: %d", sum.a);
}
else { // Father
close(pipe1[1]);
printf("\nWrite a number: \n");
char a[4];
sum.a = atoi(fgets(a, 4, stdin));
write(pipe1[1], &sum.a, sizeof(sum.a));
}
return 0;
}
The code has a father and a son process. It is quite simple, the father uses a pipe to send a number to the son and the son displays the number for the user.
I always get -1 as result. What have I done wrong?
close(pipe1[0]);
sleep(5);
sum.a = read(pipe1[0], &sum.a, sizeof(sum.a));
You close the file descriptor pipe1[0], then read from it (and so get -1 returned). You make the equivalent error in the father, too. I think you mean to close pipep1[0] here and pipe1[1] in the father
Also, when you fix that, lthough you're reading into sum.a by passing the address, you're also setting it from the return value, which will overwrite what you read.

Resources