Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 07/10/2016, à 02:02

Maralex

[Résolu] Problème de compilation avec siginfo_t

Bonjour!

Je veux faire deux programme qui vont communiquer en envoyant des signaux temps réel. Pour faire un test j'utilise deux programmes inspirer d'un livre. le premier, "SigServ.c" compile bien et semble fonctionner adéquatement. Il sert à envoyer un signal à un processus. Il prend en paramêtre le pid du processus, le numéro du signal qu'on veux envoyer et une valeur qu'on peut transmettre avec le signal dans le cas des signaux temps réel. J'utilise ubuntu 16.04.

SigServ.c

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>


void syntaxe(const char * nom){

  fprintf(stderr,"syntaxe %s signal pid...\n",nom);
  exit(EXIT_FAILURE);
}//fin de syntaxe


int main(int argc, char *argv[]){

  int i;
  int numero;
  int pid;
  union sigval valeur;
  
  if(argc==1)
    syntaxe(argv[0]);

  i=1;
  if(argc==2){
    numero=SIGTERM;
  }else{
    if(sscanf(argv[i],"%d",&numero)!=1);
    syntaxe(argv[0]);
    i++;
  }//fin du else
  if((numero<0)||(numero>NSIG-1))
    syntaxe(argv[0]);
  valeur.sival_int=0;
  for(;i<argc;i++){
    if(sscanf(argv[i],"%d",&pid)!=1)
      syntaxe(argv[0]);
    if(sigqueue((pid_t)pid,numero,valeur)<0){
      fprintf(stderr,"%d : ",pid);
      perror("");
    }//fin du if
  }//fin du for
  return EXIT_SUCCESS;
  
}//fin du main

Le deuxième programme reçoit le signal et la valeur transmise. Ensuite il affiche le numéro de signal et la valeur transmise avec le signal. J'obtiens un erreur à la compilation. Je pense que gcc ne trouve pas la définition de struct info_t. Voici le code source.

SigInfo.c

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void gestionnaire(int numero, struct siginfo_t * info,void * inutilise){

  fprintf(stderr,"Recu %d\n",numero);
  fprintf(stderr,"  si_code=%d\n",info->si_code);
  
}//fin de gestionnaire

int main(void){

  int i;
    struct sigaction action;
  char chaine[5];

  action.sa_sigaction=gestionnaire;
  action.sa_flags=SA_SIGINFO;
  sigemptyset(&action.sa_mask);
  fprintf(stderr,"PID=%ld\n",(long)getpid());
  for(i=1;i<NSIG;i++)
    if(sigaction(i,&action,NULL)<0)
      fprintf(stderr,"%d nom intercepte \n",i);
  while(1)
    fgets(chaine,5,stdin);

  return EXIT_SUCCESS;
}//fin du main

Voici les message que j'obtiens lors de la compilation:

