How to distinguish one child process from other child processes - c

I have an assignment for class and I am confused on this part of the requirements. So we need to make a multi process word counter with n number of processes and n will be an input argument for the program. Each process needs to do their own mini word count of a select portion of the inputted file. So essentially the inputted file will be divided into 1/n parts and split between n processes.
I understand how to fork the processes through a for loop and how to use pipes to send the mini word count from the children processes to the parent process, but I unsure of how to tell a certain process to do a select part of the input file.
Would you use their PID values to check which process they are then assign them their task?
This is my code so far.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define MSGLEN 64
#define MESSES 3
int main(){
int fd[2];
pid_t pid;
int result;
//Creating a pipe
result = pipe (fd);
if (result < 0) {
//failure in creating a pipe
perror("pipe error\n");
exit (1);
}
//Creating a child process
for(int i = 0; i < MESSES; i++){
if ((pid = fork()) < 0) {
//failure in creating a child
perror ("fork error\n");
exit(2);
}
if(pid == 0)
break;
}
if (pid == 0) {
// ACTUALLY CHILD PROCESS
char message[MSGLEN];
//Clearing the message
memset (message, 0, sizeof(message));
printf ("Enter a message: ");
//scanf ("%s",message);
fgets (message, 1024, stdin);
close(fd[0]);
//Writing message to the pipe
write(fd[1], message, strlen(message));
close(fd[1]);
close(fd[0]);
exit (0);
}
else {
//Parent Process
char message[MSGLEN];
char *ptr;
long wc;
close(fd[1]);
while (1) {
//Clearing the message buffer
memset (message, 0, sizeof(message));
//Reading message from the pipe
if(read(fd[0], message, sizeof(message)) == 0)
exit(0);
printf("Message entered %s\n",message);
/*
Message entered needs to be in the format of number first space then string for it to work
*/
wc = 0;
wc = strtol(message, &ptr, 10);
printf("The number(unsigned long integer) is %ld\n", wc);
printf("String part is %s", ptr);
}
close(fd[0]);
wait(NULL);
// exit(0);
}
return 0;
}

The key thing to remember when using fork is that the parent and child share the same memory and a copy of everything the parent has is passed to the child. At which point the child has now forked the parents data.
In the code below we're counting how many processes we've created. You could if you wanted use this as an argument in the child ie the nth child gets value n.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define PROCESS_COUNT 50
int main(void) {
pid_t pid;
size_t pid_count = 0;
//pid_t pid_array[PROCESS_COUNT];
for(int i = 0; i < PROCESS_COUNT; i++) {
if ((pid = fork()) < 0) {
perror ("fork error\n");
exit(2);
}
if (pid == 0) {//child
size_t n = 0;
size_t p = getpid();
while(n++ < 2) {
//Next line is illustration purposes only ie I'm taking liberties by
//printing a pid_t value
printf("child %zu has pid_count == %zu\n", p, pid_count);
sleep(1);
}
exit (0);
}
else {
//Count how many process we've created.
pid_count++;
int status;
waitpid( -1, &status, WNOHANG);
}
}
wait(NULL);
return 0;
}
If you want to get really fancy you can use IPC using pipes or shared memory. There are lots of ways to get data from one process to another, sometimes something as simple as temporary files is more than sufficient. For your problem I'd use mmap but it does not need to be that complicated

Related

Pipe between children

