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;
}
Related
I have a homework question:
Q7: After executing the following code, a new file named myFile.txt is generated. Is the content in myFile.txt will be consistent? Why?
And here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/wait.h>
int main(int argc, char *argv[]){
printf("hello world (pid:%d)\n", (int)getpid());
int fd = open("myFile.txt", O_CREAT|O_RDWR);
if(fd == -1 ) {
printf("Unable to open the file\n exiting....\n");
return 0;
}
int rc = fork();
if (rc < 0) {
fprintf(stderr, "fork failed\n");
exit(1);
}
else if (rc == 0) {
printf("hello, I am child (pid:%d)\n", (int)getpid());
char myChar='a';
write(fd, &myChar,1);
printf("writing a character to the file from child\n");
}
else {
printf("hello, I am parent of %d (pid:%d)\n",
rc, (int)getpid());
char myChar='b';
write(fd, &myChar,1);
printf("writing a character to the file from parent\n");
}
return 0;
}
The parent will write "a" into myFile.txt while the child writes "b" into that file. I executed this program several times, finding the txt file consistent being "ba", meaning that the parent always comes after the child. However, I noticed that there's no wait() function called by the parent process. Can someone explain why the parent comes after the child?
The order of concurrent tasks are implementation defined by the OS. You need to use synchronization primitives to ensure a well defined order of actions if required (file locks, pipes, mutex, condition variables, semaphores etc).
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!
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;
}
I have a very simple basic program that has two process first one is parent and second one is child.
Child process should write some stuff to the FIFO. After all writing jobs finished(after the child is terminated).
Then parent process should read all the FIFO file and print to the stdout.
So I think, I need a wait(NULL); for parent. So the parent will wait until the child is terminated. But child is also blocked because of the writing and blocked for reading this writes. So both process wait each other and I think,there occur an deadlock.
My program is this:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
int writeSomeStuffToFifo ();
void printAllFifo ();
char * myfifo = "myfifo";
int main(int argc, char **argv) {
int pid=0;
int childPid=-1;
int status;
pid=fork();
if ((pid = fork()) < 0){
perror("fork() error");
}
else if (pid == 0) {
writeSomeStuffToFifo ();
exit(1);
}
else do {
if ((pid = waitpid(pid, &status, WNOHANG)) == -1)
perror("wait() error");
else if (pid == 0) {
//child running
printf("child running\n");
}
else {
if (WIFEXITED(status)){
printf("child is terminated\n");
printAllFifo();
}
else{
printf("child did not exit successfully\n");
}
}
} while (pid == 0);
return 0;
}
int writeSomeStuffToFifo (){ //child process will run this function
int fd;
mkfifo(myfifo, 0666);
fd = open(myfifo, O_WRONLY);
write(fd,"foo1\n",strlen("foo1\n"));
close(fd);
fd = open(myfifo, O_WRONLY);
write(fd,"foo2\n",strlen("foo2\n"));
close(fd);
fd = open(myfifo, O_WRONLY);
write(fd,"foo3\n",strlen("foo3\n"));
close(fd);
}
void printAllFifo (){ //parent process will run this function
int fd=open(myfifo, O_RDONLY);
char* readBuffer=(char*)malloc((strlen("foo1\n")+strlen("foo2\n")+strlen("foo3\n"))*sizeof(char));
read(fd, readBuffer, strlen("foo1\n")+strlen("foo2\n")+strlen("foo3\n"));
printf("%s\n",readBuffer );
close(fd);
}
mkfifo() creates a pipe of limited size. You should not wait in the parent process until the child has finished in order to read, you should read constantly in the parent process while checking if the child has terminated already.
You can use ulimit -p in order to read the default size of pipes in your linux system. The number is multiplications of 512, so a value of 8 means 4096 bytes.
Using pipe() is more suited to the task than mkfifo() because you do not actually need a named pipe. this will provide you with 2 fds, one for read and one for write. In the parent code you close the write fd, in the child code you close the read fd, then you can start reading from the pipe in the parent code until it returns a value <= 0. This would mean that the child process has terminated (and the pipe was closed for writing). then you only need to call waitpid() from the parent code to collect the terminated child process.
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.