Create and write function for pipe for usage in main() - c

The 'create_andWrite' function should create a pipe and write a string to it. The child process which is created in the main should read from the pipe.
I only worked with pipes in one method(e.g. read and write are both in main) before and I'm really struggling with this one.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int creat_and_write(FILE *fd, char *string) {}
int main() {
int fd[2];
creat_and_write();
int p = fork;
}
These are my functions signatures so far

Pipes are one way of unidirectional IPC, used usually with fork() to pass data in a sort of vertical hierarchy.
Hope the example below is clear. and spot the usage of the 2 functions.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#define READ_END 0
#define WRITE_END 1
// pipe uses file descriptors to communicate between processes not pointers to files.
int creat_and_write(int *fd, char *string) {
// first and formost we need a pipe.
if (pipe(fd) == -1) {
perror("pipe error");
exit(1);
}
// now the fd contains 2 file descriptors, one for reading and one for writing to the pipe.
// we fork a child process which will inherit most internals including the pipe's file descriptors.
pid_t pid = fork();
if (pid == -1)
{
perror("fork error");
exit(1);
}
else if (pid == 0)
{
// we're at the child process.
// now we can write to the write end of the pipe
write(fd[WRITE_END], string, strlen(string));
// good practice to close done end of the pipe. for a full cleanup.
close(fd[WRITE_END]);
}
else
{
// we're at the parent process.
// now we can read from the read end of the pipe
char buffer[strlen(string)];
read(fd[READ_END], buffer, 100);
close(fd[READ_END]);
printf("now at the parent process: %s\n", buffer);
}
return 0;
}
int main() {
int fd[2];
creat_and_write(fd, "msg from child process");
return 0;
}

Related

I want to create two communication between parent and child residing in different C files using ordinary pipes (IPC)

I am trying to send message from parant.c to child.c and I am successfully receiving it in the child.c
My question is that how can I send message back to the parent using second pipe from child.c I want the exact sequence of code.
Here is my parent.c:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
int fd[2];
char buf[] = "HELLO WORLD!", receive[100];
if (pipe(fd))
{
perror("pipe");
return -1;
}
switch (fork())
{
case -1:
perror("fork");
return -1;
case 0:
// child
close(fd[1]); // close write end
dup2(fd[0], STDIN_FILENO); // redirect stdin to read end
close(fd[0]); // close read end
execl("./child", NULL); // execute child
default:
// parent
close(fd[0]); // close read end
write(fd[1], buf, sizeof(buf)); // write to write end
close(fd[1]); // close write end
wait(NULL);
}
printf("\nEND~\n");
return 0;
}
I am sending buf ("Hello world") to the child by executing ./child file.
Here is my child.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
int fd[2];
pid_t pid = fork();
char buf[100], child_msg[] = "From Child: Hello Parent";
if (pipe(fd))
{
perror("pipe");
return -1;
}
switch (pid)
{
case -1:
perror("fork");
return -1;
case 0:
read(STDIN_FILENO, buf, sizeof(buf));
printf("%s ", buf);
close(fd[1]);
default:
wait(NULL);
}
return 0;
}
I am receiving Hello world in this file. but now how can I send child_msg back to the parent? I don't how to do that. I am stuck at this for last 14 hours.
From main pipe:
pipe() creates a pipe, a unidirectional data channel ...
So, you need 2 pipes, i.e., you have to create 2 pipes in your main process that will also be inherited by the child process.
From your code, you are execing another program, in such cases you might
be better off with other IPCs and not pipe!

With vs without the C pipe() function- what's causing this behavior?