I want to do a program that first creates 3 processes (A) and later, creates one process more (B) and these first processes must write in a pipe that the last process read each time that process write.
I tried something but I don't know the way to do that because the process (B) is created after the processes (A)
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CHILDREN 3
int main(int argc, char *argv[])
{
pid_t pid;
int fd[2];
char buffer[100];
char str[] = "Hello";
char str2[] = "Hello2";
char str3[] = "Hello3";
for(int num_process = 0; num_process < MAX_CHILDREN; num_process++)
{
if(pipe(fd) == -1)
{
perror( "pipe Failed" );
continue;
}
pid = fork();
if(pid < 0)
{
perror("fork failed");
exit(1);
}
if(pid == 0)
{ //child code
if(num_process == 0){
printf("Child %i (pid= %i) send string %s\n", num_process, getpid(),str);
write(fd[1],str,strlen(str));
}
if(num_process == 1){
printf("Child %i (pid= %i) send string %s\n", num_process, getpid(),str2);
write(fd[1],str2,strlen(str2));
}
if(num_process == 2){
printf("Child %i (pid= %i) send string %s\n", num_process, getpid(),str3);
write(fd[1],str3,strlen(str3));
}
exit(0);
}
else{//parent
printf("Im parent %i\n",getpid());
wait(NULL);
}
}
//Creating another child process from parent, this process recieves string sent from
//childs
pid = fork();
if(pid < 0)
{
perror("fork failed");
exit(1);
}
if(pid == 0){//child
printf("The new process %i read fd pipe\n",getpid());
if( read(fd[0],buffer,sizeof(buffer)) <= 0) //read pipe
{
perror("error read");
exit( EXIT_FAILURE );
}
printf("String readed : %s\n",buffer);
}
else{//parent
wait(NULL);
}
return 0;
}
You need to make a number of changes to the code. The parent shouldn't really wait on its children until after they're all launched. Since you create a new pipe for each of the first three children, you need to keep track of which file descriptors are in use. You should use arrays for that, and for the strings to be sent. Neither the read() nor the write() system calls null-terminates strings, and you don't tell it to write a null byte at the end, so you need to tell printf() to print the correct information.
Those changes and sundry others lead to:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MAX_CHILDREN 3
int main(void)
{
pid_t pid;
int fd[MAX_CHILDREN][2];
char buffer[100];
const char *str[MAX_CHILDREN] = { "Hello 1", "Hello 2", "Hello 3" };
for (int i = 0; i < MAX_CHILDREN; i++)
{
if (pipe(fd[i]) == -1)
{
perror("pipe Failed");
exit(1);
}
pid = fork();
if (pid < 0)
{
perror("fork failed");
exit(1);
}
if (pid == 0)
{
printf("Child %i (pid= %i) send string %s\n", i + 1, getpid(), str[i]);
write(fd[i][1], str[i], strlen(str[i]));
exit(i + 1);
}
}
pid = fork();
if (pid < 0)
{
perror("fork failed");
exit(1);
}
if (pid == 0)
{
printf("The new process %i read fd pipe\n", getpid());
for (int i = MAX_CHILDREN; i-- > 0; )
{
int nbytes;
if ((nbytes = read(fd[i][0], buffer, sizeof(buffer))) <= 0)
{
perror("error read");
exit(EXIT_FAILURE);
}
printf("String read: %.*s\n", nbytes, buffer);
}
exit(4);
}
int corpse;
int status;
while ((corpse = wait(&status)) >= 0)
printf("child %d exited with status 0x%.4X\n", corpse, status);
return 0;
}
When run, the output might be:
Child 1 (pid= 91027) send string Hello 1
Child 2 (pid= 91028) send string Hello 2
Child 3 (pid= 91029) send string Hello 3
The new process 91030 read fd pipe
String read: Hello 3
String read: Hello 2
String read: Hello 1
child 91027 exited with status 0x0100
child 91028 exited with status 0x0200
child 91029 exited with status 0x0300
child 91030 exited with status 0x0400
I reversed the order of the elements in the reading loop, mainly just for fun. You can use a conventional for (int i = 0; i < MAX_CHILDREN; i++) loop instead if you prefer.
Although it isn't crucial in this program, you aren't closing enough file descriptors in the children or the parent. The parent should close the write ends of the pipes; it isn't going to be using them. The children should close the read ends of the pipes; they aren't going to be using them. Further, the second and third children should close the pipes opened for the first, and the third should close the pipe for the second, as they aren't going to use those, either. If you don't do this and the fourth child looped waiting for EOF (0 bytes returned), it would hang.
Rule of thumb: If you
dup2()
one end of a pipe to standard input or standard output, close both of the
original file descriptors returned by
pipe()
as soon as possible.
In particular, you should close them before using any of the
exec*()
family of functions.
The rule also applies if you duplicate the descriptors with either
dup()
or
fcntl()
with F_DUPFD
Note that an alternative design for the program would create a single pipe outside the loop and the children would all write to the same pipe. You'd probably want to add a newline to the message strings so that the results are separate. You'd definitely want to think about looping the read in the fourth child, and you'd need to worry about the pipe being closed properly, and so on. It'd be a worthwhile sub-exercise to code that.

Unexpected output while using Pipes

