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 :
Line 243: 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 327: 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 745: 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 764: 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 872: 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