I want to write a code using pipes. This code is about the rock, scissor, paper game, so I need to ask and receive messages all the time until one of two players score 3. So far, now I have the following code, but I don´t know how to iterate this code, could be with a while iteration?
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define READ_END 0 /* index pipe extremo escritura */
#define WRITE_END 1 /* index pipe extremo lectura */
int main(int argc, char* argv[])
{
int fd1[2],fd2[2];
int status, pid;
pipe(fd1); /* comunica ls y grep */
pid = fork();
if(pid == 0) /* hijo 1*/
{
close(fd1[READ_END]); /* cerrar extremo no necesario */
dup2(fd1[WRITE_END], STDOUT_FILENO);
close(fd1[WRITE_END]);
}
else /* padre */
{
close(fd1[WRITE_END]); /* extremo no necesario ya */
pipe(fd2); /* comunica grep y wc */
pid = fork();
if(pid == 0) /* hijo 2 */
{
close(fd2[READ_END]); /* cerrar extremo no necesario */
dup2(fd1[READ_END], STDIN_FILENO);
close(fd1[READ_END]);
dup2(fd2[WRITE_END], STDOUT_FILENO);
close(fd2[WRITE_END]);
}
else /* padre */
{
close(fd1[READ_END]); /* cerrar extremo no necesario */
close(fd2[WRITE_END]); /* cerrar extremo no necesario */
}
}
close(fd2[READ_END]); /* cerrar extremo que queda abierto en el padre */
/* wait para cada hijo */
wait(&status);
wait(&status);
return 0;
}
I want to make the parent processes (P1 and P2) wait for their respective child processes(P3 and P4) to terminate using waitpid (basically, parent processes can only terminate after the children terminates). Here's the code below. I'm portuguese, sorry for having non-english words on the code.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
int main()
{
int estado1, estado2;
pid_t p = fork();
pid_t k = fork();
if(p>0) //Execução do pai
{
waitpid(p, &estado1, 0); //Don't know how waitpid works that well either
waitpid(k, &estado2, 0);
printf("p=%d: PID = %d;\t", p, getpid());
// \t é para dar um tab (o que se usa nas indentações)
sleep(45);
printf("O processo pai terminou.\n");
exit(0);
}
else if(p==0) //Execução do filho
{
printf("p=%d: PID = %d;\t", p, getpid());
// \t é para dar um tab (o que se usa nas indentações)
printf("O processo filho terminou.\n");
exit(0);
}
else if(p<0)
{
printf("ERRO! p=%d\n", p);
exit(p);
}
}
This is what I have but I think it isn't right.
Thanks in advance.
Edit: Thanks to zeroSpook for fixing my text :)
The following program is supposed to do this:
The main process should create a child process,which I will refer to as main child from now on for convenience,then wait for a SIGUSR2 signal, then send a SIGUSR1 signal to his child and grandchildren, then wait for his child and finally end.
The main child should do the following 4 times: create a child and wait for SIGUSR2. After that the process should send a SIGUSR2 to his father,then wait for SIGUSR1, then wait for his children to end and finally end.
The main child's children should print Proceso "PID" listo,then send a SIGUSR2 to the main child,then wait for SIGUSR1,then print Señal capturada and finally end.
However it just prints one PID and then it never ends unless I use CTRL^C.I've tried changing the order of the pause() fucntions but to no avail. Also this is homework for college and they said we can't use semaphores yet.
If you know Spanish here are the instructions:
• El proceso padre generará un proceso hijo, que será el proceso gestor.
• El proceso gestor creará N_PROC procesos hijos (los participantes en la competición) en un
bucle, esperando tras crear cada proceso a que éste le notifique que está preparado
enviándole la señal SIGUSR2 .
• Cada participante en la carrera, una vez activo y con la señal armada, imprimirá un mensaje
y avisará al gestor mediante la señal SIGUSR2 .
• El proceso gestor, cuando haya creado los N_PROC procesos hijos y éstos estén listos para la
competición, avisará al proceso padre de que está todo listo enviándole la señal SIGUSR2 .
• El proceso padre mandará al grupo entero de procesos la señal
de la competición).
• Cuando los participantes en la carrera reciban la señal
ya han capturado la señal, y terminarán.
• Cuando el proceso gestor reciba SIGUSR1 , terminará su ejecución sin dejar hijos huérfanos.
• El proceso padre esperará a que el proceso gestor termine y acabará él también.
Thanks in advance.
#include <stdio.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define N_PROC 4
void manejador_SIGUSR1(int sig) {
printf("Señal capturada\n");
exit(EXIT_SUCCESS);
}
void manejador_SIGUSR2(int sig) {
}
int main(void){
int i,pid[N_PROC+1];
struct sigaction act;
sigemptyset(&(act.sa_mask));
act.sa_flags = 0;
/* Se arma la señal SIGUSR1. */
act.sa_handler = manejador_SIGUSR1;
if (sigaction(SIGUSR1, &act, NULL) < 0) {
perror("sigaction");
exit(EXIT_FAILURE);
}
act.sa_handler = manejador_SIGUSR2;
if (sigaction(SIGUSR2, &act, NULL) < 0) {
perror("sigaction");
exit(EXIT_FAILURE);
}
if((pid[0] = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if(pid[0] == 0) {
for(i=0;i<N_PROC;i++){
if((pid[i+1] = fork()) == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if(pid[i+1]==0){
printf("Proceso %d listo\n",getpid());
kill(SIGUSR2,getppid());
pause();
}
else{
pause();
}
}
kill(SIGUSR2,getppid());
pause();
while(wait(NULL)>0);
exit(EXIT_SUCCESS);
}
pause();
kill(SIGUSR1,0);
while(wait(NULL)>0);
exit(EXIT_SUCCESS);
}
Short Answer
Your arguments to kill are swapped, as #Arkku noted in the comments. Your "main process" waits forever for a SIGUSR2 from its very first child, which it never receives.
Aside
Ha! An assignment about race conditions given in the language of races (la carrera, le señal de competición). That's great.
If I understand correctly, the desired flow is something like this:
+--> [competitor]
+--> [competitor]
[starter] --> [manager] -+--> [competitor]
+--> [competitor]
Starter creates manager
Manager gets competitors to the starting line
Create a competitor
Wait for the competitor to indicate it is ready (SIGUSR2)
Repeat for N_PROC competitors total
Manager tells the starter that competitors are ready (SIGUSR2)
Starter fires the starting pistol (SIGUSR1 to process group)
Competitors race!
Manager process terminates after reaping all competitors.
Starter terminates after reaping manager.
Several things can go wrong here. Notably, #PSkocik's comment is right: you should use sigwait or similar functions to avoid unintended races. Also, please don't use printf in a signal handler.
Hi I've to develop this program that create 4 children and, sequentially, make 'em do a simple operation. The first will do the sum, the second the rest, the third the multiplication and the fourth the division. The father will write on the socket the string with the two number he wants his children to "calculate", and every children should read this string, extract the numbers and to the operations. Obviously, being two pipes, it's needed that the father writes every time the string, because of the read in the child. I don't really understand why at the second iteration, i receive a SIGPIPE on the write of the father. Can someone explain me why? I losed 3 days on debugging, but I didn't find anything. Thank you very much.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <fcntl.h>
/*
fd_0 padre escribe y hijo lee ==== padre cierra fd_0[0] y hijo cierra fd_0[1]
fd_1 hijo escribe y padre lee === padre cierra fd_1[1] y hijo cierra fd_1[0]
*/
int main (int argc, char * argv[]){
char * str = malloc(100*sizeof(char));//hijo
char readbuffer_h[150];
char * stringa = malloc(100*sizeof(char));//padre
char readbuffer_p[150];
int a,b;
int x,y;
int n = 4;
int i,status,nbytes, pipe_status;
int pid, ppid,yo,padre;
int fd_0[2], fd_1[2] ;
pipe_status=pipe(fd_0);
if(pipe_status==- 1) {
perror("Error creando la tuberia 0\n");
exit(EXIT_FAILURE);
}
pipe_status=pipe(fd_1);
if(pipe_status== -1) {
perror("Error creando la tuberia 1 \n");
exit(EXIT_FAILURE);
}
for(i=0; i< n; i++){
if ((pid=fork()) <0 ){
printf("Error al emplear fork\n");
exit(EXIT_FAILURE);
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
else if (pid ==0){// soy el hijo
yo = getpid();
padre = getppid();
printf("HIJO: %d, mi padre es: %d\n", yo, padre);
close(fd_0[1]);
close(fd_1[0]);
//TODO
nbytes = read(fd_0[0], readbuffer_h, sizeof(readbuffer_h));
sscanf(readbuffer_h, "%d,%d", &x, &y);
switch(i) {
case 0 :
//TODO
sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. La suma es %d", yo,x,y,(x+y));
break;
case 1 :
//TODO
sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. La resta es %d", yo,x,y,(x-y));
break;
case 2 :
//TODO
sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. El producto es %d", yo,x,y,(x*y));
break;
case 3 :
//TODO
sprintf(str, "Datos enviados a través de la tuberia por el proceso hijo: %d. Primero operando: %d, segundo operando: %d. El cociente es %d", yo,x,y,(x/y));
break;
}
write(fd_1[1], str, strlen(str));
exit(EXIT_SUCCESS);
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------*/
else{ //soy el padre
yo = getpid();
printf("PADRE:%d\n", yo);
a = 3; b = 4;
close(fd_0[0]);
close(fd_1[1]);
sprintf(stringa,"%d,%d",a,b);
printf("Stringa padre : %s\n", stringa);
fflush(stdout);
write(fd_0[1],stringa,strlen(stringa)); // questa write non va a buon fine
wait(&status);
read(fd_1[0], readbuffer_p, sizeof(readbuffer_p));
printf("%s\n",readbuffer_p);
fflush(stdout);
}
}
close(fd_0[0]);
close(fd_0[1]);
close(fd_1[0]);
close(fd_1[1]);
return 0;
}
You're getting yourself into trouble by trying to use the same pipes to communicate with each child.
You create two pipes at the beginning of the program. On the first iteration of the loop, the parent forks, and the child inherits all the parent's open file descriptors. The child closes the pipe ends it doesn't need, and the parent closes the pipe ends it doesn't need. Communication happens as intended (I imagine) -- all well and good so far.
But now consider the second iteration of the loop. You fork again, and the child again inherits the parent's open file descriptors. But now, the file descriptors the child wants to use were closed by the parent in the previous iteration of the loop. I'm a bit surprised that the child then gets an EPIPE instead of an EBADF when it tries to use those file descriptors, but I'm not at all surprised that its read attempt fails.
The cleanest thing to do would be to create a new pair of pipes for each child, instead of trying to reuse one set of pipes. If you want to make it work with just the one pair, then the parent process must avoid closing any of the pipe ends (though the child processes may close their copies, if you wish).
I have this solution for an exercise I was doing but when I try to run it
and send SIGUSR1 the terminal shows "Stack fault", and I don't know why.
It shows nothing when I send SIGUSR2, but the thing is that with SIGTERM and SIGINT the program works.
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
void manejador(int signum){
switch (signum){
case SIGUSR1:
printf("He recibido la señal SIGUSR1\n");
break;
case SIGUSR2:
printf("He recibido la señal SIGUSR2\n");
break;
case SIGTERM:
printf("Fin de ejecucion\n");
exit(EXIT_SUCCESS);
}
}
int main(int argc, char *argv[])
{
if (signal(SIGUSR1, manejador) == SIG_ERR) {
perror("error en la señal SIGUSR1");
exit(EXIT_FAILURE);
}
if (signal(SIGUSR2, manejador) == SIG_ERR) {
perror("error en la señal SIGUSR2");
exit(EXIT_FAILURE);
}
if (signal(SIGTERM, manejador) == SIG_ERR) {
perror("error en SIGTERM");
exit(EXIT_FAILURE);
}
if (signal(SIGINT, SIG_IGN) == SIG_ERR) {
perror("error en SIGINT");
exit(EXIT_FAILURE);
}
while (1)
pause();
}