Reading from pipe goes wrong - c

I want to read the integer from the pipe and then print it, but everytime it prints garbage value. Someone that can help me out?
int main()
{
int pid1 = fork();
int fd1[2];
pipe(fd1);
if (pid1 == 0) // Child process
{
int x;
close(fd1[1]);
read(fd1[0], &x, sizeof(int));
printf("I'm the First Child and I received: %d\n", x); // <--- Here it prints garbage value
close(fd1[0]);
}
else // Parent process
{
int x = 5;
close(fd1[0]);
write(fd1[1], &x, sizeof(int));
close(fd1[1]);
}
}

I had to fork() after creating the pipes. So the code looks like this:
int main()
{
int fd1[2];
pipe(fd1);
int pid1 = fork();
if (pid1 == 0) // Child process
{
int x;
close(fd1[1]);
read(fd1[0], &x, sizeof(int));
printf("I'm the First Child and I received: %d\n", x);
close(fd1[0]);
}
else // Parent process
{
int x = 5;
close(fd1[0]);
write(fd1[1], &x, sizeof(int));
close(fd1[1]);
}
}

Related

Passing data from one pipe to another

I am new to pipes but how do I redirect the output from child_1 to the input for child_2?
I am trying to pass the value from the parent to child_1, adds 1 to the value, print the value, then use that output and pass it into child_2, add 1 again, and finally print the value.
The code below has the right output value for child_1, but not for child_2, how do I redirect the output from child_1 to the input for child_2?
Here is my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char * argv[]) {
int fd[2];
int PID;
pipe(fd); //fd1[0] = read | fd1[1] = write
PID = fork(); // spawn child_1
if (PID < 0){ // failed to fork
perror("Unable to fork child");
exit(1);
}
if (PID > 0) { // parent
int value = 100;
// since parent is only writing, close the reading end of pipe
close(fd[0]);
// write the data to the write end of the pipe
write(fd[1], &value, sizeof(int));
// then close the writing end of the pipe (parent)
close(fd[1]);
/**********************************************************/
} else { // child 1
int val = 0;
// read from the parent pipe
read(fd[0], &val, sizeof(int));
val += 1;
// is this how to redirect from one pipe to another?
dup2(fd[0], fd[1]);
// this prints the right value for val (val [101] = value [100] + 1)
printf("Child [%d] read value %d\n", getpid(), val);
// close the reading end of the pipe for child_1
close(fd[0]);
int PID2 = fork(); // make child 2
if(PID2 == 0) { // child 2
int val2 = 0;
close(0); // close stdin since we are trying to take the value from child_1
// read input from child_1 pipe (NOT WORKING?)
read(fd[0], &val2, sizeof(int));
val2 += 1;
printf("Child [%d] out %d\n", getpid(), val2);
close(fd[0]);
}
}
return EXIT_SUCCESS;
}
The way you have things set up, there's no need to use dup2() or any other I/O redirection.
Add #include <unistd.h> to the list of include files (and remove #include <string.h> — it seems to be unused)
Delete: dup2(fd[0], fd[1]);
Delete: close(fd[0]);
Delete: close(0);
Before the second fork(), add write(fd[1], &val, sizeof(val));
When you have close(fd[0]) in the first child, you effectively close fd[0] for the second child too.
You should check the status of the read and write operations before using the results.
Those changes lead to:
/* SO 7383-1815 */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
int fd[2];
int PID;
pipe(fd);
PID = fork();
if (PID < 0)
{
perror("Unable to fork child");
exit(EXIT_FAILURE);
}
if (PID > 0)
{
int value = 100;
close(fd[0]);
write(fd[1], &value, sizeof(int));
close(fd[1]);
}
else
{
int val = 0;
if (read(fd[0], &val, sizeof(val)) != sizeof(val))
{
perror("read() failed in child 1");
exit(EXIT_FAILURE);
}
val += 1;
printf("Child [%d] read value %d\n", getpid(), val);
if (write(fd[1], &val, sizeof(val)) != sizeof(val))
{
perror("write() failed in child 1");
exit(EXIT_FAILURE);
}
int PID2 = fork();
if (PID2 == 0)
{
int val2 = 0;
if (read(fd[0], &val2, sizeof(val2)) != sizeof(val2))
{
perror("read() failed in child 2");
exit(EXIT_FAILURE);
}
val2 += 1;
printf("Child [%d] out %d\n", getpid(), val2);
close(fd[0]);
close(fd[1]);
}
}
return EXIT_SUCCESS;
}
When compiled (cleanly with options set fussy), it produces output such as:
Child [34520] read value 101
Child [34521] out 102
I believe this is what was wanted.