I am a new to pipes in C.
I am trying to Write "hello" on the pipe from a child process & read the same from parent process, but I am getting unexpected output.
I using this piece of code:
#include<stdio.h>
#include<unistd.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t pid;
int fds[2];
int ret;
char ch[20];
ret = pipe(fds);
if(ret == -1)
{
perror("pipe failed");
exit(0);
}
pid = fork();
if (pid == 0)
{
printf("Child process\n");
write(fds[1],"Hello",5);
}
if (pid > 0)
{
printf("Parent Process\n");
read(fds[0],ch,15);
printf("%s\n",ch);
}
return 0;
}
I am getting this as output :
Parent Process
Child process
Helloq.
I can't understand why this extra "q." is coming ??
You are trying to write 6 bytes but are setting the size to 5. You need to also send the '\0' at the end of Hello along.
Just change your write call to
write(fds[1],"Hello",6);
and you should be fine.
Use memset() function in your code before writing data into buffer, which fill memory with a constant byte. like,
memset(ch,'\0',20);
Full code may be help you.
#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t pid;
int fds[2];
int ret;
char ch[20];
memset(ch,'\0',20);
ret = pipe(fds);
if(ret == -1)
{
perror("pipe failed");
exit(0);
}
pid = fork();
if (pid == 0)
{
printf("Child process\n");
write(fds[1],"Hello",5);
}
if (pid > 0)
{
printf("Parent Process\n");
read(fds[0],ch,15);
printf("%s\n",ch);
}
}
Since you don't record how many bytes were read off the pipe, your code is printing the garbage that was already in the ch variable. There are numerous ways to deal with it. This code shows two of them. I used memset() to ensure that ch contained some data (and the assignment makes sure it is null terminated).
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
pid_t pid;
int fds[2];
int ret;
char ch[20];
memset(ch, 'X', sizeof(ch)-1);
ch[sizeof(ch)-1] = '\0';
ret = pipe(fds);
if (ret == -1)
{
perror("pipe failed");
exit(0);
}
pid = fork();
if (pid == 0)
{
printf("Child process\n");
write(fds[1], "Hello", 5);
}
else if (pid > 0)
{
printf("Parent Process\n");
int nbytes = read(fds[0], ch, 15);
printf("[%s]\n", ch);
printf("[%.*s]\n", nbytes, ch);
ch[nbytes] = '\0';
printf("[%s]\n", ch);
}
else
fprintf(stderr, "fork() failed\n");
return 0;
}
The code records how many bytes were written (truly diligent code would ensure that the correct amount of data was written, too). It prints the data 3 times — once using your original technique, then once using the number of bytes read off the pipe to limit the output, and then null-terminating the data so that it can be written as a simple string.
The %.*s conversion specification uses two values — a number and the string. The number is the maximum number of bytes that will be written. If the string is shorter than that, so be it. If the string is longer, the excess bytes are ignored.
Sample output:
Parent Process
[HelloXXXXXXXXXXXXXX]
[Hello]
[Hello]
Child process
This was the result of piping the program output. Visually, on the terminal, I usually got:
Parent Process
Child process
[HelloXXXXXXXXXXXXXX]
[Hello]
[Hello]
Both outputs are valid. Note how the first printing of the data also includes a number of the X's because there was no null byte read from the pipe.
Another alternative is to have the child write the null of the null-terminated string to the pipe: write(fds[1], "Hello", sizeof("Hello"));. Other options include writing the length of the string on the pipe followed by the data and then reading the length and that many bytes of data. This is a minor variant on a TLV (type, length, value) encoding system — the type is not explicitly specified as it is assumed to be char.

Child reading from std input and writes to std output

I have a program where the child runs a program but the parent process passes the child a number and the child writes back to the parent a response. However whenever I run the code, it does not give me anything back, so I must be passing or receiving to the child wrong, but I'm not sure how. Any help is appreciated. Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main() {
int pid;
int n;
char buf[101];
int pfdA[2];
int pfdB[2];
// CREATES FIRST PIPE
if (pipe(pfdA) == -1) {
perror("pipe failed");
exit(-1);
}
// CREATES SECOND PIPE
if (pipe(pfdB) == -1) {
perror("pipe failed");
exit(-1);
}
// FORK()
if ((pid == fork()) < 0) {
perror("fork failed");
exit(-2);
}
if (pid == 0 ) {
// duplicate file descriptor 0 to point to FIRST pipe
dup(pfdA[0]);
// CLOSES ends of FIRST pipe you don't need anymore
close(pfdA[0]);
close(pfdA[1]);
// duplicates file descriptor 1 to point to SECOND pipe
dup(pfdA[1]);
// CLOSES ends of SECOND pipe you don't need anymore
close(pfdB[0]);
close(pfdB[1]);
execlp("./A5_CHILD", "./A5_CHILD", (char *) 0);
perror("execlp");
exit(-3);
}
else {
while( 1 ) {
char NUM[100];
close(pfdA[0]);
close(pfdB[1]);
int r=0;
printf("Enter a Number: ");
fflush(stdout);
scanf("%s", NUM);
// SENDS NUM to Child process
write(pfdA[1], NUM, strlen(NUM));
// READS FROM CHILD THE RESPONSE into the variable buf and
// store the return value from read() into the variable r
r= read(pfdB[0], buf, 100);
if( r > 0 ) {
buf[r] = '\0';
printf("%s\n", buf);
fflush(stdout);
}
else {
printf("[PARENT] Reading from child: read() returned %d\n", r);
break;
}
}
}
return(0);
}
Unless you explicitly close(0), dup(pfdA[0]) almost certainly does not return 0. Try dup2 to specify which descriptor you want as the new one. That is (error checking omitted for brevity):
dup2( pfdA[0], STDIN_FILENO );
close( pfdA[0])
Similarly for stdout.

