User Tools

Site Tools


progsys:index

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Last revisionBoth sides next revision
progsys:index [2017/10/19 14:43] orelprogsys:index [2020/11/06 11:14] – [Ctrl-C] orel
Line 182: Line 182:
  
  
-== Une chaîne de commandes  ==+==== Une chaîne de commandes  ====
  
 On souhaite écrire un programme //./chaine cmd0 cmd1 cmd2 ... cmdN// qui exécute une chaîne de commandes de la façon suivante : On souhaite écrire un programme //./chaine cmd0 cmd1 cmd2 ... cmdN// qui exécute une chaîne de commandes de la façon suivante :
  
   ./cmd1 | ./cmd2 | ./cmd3 | ... | cmdN   ./cmd1 | ./cmd2 | ./cmd3 | ... | cmdN
- 
  
 Dans cette première version, chaque fils crée un nouveau fils en cascade : Dans cette première version, chaque fils crée un nouveau fils en cascade :
  
   Père ==> Fils0 ==> Fils1 ==> ... ==> FilsN-1   Père ==> Fils0 ==> Fils1 ==> ... ==> FilsN-1
- 
   (cmd0)   (cmd1)   (cmdN-1)           cmdN   (cmd0)   (cmd1)   (cmdN-1)           cmdN
  
Line 245: Line 243:
 Examinons maintenant une autre version... Nous allons juste inverser le code du père et du fils dans la boucle for ! Expliquer par quel miracle ce code peut marcher ? Examinons maintenant une autre version... Nous allons juste inverser le code du père et du fils dans la boucle for ! Expliquer par quel miracle ce code peut marcher ?
  
 +<code C chaine2.c>
 +#include <unistd.h>
 +#include <stdio.h>
 +#include <stdlib.h>
 +
 +int main(int argc, char *argv[])
 +{
 +  int nb = argc-1;
 +  int tube[2];
 +  int i;
 +  
 +  for(i=0; i < nb-1; i++) {
 +    pipe(tube);
 +    if(fork() == 0) { /* fils */
 +      dup2(tube[1],1);
 +      close(tube[0]); 
 +      close(tube[1]);
 +      break; 
 +      
 +    } else { /* père */
 +      dup2(tube[0],0);
 +      close(tube[0]); 
 +      close(tube[1]);
 +    }
 +  }  
 +
 +  execlp(argv[i+1], argv[i+1], NULL); 
 +  perror("execlp"); 
 +
 +  return EXIT_SUCCESS;
 +}
 +</code>
 +
 +__Indice__ :  Dans ce cas, un même père crée tous les fils de la façon suivante... mais cela n'explique pas tout !
 +  
 +  Père             (cmdN)
 +       ==> Fils0   (cmd0)
 +       ==> Fils1   (cmd1) 
 +       ==> 
 +       ... 
 +       ==> FilsN-1 (cmdN-1)
 +
 +
 +
 +==== Calculer en Pipeline ====
  
 ==Générer/afficher un fichier de k double== ==Générer/afficher un fichier de k double==