Child process not waking up after a sigsuspend (C)

I have to create a program that generates 2 childs and each of them has to generate a random number. After that the child who generated the lowest number has to send a SIGUSR1 to the other child. In my case i wanna send a SIGCONT to child 1 to wake him up so that he can send SIGUSR1 to the other process but child 1 doesn't wake up.. any help? Thanks in advance.
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdbool.h>
#define N 2
int getRand(int upper)
{
srand(time(0));
int random;
random = rand() % upper;
return random;
}
void sighandler(int signo)
{
if (signo == SIGUSR1)
{
printf("Received SIGUSR1, my PID is %d\n\n", getpid());
exit(0);
}
if (signo == SIGUSR2)
{
printf("Received SIGUSR2.. I woke up! (My PID is %d)\n\n", getpid());
}
}
int main (int argc, char **argv)
{
int i, r, m, b;
int status = 0;
int tabcpid[N], ppid, wpid;
int fd[2], fdbool[2]; //fd [0 = read] [1 = write]
sigset_t set, zeromask;
struct sigaction action;
//Gestione segnali
sigemptyset(&zeromask);
sigemptyset(&action.sa_mask);
action.sa_handler = sighandler;
action.sa_flags = 0;
sigemptyset(&set);
sigaddset(&set, SIGUSR1);
sigprocmask(SIG_BLOCK, &set, NULL);
if (sigaction(SIGUSR1, &action, NULL) == -1)
{
perror("Error while doing sigaction.\n\n");
}
if (pipe(fd) == -1)
{
printf("Error opening pipe fd!\n\n");
exit(1);
}
if (pipe(fdbool) == -1)
{
printf("Error opening pipe fdbool!\n\n");
exit(1);
}
printf("\nPipes opened successfully. Forking ...\n\n");
sleep(2);
for (i = 0; i < N; i++)
{
if ((tabcpid[i] = fork()) == 0) //Child code
{
int n = atoi(argv[1]);
m = getRand(n);
b = 20;
ppid = getppid();
printf("I'm the son process #%d with PID: %d\n", i + 1, getpid());
printf("Random number in interval 0 - %d: %d\n\n", n, m);
sleep(2);
if (i == 0)
{
close(fd[0]);
write(fd[1], &m, sizeof(int));
close(fd[1]);
printf("Suspending..\n\n");
sigsuspend(&zeromask);
printf("So' ripartitoo\n\n");
/*
close(fdbool[1]);
read(fdbool[0], &b, sizeof(int));
close(fdbool[0]);
printf("--- b value: %d\n\n", b);
if (b == 0)
{
printf("I'm the process %d and I got the lowest number, SIGUSR1 sent to my brother.\n\n", getpid());
kill(tabcpid[1], SIGUSR1);
}
sleep(2);
*/
}
else
{
close(fd[1]);
read(fd[0], &r, sizeof(int));
close(fd[0]);
int lower = (r < m) ? r : m;
int igotlower = (m < r) ? 1 : 0;
printf("--- igotlower value: %d\n\n", igotlower);
close(fdbool[0]);
write(fdbool[1], &igotlower, sizeof(int));
close(fdbool[1]);
//printf("Got %d from other child process, while i got %d.\nThe smallest number is %d.\nMy PID is %d and the other process' PID is %d.\n\n", r, m, lower, getpid(), tabcpid[0]);
//sleep(2);
if (igotlower == 1)
{
printf("I'm the process %d and I got the lowest number, SIGUSR1 sent to my brother..\n\n", getpid());
kill(tabcpid[0], SIGUSR1);
sigsuspend(&zeromask);
}
else
{
printf("I'm sending SIGCONT to %d\n\n", tabcpid[0]);
kill(tabcpid[0], SIGCONT);
sigsuspend(&zeromask);
}
}
sleep(2);
}
sleep(2);
}
wait(&status);
close(fdbool[1]);
read(fdbool[0], &b, sizeof(int));
close(fdbool[0]);
kill(tabcpid[b], SIGUSR1);
wait(&status);
printf("It's me the father... it's all over, we're done!\n\n");
sleep(2);
return 0;
}