New to IPC, can't get my pipe to work

Sorry for the length of this post... I've encountered about a zillion problems in this. Up front I'll say I'm a student and my professor is a worthless resource. So, all I want to to do is have producer fork, then the parent producer will count some stuff in a file and send two ints to consumer, which was launched by the child process. I've tested everything, the fork and the file stuff works and I have printf statements all over the place so I know what is being done and where the code is at.
When I added the
if (pipe(pipefd) == -1) {
perror("pipe");
}
it caused my parent to just terminate. It reaches "parent pipe open" but then it dies. I checked with $ ps to see if it was just hung, but it's not there; it just dies. If I take that snippet out, it runs to the end but I presume if that code isn't there, then it's not actually aware that pipefd is a pipe... right?
I did search on this site and found another example of this and followed what he did as well as the answer and mine just refuses to work. I'm pretty sure it's a trivially easy thing to fix but I've run out of ideas of what to try :(
I don't really want to post all my code because it'll be a huge wall of text but I don't want to accidentally cut something out that turns out to be important either.
producer.c
#include <stdio.h> /* printf, stderr, fprintf */
#include <sys/types.h> /* pid_t */
#include <unistd.h> /* _exit, fork, execl */
#include <stdlib.h> /* exit */
#include <errno.h> /* errno */
#include <string.h> /* strlen */
#include <sys/wait.h> /* wait */
#define SLEEP_TIME 8
int main (int argc, char *argv[]){
//PID
pid_t local_pid;
local_pid = fork();
//Logic to determine if the process running is the parent or the child
if (local_pid == -1) {
/* Error:
* When fork() returns -1, an error happened
* (for example, number of processes reached the limit).
*/
fprintf(stderr, "can't fork, error %d\n", errno);
exit(EXIT_FAILURE);
} else if (local_pid == 0) {
//Child specific code
int child;
char *temp[] = {NULL};
printf("Child PID found\n");
child = execv("./consumer", temp);
_exit(0);
} else {
//Parent specific code
printf("Parent running\n");
//open file
FILE * randStrings;
randStrings = fopen("randStrings.txt", "r");
int file_length;
int num_of_e = 0;
int c; //using this as a char
//until eof
while (feof(randStrings) == 0) {
c = fgetc(randStrings);
//calculate length of file
file_length++;
//count e chars
if (c == 'e') {
num_of_e++;
}
}
//close file
fclose(randStrings);
//send bundle to child
int a[2];
a[0] = num_of_e;
a[1] = file_length;
printf("num of e = %i\n", a[0]);
printf("len = %i\n", a[1]);
//set up parent pipe
int pipefd[2];
if (pipe(pipefd) == -1) {
perror("pipe");
printf("x\n");
}
printf("parent pipe open\n");
close(pipefd[0]); //close the read end
write(pipefd[1], &a[0], sizeof(int));
write(pipefd[1], &a[1], sizeof(int));
close(pipefd[1]);
printf("parent pipe closed\n");
//wait for child to finish running
wait(NULL);
printf("parent out\n");
//terminate
}
}
and consumer.c
#include <stdio.h> /* printf, stderr, fprintf */
#include <sys/types.h> /* pid_t */
#include <unistd.h> /* _exit, fork, execl */
#include <stdlib.h> /* exit */
#include <errno.h> /* errno */
#define SLEEP_TIME 5
int main (int argc, char *argv[]){
sleep(SLEEP_TIME);
printf("Child program launched\n");
//receive bundle
int pipefd[2];
int buf[2];
if (pipe(pipefd) == -1) {
perror("pipe");
printf("child x\n");
}
close(pipefd[1]); //child closes write end
buf[0] = 0;
buf[1] = 0;
/*int i = 0; // i dont like this
while (read(pipefd[0], &buf[i], sizeof(int)) > 0) {
i++;
}*/
printf("child reading pipe\n");
read(pipefd[0], &buf[0], sizeof(int));
read(pipefd[0], &buf[1], sizeof(int));
close(pipefd[0]);
//buf should have the stuff in it
int num_of_e = buf[0];
int file_length = buf[1];
printf("child num of e = %i\n", num_of_e);
printf("child len = %i\n", file_length);
//open file
FILE * resultStrings;
resultStrings = fopen("resultStrings.txt", "w");
for (int i = 0; i < num_of_e; i++) {
//write num_of_e e chars
fputc('e', resultStrings);
}
//or if no e chars, write - chars
if (num_of_e == 0) {
for (int i = 0; i < file_length; i++) {
//write file_length '-' chars
fputc('-', resultStrings);
}
}
//close file
fclose(resultStrings);
printf("child out\n");
}
if you're still here after all that, you deserve a thank you just due to the length of this.
You're doing it wrong. The whole mechanism works because a child process inherits the parent's open file descriptors.
It should go like this:
Open the pipe with pipe(pipefd)
fork()
Parent (producer):
closes the read side (pipefd[0])
writes to the write side (pipefd[1])
Child (consumer):
closes the write side (pipefd[1])
reads from the read side (pipefd[0]) or calls exec
You are opening distinct pipes in both the parent and child process (after you've forked.) It needs to happen before you fork.
Now since you're execing, the new process needs to be aware of read-only pipe. There are a couple ways you could do this:
Pass it the file descriptor number (pipefd[0]) on the command line
dup2(1, fd) it to be the stdin of the newly exec'd process

Using pipe to pass integer values between parent and child

I'm a little confused on how to properly use pipe() to pass integer values between two processes.
In my program I first create a pipe, then I fork it. I assume I have "Two" pipes then?
From what I understand, this is my assignment.
My parent goes through a for loop checking an integer value "i" for a certain operation, increases a count variable, and saves value into an array. After each check my parent should pass an integer value, "i" to my child through a pipe. My child then uses that integer value, does some check on the value, and should increase a count variable, and save the result in a [shared?] array. Eventually; the child should return it's final count to the parent, who then prints out the two counts, and the "Shared" array.
-> I'm not sure I need to have a shared array or to save the results at all. I may only need the counts - the homework was ambiguous and I'm awaiting a response from the professor. Also; can I even do a shared array between processes? It sounds like a start of some problem to me.
-> Here are my questions:
One; how do I use pipes for integers? I've only seen them for character arrays and previous answers don't seem to think this is possible or legal..? I'm not sure. There was no resolution that I could find on it.
-> How do I use a unidirectional pipe to pass integers to a child? And have the child return something? I'm not sure how I'm able to... differentiate between the two pipes. I do "know" [or think I know] that I have to close one unused portion of each pipe to avoid "Some vague problem".
Sorry for the dumb questions; I haven't been taught processes (aside from fork) or pipes (at all) yet in this class - so I'm not really sure where to start!
Heres parts of my code - it's not pretty and it doesn't work and I don't expect it to. It's more of a shell placeholder. Once I figure out how to use a pipe - I'd Probably make the code make sense.
int main(void)
{
int fd[2];
pid_t childpid;
pid_t parentpid;
int i;
int threecount = 0;
int fivecount = 0;;
int results [MAXSIZE];
parentpid = getpid(); //Get current process ID number
pipe(fd);
childpid = fork();
if(childpid == 0){
close(fd[0]); //Closing this for some other reason
}
int j = 0;
if(childpid > 0)
close(fd[1]); //Closing this for some reason
if( childpid == -1 )
{
perror("Failed to fork\n");
return 1;
}
if (childpid > 0)
{
for(i = 1; i < MAXSIZE;i++)
{
if(i % 5 == 0)
{
fivecount++;
i = results[j];
j++;
wait(NULL);
}
}
}
else if (childpid == 0)
{
if(i % 3 == 0) //This i here should probably be the i value above, piped to the child
{
threecount++;
i = results[j]; //This should be part of th pipe
j++; //Trying to keep count of that shared array, not really the right way to do it though.
}
}
printf("%d %d \n", fivecount,threecount);
return 0;
}
This is about as lame (and no error checking, btw) a sample as I can muster for using a pipe to send int from a parent to a child process, where the child was launched from fork(). It gets more complicated (obviously) for sending and receiving data, but i can't do everything for you. This just forks and waits for an int (actually, the number of bytes that are used by an int) from the child.
Update: Added send+response two-way communication example after this one. See the second code listing for more information.
Hope it helps.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int fd[2];
int val = 0;
// create pipe descriptors
pipe(fd);
// fork() returns 0 for child process, child-pid for parent process.
if (fork() != 0)
{
// parent: writing only, so close read-descriptor.
close(fd[0]);
// send the value on the write-descriptor.
val = 100;
write(fd[1], &val, sizeof(val));
printf("Parent(%d) send value: %d\n", getpid(), val);
// close the write descriptor
close(fd[1]);
}
else
{ // child: reading only, so close the write-descriptor
close(fd[1]);
// now read the data (will block)
read(fd[0], &val, sizeof(val));
printf("Child(%d) received value: %d\n", getpid(), val);
// close the read-descriptor
close(fd[0]);
}
return 0;
}
Output:
Parent(5943) send value: 100
Child(5945) received value: 100
Update: Expanded to include send+response using two pipe sets
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
// some macros to make the code more understandable
// regarding which pipe to use to a read/write operation
//
// Parent: reads from P1_READ, writes on P1_WRITE
// Child: reads from P2_READ, writes on P2_WRITE
#define P1_READ 0
#define P2_WRITE 1
#define P2_READ 2
#define P1_WRITE 3
// the total number of pipe *pairs* we need
#define NUM_PIPES 2
int main(int argc, char *argv[])
{
int fd[2*NUM_PIPES];
int val = 0, len, i;
pid_t pid;
// create all the descriptor pairs we need
for (i=0; i<NUM_PIPES; ++i)
{
if (pipe(fd+(i*2)) < 0)
{
perror("Failed to allocate pipes");
exit(EXIT_FAILURE);
}
}
// fork() returns 0 for child process, child-pid for parent process.
if ((pid = fork()) < 0)
{
perror("Failed to fork process");
return EXIT_FAILURE;
}
// if the pid is zero, this is the child process
if (pid == 0)
{
// Child. Start by closing descriptors we
// don't need in this process
close(fd[P1_READ]);
close(fd[P1_WRITE]);
// used for output
pid = getpid();
// wait for parent to send us a value
len = read(fd[P2_READ], &val, sizeof(val));
if (len < 0)
{
perror("Child: Failed to read data from pipe");
exit(EXIT_FAILURE);
}
else if (len == 0)
{
// not an error, but certainly unexpected
fprintf(stderr, "Child: Read EOF from pipe");
}
else
{
// report what we received
printf("Child(%d): Received %d\n", pid, val);
// now double it and send it back
val *= 2;
printf("Child(%d): Sending %d back\n", pid, val);
if (write(fd[P2_WRITE], &val, sizeof(val)) < 0)
{
perror("Child: Failed to write response value");
exit(EXIT_FAILURE);
}
}
// finished. close remaining descriptors.
close(fd[P2_READ]);
close(fd[P2_WRITE]);
return EXIT_SUCCESS;
}
// Parent. close unneeded descriptors
close(fd[P2_READ]);
close(fd[P2_WRITE]);
// used for output
pid = getpid();
// send a value to the child
val = 42;
printf("Parent(%d): Sending %d to child\n", pid, val);
if (write(fd[P1_WRITE], &val, sizeof(val)) != sizeof(val))
{
perror("Parent: Failed to send value to child ");
exit(EXIT_FAILURE);
}
// now wait for a response
len = read(fd[P1_READ], &val, sizeof(val));
if (len < 0)
{
perror("Parent: failed to read value from pipe");
exit(EXIT_FAILURE);
}
else if (len == 0)
{
// not an error, but certainly unexpected
fprintf(stderr, "Parent(%d): Read EOF from pipe", pid);
}
else
{
// report what we received
printf("Parent(%d): Received %d\n", pid, val);
}
// close down remaining descriptors
close(fd[P1_READ]);
close(fd[P1_WRITE]);
// wait for child termination
wait(NULL);
return EXIT_SUCCESS;
}
(compile with, e.g., gcc thisfile.c -o test)
Output
Parent(2794): Sending 42 to child
Child(2797): Received 42
Child(2797): Sending 84 back
Parent(2794): Received 84

Resources