Using Pipes in C - 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.

Related

how to synchronize two process

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

C on LINUX - Multiple child proces exec unusual number of times

I'm trying to create n = 10 child processes and make its execute a peace of code ..
However it creates 14 child processes indifferent of n.
Why is that?
This is the sample code :
#include <stdlib.h>
#include <stdio.h>
int main()
{
printf("It worked! ");
return 0;
}
And this is the main program:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
int main (int argc, char *argv[])
{
int n = 10;
pid_t pid;
int status = 0;
int fd2[2];
int i = 0;
while (i < n)
{
/*create the pipe */
if (pipe(fd2) == -1)
{
fprintf(stderr, "Problem at pipe: %s\n", strerror(errno));
exit(1);
}
/*create fork*/
pid = fork();
if (pid == -1)
{
fprintf(stderr, "Problem at fork: %s\n", strerror(errno));
exit(1);
}
else if (pid == 0) /*in child*/
{
close(fd2[0]);
close(1);
dup2(fd2[1], 1);
close(fd2[1]);
execl("sample.bin", "sample.bin", NULL);
fprintf(stderr, "Problem at exec: %s", strerror(errno));
exit(1);
}
/* in parent */
close(fd2[1]);
char line[255];
if (n = read(fd2[0], line, 254))
{
printf("%d The message is: %s\n", i, line);
}
close(fd2[0]);
wait(&status);
i++;
}
return 0;
}
I corrected the code, now the output is what I've expected. And of course another problem was that I used at read the same variable n.
I modified from this:
if (n = read(fd2[0], line, 254))
{
printf("%d The message is: %s\n", i, line);
}
To this:
int m;
while((m = read(fd2[0], line, 254) > 0)
{
printf("%d The message is: %s\n", i, line);
}

Create child process, make parent of the child to transmit a file.How do i do this?

This is my code.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
int file,parentID,childID;
pid_t pid;
int main(int argc, char *argv[])
{
if( argc != 2 )
{
printf("ERROR ! You have not write an argument\n");
printf("ERROR ! You give more than one argument");
return 1;
}
file = open(argv[1], O_RDONLY); //open file
if(file<0) //test the file
{
printf("Error open file\n");
printf("ERROR : %s\n", strerror(errno));
return 1;
}
// ---------------------------------------------------------------------
pid = fork();
if( pid == -1) //error fork
{
printf("Error fork\n");
return 1;
}
if(pid == 0) // child process
{
childID = getpid();
printf("Child process %d\n",childID);
// if(childID %2 == 1)
// {
// parentID = getppid();
// printf("Process of father of this child= %d\n",parentID);
// }
}
if( pid == 1)
{
parentID = getppid();
printf("ParentProcess %d\n",parentID);
}
}
I have to write a program to create a child process.Depending on the parity of the child process , the parent should transmit to child a message through a file , the message being taken over and showed by the child process( if the child process is a number that is divizible with 2 it will say -"Good morning!" else "Good night!" ).The parent should wait for the final execution of the child to terminate.
I'm trying really hard to do this exercise and i can't find anywere to explain me how or what function/structure object should i use to do this.Above i tried but i failed , and i understand somehow how fork does but... please help me with this code , or suggest me were should i go to read to make this exercise .Sorry for my bad english spelling.
What documentation are you using for the system calls?
There are a number of ways to do this, but what you probably want to do is create a pipe, and then fork the process. Since a fork copies everything, and child processes inherit the environment, each process has a copy of the file descriptors for the pipe. You can then read/write based on the return value of fork().
int main(int argc, char *argv[])
{
int fd[2];
char in[128], out[128];
if( argc != 2 )
{
printf("ERROR ! You have not write an argument\n");
printf("ERROR ! You give more than one argument");
return 1;
}
if (pipe(fd) == -1)
return 1;
// ---------------------------------------------------------------------
pid = fork();
if (!pid)
read(fd[0], in, 128);
else
write(fd[1], out, strlen(out) + 1);
pipe(2)
note, you usually want to close the file descriptor you're not using for one way communication
I think this is the code.
#include <stdio.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>
void sighandler (int sig)
{
if (sig == SIGUSR1)
{
FILE *f;
char line[100];
f = fopen("file","r");
fgets(line, 100, f);
printf ("Procesul copil cu pid %d a primit mesajul %s", getpid(), line);
fclose(f);
}
}
int main ()
{
pid_t pid;
FILE * f;
pid = fork();
if (pid < 0)
{
perror ("Eroare la fork()");
return (1);
}
else
if (pid == 0)
{
signal (SIGUSR1, sighandler);
pause();
return 0;
}
else
{
if (pid % 2 == 0)
{
printf ("Notificam procesul fiu cu pid %d", pid);
f = fopen ("file","w");
fprintf (f,"Good morning!");
fclose(f);
kill (pid, SIGUSR1);
}
else
{
printf ("Notificam procesul fiu cu pid %d", pid);
f = fopen ("file","w");
fprintf (f,"Good night!");
fclose(f);
kill (pid, SIGUSR1);
}
}
wait(NULL);
return 0;
}

Fork() and Posix Queues. Send and Receive strings

what I want is this:
1 main process that create 4 children process where:
-> The main process receive messages from the children through the queue and print the message recieved.
-> The children send messages (a string with priority+message) through the queue and finish.
All in a while (1), so, when you CTRL+C, the children finish first (the signal is in the children code) and then, the parent finish.
For the moment, I am having problem with mq_send() and mq_recieve().
Well, this is my code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
#include <mqueue.h>
void sigint_handler()
{
/*do something*/
printf("killing process %d\n",getpid());
exit(0);
}
int main ()
{
mqd_t mqd;
struct mq_attr atributos;
// atributos.mq_maxmsg = 10;
//
// atributos.mq_msgsize = 50;
printf ("This is the parent. PID=%d\n",getpid ());
int num_children = 4;
int i;
int pid;
int status;
char buffer [50];
while (1){
for (i=0; i<num_children ;i++){
if ((pid=fork()==0)){
signal(SIGINT, sigint_handler);
int prio = rand () % 3;
printf ("%d\n",prio);
char * msg= "Hi dude";
char * priority=NULL;
if (prio == 0){
priority = "NORMAL";
}
else {
priority = "URGENT";
}
char* toSend=NULL;
toSend = malloc(strlen(msg)+1+strlen(priority));
strcpy (toSend,priority);
strcat (toSend,msg);
printf ("%s\n",toSend);
if ((mqd=mq_open("/queue.txt", O_CREAT|O_WRONLY, 0777, &atributos))==-1){
printf ("Error mq_open\n");
exit(-1);
}
if (mq_send(mqd, msg , strlen(toSend), prio) == -1) {
printf ("Error mq_send\n");
exit (-1);
}
mq_close(mqd);
printf ("This is children %d\n",getpid());
sleep(1);
exit(0);
}
}
if ((mqd=mq_open("/queue.txt", O_CREAT|O_WRONLY, 0777, &atributos))==-1){
printf ("Error mq_open\n");
exit(-1);
}
//Rest Parent code
if (mq_receive(mqd, buffer, strlen(buffer),0)==-1){
printf ("Error mq_recieve\n");
exit(-1);
}
printf("Received: %s\n",buffer);
sleep (1);
waitpid(pid,&status,0);
printf ("This is the parent again %d, children should have finished\n",getpid());
mq_close(mqd);
}
}
I don't know why both mq_send() and mq_receive() returns -1, what am I doing wrong¿?
And you you see something wrong in my code in order to do what I intend apart from the error I am talking about, let me know.
Thank you in advance, I appreciate any help.
user58697 touched upon the biggest problems.
(1) Your queue opens were failing with EINVAL because you wee passing uninitialized attributes because you commented out assignments.
(2) You were opening both queues for write-only. The parent queue needed to be opened in read mode.
(3) Execute permissions don't mean anything to a queue so 777 permissions while not invalid are unnecessary.
(4) Your sends/receives were failing because of invalid lengths. In many if not most cases it is just easier and safer to allocate your buffers to the length attribute of the queue. In this case you know the length before hand but in programs that don't you can get the value via mq_getattr.
(5) You weren't calling srand to seed the RNG before calling rand.
(6) You had a memory leak where you allocate space (unnecessarily) for the message but never freed it.
(7) What you were trying to do with passing priorities is redundant. POSIX MQs have priorities already built in. You can just use those.
I took out some of the fluff (mainly the loops & signals) to concentrate more on the queue aspects of your program.
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <sys/wait.h>
#include <mqueue.h>
int main()
{
srand(time(NULL));
mqd_t mqd;
struct mq_attr atributos = {.mq_maxmsg = 10, .mq_msgsize = 50};
int i;
int pid;
int status;
int num_children = 4;
char buffer[atributos.mq_msgsize];
for (i = 0; i < num_children; i++)
{
if ((pid = fork() == 0))
{
int prio = rand () % 3;
char* msg = "Hi dude";
strncpy (buffer, msg, sizeof(buffer));
if ((mqd = mq_open("/queue.txt", O_CREAT | O_WRONLY, 0666, &atributos)) == -1)
{
perror("child mq_open");
exit(1);
}
if (mq_send(mqd, buffer, sizeof(buffer), prio) == -1)
{
perror("mq_send");
exit(1);
}
mq_close(mqd);
exit(0);
}
}
// parent
if ((mqd = mq_open("/queue.txt", O_CREAT | O_RDONLY, 0666, &atributos)) == -1)
{
perror("parent mq_open");
exit(1);
}
int priority;
for (int i = 0; i < num_children; ++i)
{
if (mq_receive(mqd, buffer, sizeof(buffer), &priority) == -1)
{
perror("mq_recieve");
exit(1);
}
printf("Received (%s): %s\n", (priority == 0) ? "NORMAL" : "URGENT", buffer);
pid_t childpid;
if ((childpid = waitpid(-1, &status, 0)) > 0)
{
if (WIFEXITED(status))
printf("PID %d exited normally. Exit status: %d\n",
childpid, WEXITSTATUS(status));
else
if (WIFSTOPPED(status))
printf("PID %d was stopped by %d\n",
childpid, WSTOPSIG(status));
else
if (WIFSIGNALED(status))
printf("PID %d exited due to signal %d\n.",
childpid,
WTERMSIG(status));
}
}
mq_close(mqd);
}
First and foremost, when a system call fails, print errno (and strerror(errno)).
Now, obvious mistakes:
as was mentioned, you need a read access to be able to mq_receive()
what is strlen(buffer)?
you are passing attributes without initializing them.
To summarize, print errno and see what is wrong.

Using pipe between diffrent programs how ?

Question asked again and code modified...
I need to create three programs named as program0 program1 and program2 in linux.
Program0:Creates a parent with two child processes and executes program 1 and program 2 with its childs waits them to finish and close.
Program1:Takes a file name from the user and writes text to the file.It finishes writing when CTNL+D pressed and creates a pipe.After that by using cat command it writes file to stdout and uses dup() to create pipe which has file in it.
Program2:It reads filename from the pipe with the help of dup() and then executes wc command.
So far I managed to create all programs and I have no compling errors.Program 0 executes both programs.Program1 is also working and sends file to the pipe but program2 cannot read it from the pipe is prints weird symbols..
When I try to read from the pipe within the program1 it works(see the deactivated code in program1) but same code is not working if I put it inside program2.
So what how can I make program2 to read from the pipe after that I will try to execute wc command in program2 but first I should be able to see that its taking file input from the stdout so how?
I know its kinda long but please help me guys...
Program 0
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#define MAX 999
int main()
{
pid_t pid1, pid2;
pid1 = fork();
if(pid1<0)
{
fprintf(stderr,"Fork basarisiz");
exit(-1);
}
else if (pid1 ==0)/*child prosesleri*/
{
printf("program1\n");
execlp("./program1","program1",NULL);
execlp("./program2","program2",NULL);
}
else /*parent procsesleri */
{
wait(NULL);
pid2 = fork();
if(pid2<0)
{
fprintf(stderr,"Fork basarisiz");
exit(-1);
}
else if (pid2 ==0)/*child prosesleri*/
{
printf("\n");
printf("Program 2\n");
printf("\n");
execlp("./program2","program2",NULL);
//printf("\n");
}
else
{
}
/////////////////////////////////////////////////////////////////////////
wait(NULL);
printf("\n");
printf("Parent:Two child processes have successfully been created\n");
printf("Parent:Two child processes have successfully been terminated\n");
printf("Parent:This process will now terminate\n");
printf("\n");
exit(0);
}
}
Program 1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#define MAX 999
int main()
{
char c[10000];
char file[10000];
int words;
printf("Child1:A text file will be created\n");
printf("Child1:Enter the name of the file\n");
scanf("%123s",file);
strcat(file,".txt");
FILE * pf;
pf = fopen(file, "w" );
if (!pf)
fprintf( stderr, "I couldn't open the file.\n" );
else
{
printf("Child1: Input a number of text lines ended, each ended by a CR (carriage return).\n");
/////////////////////////////
do
{
if (NULL != fgets(c, sizeof(c), stdin))
{
if (0 == strcmp(c, ".\n"))
{
break;
}
fprintf(pf, "%s", c);
}
else
{
if (0 != ferror(stdin))
{
fprintf(stderr, "An error occured while reading from stdin\n");
}
else
{
printf("Child1: Finish the input by CNTL^D\n");
}
break;
}
} while (1);
/////////////////////////////
}
printf("\nChild1:The file %s is succesfully created and saved in the current dictionary\n",file);
//////////////////////////////////////////////
/////////////////////////pipe///////////////
fclose(pf); // close file
char ch;
int outcount = 0;
int fd[2], nbytes;
pid_t childpid;
int i;
char f2[2];
char readbuffer[80];
pipe(fd);
if((childpid = fork()) == -1)
{
perror("fork");
exit(1);
}
if(childpid == 0)
{ printf("\nChild1:The file written to pipe with cat\n");
close(1) ;
dup(fd[1]);
close(fd[0]);
execlp("/bin/cat", "cat", file,NULL);
}
else
{
wait(NULL);
//close(0) ;
//dup(fd[0]) ;
//close(fd[1]);
//nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
//printf("%s\n",readbuffer);
}
return(0);
}
Program 2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
int fd[2],nbytes;
pid_t childpid;
char readbuffer[80];
pipe(fd);
if((childpid = fork()) == -1)
{
perror("fork");
exit(1);
}
if(childpid == 0)
{
}
else
{
close(0) ;
dup(fd[0]) ;
close(fd[1]);
nbytes = read(fd[0], readbuffer, sizeof(readbuffer));
printf("%s\n",readbuffer);
}
return(0);
}
You may want to check the man pages for execve(2) (for starting cat) and dup2(2) (for overriding stdin and stdout as needed) for this one. execve will overwrite the currently executing program by a different one (same PID, same file descriptors), while dup2 will allow you re-define any of the standard file descriptors to point into any file descriptor you provide to it (such as any of the ends of your pipe).

Resources