How to make parent and child bidirectional pipe in C

I am trying to do a bidirectional pipe, the parent sends n number (int) to the child and the child return them doubled. I can't figure out what's my error?
I scanned the number n is the parent, sent it through fd1[1], and then proceeded to send those n numbers for the child to double.
In the child, I read the number n and then for every number I read, I double and send back.
int main(){
int pid,n,c,p,k,nbread;
char buf1[2], buf2[2];
int fd1[2], fd2[2];
pipe(fd1);
pipe(fd2);
pid=fork();
if(pid==0){
close(fd1[1]);
close(fd2[0]);
read(fd1[0],buf2,sizeof(int));
n = atoi(buf2);
for(int i = 0; i<n;i++){
nbread = read(fd1[0],buf2,sizeof(int));
sleep(3);
if(nbread == -1)
exit(1);
c = atoi(buf2);
c = c*2;
sprintf(buf2,"%d",c);
write(fd2[1],buf2, sizeof(int));
}
close(fd1[0]);
close(fd2[1]);
}
close(fd1[0]);
close(fd2[1]);
printf("Enter integer: ");
scanf("%d",&p);
sprintf(buf1,"%d",p);
write(fd1[1],buf1,sizeof(int));
sleep(3);
for(int i=0;i<n;i++){
sprintf(buf1,"%d",i);
write(fd1[1],buf1,sizeof(int));
read(fd2[0],buf1,sizeof(int));
printf("number is: %s",buf1);
}
close(fd1[1]);
close(fd2[0]);
wait(NULL);
return 0;}
Fixing the parent loop to test p and not n fixes the main problems. Making sure that the buffers are big enough is a good idea too. Writing the whole buffer is OK though not necessarily ideal.
This code works; it has more debugging output in it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
int pid, n, c, p, k, nbread;
char buf1[12], buf2[12];
int fd1[2], fd2[2];
pipe(fd1);
pipe(fd2);
pid = fork();
if (pid == 0)
{
close(fd1[1]);
close(fd2[0]);
read(fd1[0], buf2, sizeof(buf2));
n = atoi(buf2);
printf("Child read %d\n", n);
for (int i = 0; i < n; i++)
{
printf("child dozes...\n");
sleep(3);
printf("child wakes...\n");
nbread = read(fd1[0], buf2, sizeof(buf2));
if (nbread == -1)
{
fprintf(stderr, "child exits after read failure\n");
exit(1);
}
c = atoi(buf2);
c = c * 2;
sprintf(buf2, "%d", c);
write(fd2[1], buf2, sizeof(buf2));
printf("Child wrote [%s]\n", buf2);
}
close(fd1[0]);
close(fd2[1]);
printf("Child done\n");
exit(0);
}
else
{
close(fd1[0]);
close(fd2[1]);
printf("Enter integer: ");
scanf("%d", &p);
sprintf(buf1, "%d", p);
write(fd1[1], buf1, sizeof(buf1));
printf("Parent wrote [%s]\n", buf1);
printf("parent dozes...\n");
sleep(3);
printf("parent wakes...\n");
for (int i = 0; i < p; i++)
{
sprintf(buf1, "%d", i);
write(fd1[1], buf1, sizeof(buf1));
printf("parent wrote [%s]\n", buf1);
read(fd2[0], buf2, sizeof(buf2));
printf("number is: %s\n", buf2);
}
close(fd1[1]);
close(fd2[0]);
wait(NULL);
}
return 0;
}
Sample output:
Enter integer: 4
Parent wrote [4]
parent dozes...
Child read 4
child dozes...
parent wakes...
parent wrote [0]
child wakes...
Child wrote [0]
child dozes...
number is: 0
parent wrote [1]
child wakes...
Child wrote [2]
child dozes...
number is: 2
parent wrote [2]
child wakes...
Child wrote [4]
child dozes...
number is: 4
parent wrote [3]
child wakes...
Child wrote [6]
Child done
number is: 6
The code puts the child code and parent code into separate if and else blocks. It doesn't detect failures in pipe() or fork() which is suboptimal. The child exit(0) is not crucial any more.