SigInfo.c:8:38: warning: ‘struct siginfo_t’ declared inside parameter list
 void gestionnaire(int numero, struct siginfo_t * info,void * inutilise){
                                      ^
SigInfo.c:8:38: warning: its scope is only this definition or declaration, which is probably not what you want
SigInfo.c: In function ‘gestionnaire’:
SigInfo.c:11:39: error: dereferencing pointer to incomplete type ‘struct siginfo_t’
   fprintf(stderr,"  si_code=%d\n",info->si_code);
                                       ^
SigInfo.c: In function ‘main’:
SigInfo.c:21:22: warning: assignment from incompatible pointer type [-Wincompatible-pointer-types]
   action.sa_sigaction=gestionnaire;
                      ^

Comment résoudre ce problème et utiliser la transmission d'une valeur avec un signal temps réel??

Merci!

Yves

Dernière modification par Maralex (Le 07/10/2016, à 19:47)

Hors ligne

#2 Le 07/10/2016, à 04:28

pingouinux

Re : [Résolu] Problème de compilation avec siginfo_t

Bonjour,
Il n'y a plus d'erreur de compilation en remplaçant la ligne 6 de Siginfo.c

void gestionnaire(int numero, struct siginfo_t * info,void * inutilise){

par

void gestionnaire(int numero, siginfo_t * info,void * inutilise){

Je ne suis pas allé plus loin.

Hors ligne

#3 Le 07/10/2016, à 19:44

Maralex

Re : [Résolu] Problème de compilation avec siginfo_t

Bonjour et Merci!

Tu as raison!
Quand j'y repense je ne pensais jamais que mon erreur pouvait être aussi simple que ça! J'avais été confus parce que tous les exemples que je trouvais portait sur siginfo et non siginfo_t et tous les exemples ont la ligne struct dedans Je ne sais pas pourquoi ils la mettent. Lorsque j'y réfléchis un peu la ligne struct n'avait vraiment pas à être la.

J'ai aussi retravaillé mes deux petits utilitaires qui me permettre de tester la communication par signaux. Je vais les mettres ici puisque j'ai fouillé beaucoup sur le net et je trouve qu'il n'y a pas beaucoup d'information pour quelqu'un qui comme moi commence dans les signaux. Je les ai renommé de façon plus significative. SigRecv.c est celui qui reçois les signaux et SigSend.c envoie les signaux.

SigSend.c prend entre un et trois paramètres. Le premier paramètre est le pid du processus auquel on envoye le signal, le deuxième est le numéro du signal à envoyer et dans le cas des signaux temps réel le troisième est la valeur qu'on peut envoyer avec le signal. Si la valeur n'est pas spécifier elle prend une valeur par défaut de -1. Si le numéro de signal n'est pas spécifié il prendra la valeur SIGTERM.

#include <signal.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>


int main(int argc, char *argv[]){

  int numero;
  int pid;
  union sigval valeur;

  fprintf(stdout,"Signaux classique sont compris entre %i et %i\n",0,SIGRTMIN-1);
  fprintf(stdout,"Signaux temps reel sont compris entre %i et %i\n",SIGRTMIN,SIGRTMAX);

  if(argc==1){
    fprintf(stderr,"Syntaxe: %s pid signal valeur\n",argv[0]);
    exit(EXIT_FAILURE);
  }//fin du if
    

  if(argc>1){
    numero=SIGTERM;
    valeur.sival_int=-1;
    sscanf(argv[1],"%d",&pid);
  }//fin du if
	
  if(argc>2){
    valeur.sival_int=-1;
    sscanf(argv[2],"%d",&numero);
    if((numero<0)||(numero>NSIG-1)){
      fprintf(stderr,"signal %i invalide\n",numero);
      fprintf(stderr,"Syntaxe: %s pid signal valeur\n",argv[0]);
      exit(EXIT_FAILURE);
    }//fin du if
  }//fin du if
  
  if(argc>3){
    sscanf(argv[3],"%d",&valeur.sival_int);
  }//fin du if

    fprintf(stdout,"pid=%i signal# %i sival_int=%i\n",pid,numero,valeur.sival_int);
    if(sigqueue((pid_t)pid,numero,valeur)<0){
      fprintf(stderr,"%d : ",pid);
      perror("");
    }//fin du if
  
  return EXIT_SUCCESS;
  
}//fin du main


SigRecv.c ne prend pas de paramètre en ligne de commande. Lors de l'éxecution il affichera sont numéro de pid et la liste des signaux qui sont bloqué et qui ne seront donc pas reçu si on les lui envoie. Par la suite il affichera le numéro et la valeur de chaque signal qu'il recevra. Pour mettre fin au processus il sufit de lui envoyer le signal #36 avec la valeur #28. Pourquoi 36 et 28 simplement parce que je devais bien choisir des valeurs!!

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int continu=1;

void gestionnaire(int numero, siginfo_t * info,void * inutilise){

  fprintf(stderr,"Recu signal=%d : valeur=%d\n",numero,info->si_value.sival_int);
  switch(numero){

  case 36:
    if(info->si_value.sival_int==28)continu=0;//Termine le processus
    break;
    
  }//fin du switch
  
}//fin de gestionnaire

int main(void){

  int i;
    struct sigaction action;
  char chaine[5];

  action.sa_sigaction=gestionnaire;
  action.sa_flags=SA_SIGINFO;
  sigemptyset(&action.sa_mask);
  fprintf(stderr,"PID=%ld\n",(long)getpid());
  for(i=1;i<NSIG;i++)
    if(sigaction(i,&action,NULL)<0)
      fprintf(stderr,"%d nom intercepte \n",i);
  while(continu==1)
    fgets(chaine,5,stdin);

  return EXIT_SUCCESS;
}//fin du main

En espérant que mes deux petits programmes pourront aider quelqu'un.

Encore merci de l'aide que vous m'avez apporté!

Maralex

Hors ligne