I wrote a simple script (taken from a tutorial) which writes data to one end of a pipe in a child process, and reads it from the other end of the pipe in the parent process:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main()
{
pid_t pid;
int mypipefd[2];
int ret;
char buf[20];
ret = pipe(mypipefd);
if (ret == -1) {
printf("Pipe failed.\n");
exit(1);
}
if ((pid = fork()) == -1) {
printf("Fork failed.\n");
exit(1);
} else if (pid == 0) {
printf("Child process.\n");
char msg[] = "Hello there!";
write(mypipefd[1], msg, strlen(msg) + 1);
} else {
printf("Parent process.\n");
read(mypipefd[0], buf, 15);
printf("Buf: %s\n", buf);
}
return 0;
}
This works fine and outputs the results I expect:
Parent process.
Child process.
Buf: Hello there!
[ project ] $
Then as I got more familiar with the code, I wondered why we need to use mypipefd[2] and pipe() to achieve this goal, or whether mypipefd[1] by itself would work. So I tried it out with the following code:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
int main()
{
pid_t pid;
int my_array[1];
char buf[20];
if ((pid = fork()) == -1) {
printf("Fork failed.\n");
exit(1);
} else if (pid == 0) {
printf("Child process.\n");
char msg[] = "Hello there!\n";
write(my_array[0], msg, strlen(msg) + 1);
} else {
// wait(NULL);
printf("Parent process.\n");
read(my_array[0], buf, 15);
printf("Buf: %s\n", buf);
}
return 0;
}
This code outputs the same text, but it hangs after it finishes printing.
Parent process.
Child process.
Buf: Hello there!
No prompt, this time. I even tried un-commenting that call to wait(NULL), on the off-chance that the root cause was a conflict between parent and child processes. No such luck.
What's going on here? Why am I unable to read and write to a length-of-one array in this way without the program hanging? What exactly is the compiler stuck on?
A pipe, on computers as well as in real life, have two ends. And like pipes in real life, data flows from one end of the pipe (the write end) to the other (the read end).
The pipe function gives you those two ends by writing them to an array of two file-descriptors. The first element of the pair is read-only, and the second is write-only.
The pipe() function accepts an array of 2 integer as an input argument.
#include <unistd.h>
int pipe(int pipefd[2]);
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <fcntl.h> /* Obtain O_* constant definitions */
#include <unistd.h>
int pipe2(int pipefd[2], int flags);
It then generates a new pipe object, and initializes the pipefd array with file descriptors for read and write operation.
What you try to do is call read() and write() using some arbitrary, uninitialized ints (or file descriptor). Meaning the OS did not allocate a pipe object and did not provide you with file descriptors (the pipe's API) to be use with read() and write().
This (calling read() or write() with uninitialized file descriptor) will result in "undefined behavior".
"I find that a good working definition of "undefined behaviur" is "works for me, works for you, works during development and QA, but blows up in your most important customer's face"" --- Scott Meyers

pipe() and fork() to transer data from parent to child

I have to create a pipe and then a fork and allow parent and child process (1 child) communication.
In particular Parent reads from a file and writes on pipe the content of file (which is supposed to be huge) then child has to read from pipe and display on stdout the content of file.
gcc compiler is ok but nothing happen when I run the executable file.
Can someone help me with my code? Where did I go wrong and why?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define size 80
int main(int argc,char*argv[]){
if(argc!=2){
write(2,"Missing parameters on the command line\n",38);
return 1;
}
int fd[2];
pid_t pid;
int fd_in;
int i;
char buf[size];
//create pipe for communication between parent and child in this case parent read the file at size bytes at time write into pipe then child write data on stdout received from father
if(pipe(fd)!=0){
printf("Pipe failure\n");
return 1;
}
pid=fork();
if(pid<0){
printf("Fork() failure\n");
return 1;
}
if(pid>0){ // parent process
close(fd[0]);// parent write into pipe ,close reading
if(access(argv[1],F_OK)!=0){
write(2,"Input file does not exists\n",35);
return 1;
}
if(fd_in=open(argv[1],O_RDONLY)<0){
printf("Cannot open for reading file %s\n",argv[1]);
return 1;
}
while(read(fd_in,buf,size)>0){
write(fd[1],buf,size);
}
close(fd[1]); // close write into pipe
wait(0);
}
if(pid==0){ //Child process
close(fd[1]);// child read from pipe, close writing
while(read(fd[0],buf,size)>0){
write(1,buf,size);
}
close(fd[0]);// close reading
return 0;
}
close(fd_in);
return 0;
}

how does synchronization work in this example?

I am trying to implement pipe system call as part of my semester project.
I came across the following code here
#include <sys/wait.h>
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
int
main(int argc, char *argv[])
{
int pfd[2];
pid_t cpid;
char buf;
assert(argc == 2);
if (pipe(pfd) == -1) { perror("pipe"); exit(EXIT_FAILURE); }
cpid = fork();
if (cpid == -1) { perror("fork"); exit(EXIT_FAILURE); }
if (cpid == 0) { /* Child reads from pipe */
close(pfd[1]); /* Close unused write end */
while (read(pfd[0], &buf, 1) > 0)
write(STDOUT_FILENO, &buf, 1);
write(STDOUT_FILENO, "\n", 1);
close(pfd[0]);
_exit(EXIT_SUCCESS);
} else { /* Parent writes argv[1] to pipe */
close(pfd[0]); /* Close unused read end */
write(pfd[1], argv[1], strlen(argv[1]));
close(pfd[1]); /* Reader will see EOF */
wait(NULL); /* Wait for child */
exit(EXIT_SUCCESS);
}
}
Having studied Multiprocessor programming, I realize this is a producer consumer model. The main process is forking a child which is consuming the bytes written by the main process in the write end of the pipe.
I am not able to understand how the synchronization is working here. I mean how does the parent notify the child that it has written n number of bytes in the write end of the pipe?
Does closing unused fd's has anything to do with synchronization?
What if in this example, I want child to write something in the write end and parent to read it?
Any help would be great, thanks!

C: "write: Broken pipe" error

I want to try Pipe communication with child and parent process. Parent process write to pipe and child process read this but my program get error "write: Broken pipe". How can I change this code?
Thnks.
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <termios.h>
#include <errno.h>
#include <fcntl.h>
int main(void)
{
int i=0;
int child=5;
int fdp;
int fds[2];
int controlRead;
int controlWrite;
char pathName[30] = {"Trying Pipe Communication\n"};
if(pipe(fds) < 0)
{
perror("pipe");
exit(EXIT_FAILURE);
}
do{
if(child == 0)
{
close(fds[1]);
if( (controlRead = read(fds[0],pathName,sizeof(pathName)) ) <= 0)
{
perror("read");
exit(EXIT_FAILURE);
}
close(fds[0]);
printf("boru :%s\n",pathName);
wait();
}
else
{
printf("Parent process\n");
close(fds[0]);
if( (controlWrite = write(fds[1],&pathName,sizeof(pathName))) <= 0)
{
perror("write");
exit(EXIT_FAILURE);
}
close(fds[1]);
}
i++;
child = fork();
}while(i<3);
return 0;
}
error "write: Broken pipe". How can I change this code?
Don't break the pipe before you write to it. On the first pass through your do/while loop, the parent closes the read end and then writes to the remaining pipe fd. Kablam. EPIPE.
Your read loop shall count number of bytes read before closing the socket. Otherwise it is terminated too early.
Pipes are not packet transport, and single read/write is actually a series of operations. So when you are writing an array, it is wrong to assume it will come in one piece.

Resources