SIGUSR1 - kill sigaction in C

In the C language create a program that creates two processes and connects them via pipe.
The first descendant redirects its' stdout into the pipe and writes (space separated) pairs of random numbers into it (function rand). Delay the output of the numbers by 1 second.
The second descendant redirects the pipe output to it's stdin, redirects it's stdout into a file called out.txt in the current directory.
The parent process waits 5 seconds and then sends SIGUSR1 to the first process (number generator). This should perform a correct termination of both processes. It waits for the sub-processes to terminate (wait function) and terminates itself.
I really need help with:
The first descendant has to treat the SIGUSR1 signal (sigaction function) and in case of receiving such signal it prints a string “TERMINATED” to it's stderr and terminates.
FILE *file;
file = fopen(NAZEV, "a+");
int pipefd[2];
pipe(pipefd);
pid_t pid1;
int retcode;
pid1=fork();
if(pid1 == 0) // child 1
{
close(roura[0]);
printf("child1...\n");
dup2(roura[1], STDOUT_FILENO);
int i = 0;
while(i < 6)
{
i++;
int a = rand();
int b = rand();
sleep(1);
printf("%d %d\n", a, b);
}
close(roura[1]);
exit(45);
}
else if (pid1 < 0)
{
printf("Fork selhal\n");
exit(2);
}
else
{
pid_t pid2;
pid2 = fork();
if (pid2 == 0) //child 2
{
close(roura[1]);
dup2(roura[0], STDIN_FILENO);
printf("child2...\n");
int i = 0;
while(i < 5)
{
i++;
int c;
int d;
scanf("%d %d", &c, &d);
printf("%d %d\n", c, d);
fprintf(file,"%d %d\n", c, d);
}
printf("child2 end\n");
exit(0);
}
else if (pid2 < 0)
{
printf("Fork error\n");
exit(2);
}else
{
sleep(5);
kill(pid1, SIGUSR1);
wait(&pid1); //wait for child 1
wait(&pid2); //wait for child 2
printf("parent end\n");
exit(0);
}
}
exit(0);
}
Adda signal handler to sigusr1 that prints to stderr and exits.
Try this, adapted to compile in cygwin:
#include <stdio.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
#ifndef STDOUT_FILENO
# define STDOUT_FILENO 1
#endif
void sig_handler(){
fprintf(stderr,"TERMINATED");
exit(0);
}
void main(int argc, char ** argv){
FILE *file;
file = fopen("NAZEV", "a+");
int pipefd[2];
int roura[2] ;
pipe(pipefd);
pid_t pid1;
int retcode;
pid1=fork();
if(pid1 == 0) // child 1
{
close(roura[0]);
printf("child1...\n");
dup2(roura[1], STDOUT_FILENO);
if (signal(SIGUSR1, sig_handler) == SIG_ERR){
printf("\ncan't catch SIGUSR1\n");
exit(13);
}
int i = 0;
while(i < 6)
{
i++;
int a = rand();
int b = rand();
sleep(1);
printf("%d %d\n", a, b);
}
close(roura[1]);
exit(45);
}
else if (pid1 < 0)
{
printf("Fork selhal\n");
exit(2);
}
else
{
pid_t pid2;
pid2 = fork();
if (pid2 == 0) //child 2
{
close(roura[1]);
dup2(roura[0], STDIN_FILENO);
printf("child2...\n");
int i = 0;
while(i < 5)
{
i++;
int c;
int d;
scanf("%d %d", &c, &d);
printf("%d %d\n", c, d);
fprintf(file,"%d %d\n", c, d);
}
printf("child2 end\n");
exit(0);
}
else if (pid2 < 0)
{
printf("Fork error\n");
exit(2);
}else
{
sleep(5);
kill(pid1, SIGUSR1);
wait(&pid1); //wait for child 1
wait(&pid2); //wait for child 2
printf("parent end\n");
exit(0);
}
}
exit(0);
}
You need to register a signal handler using sigaction if you want to override the default action. For SIGUSR1, the default action is to terminate the process.