Line 329: Line 372:
   /* création de N fils */   /* création de N fils */
   for(int i = 0 ; i < N ; i++) {    for(int i = 0 ; i < N ; i++) { 
-    /* fils i qui utilise tubes[i-1] et tubes[i] */+    /* fils i qui utilise tubes[i] et tubes[i+1] */
     if(fork() == 0) {      if(fork() == 0) { 
       /* TODO: redirection tube */       /* TODO: redirection tube */
Line 747: Line 790:
     int k = atoi(argv[1]);     int k = atoi(argv[1]);
  
-    for(int s = ; s < argc ; s++)+    for(int s = ; s < argc ; s++)
       for(int i = 0 ; i < k ; i++) {       for(int i = 0 ; i < k ; i++) {
  kill(ppid, atoi(argv[s])); // envoi signal  kill(ppid, atoi(argv[s])); // envoi signal
Line 766: Line 809:
     sigemptyset(&act.sa_mask);     sigemptyset(&act.sa_mask);
      
-    for(int sig = ; sig < NSIGNORT ; sig++) {+    for(int sig = ; sig < NSIGNORT ; sig++) {
       sigaction(sig, &act, NULL);       sigaction(sig, &act, NULL);
       tab[sig] = 0;       tab[sig] = 0;
Line 874: Line 917:
      
   return 0;   return 0;
 +}
 +</code>
 +
 +==== Open Pipe Command (exo 3, DS 2017-2018) ====
 +
 +On souhaite disposer d’une fonction //open_pipe_command// dont le profil est :
 +
 +  int open_pipe_command (int *fd, char *cmd, char **argv)
 +
 +Cette fonction crée un processus chargé d’exécuter la commande //cmd// avec les arguments //argv//, et renvoie deux descripteurs (dans le tableau fd) permettant respectivement d’écrire vers l’entrée standard de la commande (descripteur fd[1]) et de lire depuis la sortie standard de la commande (descripteur fd[0]). On utilisera pour cela deux tubes permettant d’établir une connexion bidirectionnelle avec le processus exécutant la commande. La fonction retournera le //pid// du processus fils exécutant la commande.
 +
 +<code C open_pipe_command.c>
 +/* gcc -Wall -std=c99 open_pipe_command.c && ./a.out */
 +
 +#include <stdio.h>
 +#include <unistd.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <sys/types.h>
 +#include <sys/wait.h>
 +
 +#define HELLO "hello world!" // 12 
 +
 +int open_pipe_command(int * fd, char * cmd, char **argv)
 +{
 +  int pr[2]; pipe(pr); 
 +  int pw[2]; pipe(pw); 
 +  /* user reads in fd[0]=pr[0] & writes in fd[1]=pw[1] */
 +  fd[0] = pr[0]; fd[1] = pw[1];   
 +  int pid = fork();
 +  if(pid == 0) { /* child */        
 +    close(pw[1]); close(pr[0]); /* useless */
 +    /* cmd writes in pr[1]=1 & reads in pw[0]=0 */
 +    dup2(pw[0],0); dup2(pr[1],1); 
 +    close(pw[0]); close(pr[1]); 
 +    execvp(cmd, argv); 
 +    perror("Error execvp");
 +    exit(EXIT_FAILURE);
 +  }
 +  close(pw[0]); close(pr[1]); /* useless */
 +  return pid; /* success > 0*/
 +}
 +
 +int main(int argc, char * argv[])
 +{
 +  int fd[2];
 +  char* cmd[] = {"tr", "a-z", "A-Z", NULL};
 +  int pid = open_pipe_command(fd, *cmd, cmd);
 +  if(pid <= 0) return EXIT_FAILURE;
 +  write(fd[1], HELLO, strlen(HELLO)+1);
 +  close(fd[1]);
 +  char msg[128];
 +  int r = read(fd[0], msg, 128);  
 +  printf("msg[%d]: %s -> %s\n", r, HELLO, msg);
 +  close(fd[0]);
 +  waitpid(pid, NULL, 0);
 +  return EXIT_SUCCESS;
 +}
 +</code>
 +
 +==== Ctrl-C ====
 +
 +Un processus fils est dans le même PGID (process group ID) que son père par defaut (pgid père = pgid fils = pid père). Un kill sur -pid du père envoie le signal à tous le groupe, donc au fils également...
 +
 +<code C sigint.c>
 +#include <stdlib.h>
 +#include <stdio.h>
 +#include <unistd.h>
 +#include <signal.h>
 +#include <sys/types.h>
 +
 +void handler(int sig)
 +{
 +    printf("paf\n");
 +}
 +
 +int main(void)
 +{
 +    signal(SIGINT, handler); // TODO: utiliser sigaction() plutôt que signal() !
 +
 +    if (fork() == 0)
 +    {
 +        printf("child: %d %d\n", getpid(), getpgid(0));
 +        pause();
 +        printf("child: bye bye!\n");
 +        exit(EXIT_SUCCESS);
 +    }
 +
 +    printf("father: %d %d\n", getpid(), getpgid(0));
 +    pause();
 +    printf("father: bye bye!\n");
 +    return EXIT_SUCCESS;
 +}
 +</code>
 +
 +
 +==== Timeout ====
 +
 +<code C executer-avant-delai.c>
 +
 +#define _GNU_SOURCE
 +#include <unistd.h>
 +#include <signal.h>
 +#include <stdio.h>
 +#include <setjmp.h>
 +
 +static struct sigaction sa, old;
 +static sigjmp_buf env;
 +
 +static void myalarm(int sig)
 +{
 +  printf("alarm!\n");
 +  siglongjmp(env,1);
 +}
 +
 +int executer_avant_delai( void (*fun)(void *), void *parametre, int delai_en_seconde)
 +{
 +  int ret = 1;
 +  sa.sa_handler = myalarm;
 +  sa.sa_flags = 0; // SA_RESETHAND;
 +  sigemptyset(&sa.sa_mask);
 +  sigaction(SIGALRM, &sa, &old);
 +
 +  alarm(delai_en_seconde);
 +  if(sigsetjmp(env,1) == 0)
 +    fun(parametre);
 +  else
 +    ret = 0; // alarm
 +  alarm(0);
 +  sigaction(SIGALRM, &old, NULL);
 +  return ret;
 } }
 </code> </code>
progsys/index.txt · Last modified: 2024/03/18 15:06 by 127.0.0.1