What is the correct way to read from multiple pipes?

So in my program, the user gives three arguments. Then, I pipe it into three children.
Two children all do their own calculations, then exits. The last child displays the results.
The parent waits for all children to finish, then it simply terminates the program.
A summary of what the children do:
inputs are a, b, c.
child0: c0 = a*b
child1: c1 = b*c
overview: printf("%d %d", c0, c1);
I can't figure out how to get the overview to print out correctly. It keeps printing out weird corrupted characters or boxes.
Anyone have any advice on how to do it correctly? I read a book, but it only went over in detail single child-parent pipes. This deals with multiple children, and I guess that's where I got confused. Thanks for your help!
Code below:
int main(int argc, char *argv[]) {
int fd[4];
int a, b, c, c0, c1, status;
char char0[10];
char char1[10];
pid_t child0;
pid_t child1;
pid_t overview;
// Set argv to ints
a = atoi(argv[1]);
b = atoi(argv[2]);
c = atoi(argv[3]);
// Pipe
pipe(fd);
// child0
if((child0 = fork()) == 0) {
close(fd[2]);
c0 = a*b;
sprintf(char0, "%d", c0);
write(fd[0], char0, 10);
close(fd[0]);
exit(0);
}
// child1
if((child1 = fork()) == 0) {
close(fd[2]);
c1 = b*c;
sprintf(char1, "%d", c1);
write(fd[1], char1, 10);
close(fd[1]);
exit(0);
}
// overview
if((overview = fork()) == 0) {
close(fd[0]);
close(fd[1]);
read(fd[2], char0, 10);
read(fd[2], char1, 10);
printf("%s %s", char0, char1); //Prints weird stuff??
close(fd[2]);
exit(0);
}
// Wait for children to finish
waitpid(child0, &status, 0);
waitpid(child1, &status, 0);
waitpid(overview, &status, 0);
exit(0);
}
Your code for declaring pipe is totally wrong, pipes will have only two ends and for declaring three pipes you need to declare as follows
pd1[2];
pd2[2];
pd3[2];
from one end you can write that is pd1[1];
and from the other end you can read pd1[0];
So your code will look like,
int main(int argc, char *argv[]) {
int fd1[2];
int fd2[2];
int fd1[2];
int a, b, c, c0, c1, status;
char char0[10];
char char1[10];
pid_t child0;
pid_t child1;
pid_t overview;
// Set argv to ints
a = atoi(argv[1]);
b = atoi(argv[2]);
c = atoi(argv[3]);
// Pipe
pipe(fd1);
pipe(fd2);
pipe(fd3);
// child0
if((child0 = fork()) == 0) {
close(fd1[0]);
c0 = a*b;
sprintf(char0, "%d", c0);
write(fd1[1], char0, 10);
close(fd[1]);
exit(0);
}
// child1
if((child1 = fork()) == 0) {
close(fd2[0]);
c1 = b*c;
sprintf(char1, "%d", c1);
write(fd2[1], char1, 10);
close(fd2[1]);
exit(0);
}
// overview
if((overview = fork()) == 0) {
close(fd1[1]);
close(fd2[1]);
read(fd1[0], char0, 10);
read(fd2[0], char1, 10);
printf("%s %s", char0, char1); //Prints weird stuff??
//close(fd[2]);
exit(0);
}
// Wait for children to finish
waitpid(child0, &status, 0);
waitpid(child1, &status, 0);
waitpid(overview, &status, 0);
exit(0);
}
This code might also not correct I have just explained how to use pipes, see opening and closing of pipes, that is while writing reading end should be closed and while reading writing end should be closed.
edit
see this post and execute small program then modify your code step by step you will get understand.
How to send a simple string between two programs using pipes?

Resources