Développement en C sous Linux : pthread et la fonction sleep().

Un petit exemple vaut mieux que de grands discours, voici le source en C :

#include 
#include 
#include 
#include <sys/time.h>
#include <sys/types.h>
#include 
static long debut = 0;
void* longue_pause(void* a){
        pid_t t = getpid();
        printf("pid = %d\n",(int)t);
        printf("thread longue_pause %d debut : %ld\n",(int)pthread_self(),time(0)-debut);
        sleep(10);
        printf("thread longue_pause %d fin : %ld\n",(int)pthread_self(),time(0)-debut);
}
void* petites_pauses(void* a){
	int i = 0;
        pid_t t = getpid();
        printf("pid = %d\n",t);
        printf("thread petites_pauses %d debut : %ld \n",(int)pthread_self(), time(0)-debut);
        for(; i < 10 ;++i){
                printf("thread petites_pauses %d en cours : %ld \n",(int)pthread_self(), time(0)-debut);
                sleep(1);
        }
}
int main(){
        pthread_t longue;
        pthread_t petit1;
        pthread_t petit2;
        debut = time(0);
        pthread_create(&longue,NULL,longue_pause,NULL);
        pthread_create(&petit1,NULL,petites_pauses,NULL);
        pthread_create(&petit2,NULL,petites_pauses,NULL);
	sleep(8);
	printf("Debut join: %ld\n",time(0)-debut);
        pthread_join(longue,NULL);
        printf("fin long : %ld\n",time(0)-debut); 
        pthread_join(petit1,NULL);
	printf("fin petit1 : %ld\n",time(0)-debut);	
        pthread_join(petit2,NULL);
	printf("fin petit2 : %ld\n",time(0)-debut);
}

Pour la compilation :

$ gcc test_pthread_test.c -lpthread -o test2

On lance le test :

$ ./test2 
pid = 324
thread longue_pause 1078445824 debut : 0
pid = 324
thread petites_pauses 1070053120 debut : 0 
thread petites_pauses 1070053120 en cours : 0 
pid = 324
thread petites_pauses 1061660416 debut : 0 
thread petites_pauses 1061660416 en cours : 0 
thread petites_pauses 1070053120 en cours : 1 
thread petites_pauses 1061660416 en cours : 1 
thread petites_pauses 1070053120 en cours : 2 
thread petites_pauses 1061660416 en cours : 2 
thread petites_pauses 1070053120 en cours : 3 
thread petites_pauses 1061660416 en cours : 3 
thread petites_pauses 1070053120 en cours : 4 
thread petites_pauses 1061660416 en cours : 4 
thread petites_pauses 1061660416 en cours : 5 
thread petites_pauses 1070053120 en cours : 5 
thread petites_pauses 1061660416 en cours : 6 
thread petites_pauses 1070053120 en cours : 6 
thread petites_pauses 1070053120 en cours : 7 
thread petites_pauses 1061660416 en cours : 7 
Debut join: 8
thread petites_pauses 1070053120 en cours : 8 
thread petites_pauses 1061660416 en cours : 8 
thread petites_pauses 1070053120 en cours : 9 
thread petites_pauses 1061660416 en cours : 9 
thread longue_pause 1078445824 fin : 10
fin long : 10
fin petit1 : 10
fin petit2 : 10

Le petit exemple nous montre bien qu’aucun sleep() ne fait une attente sur les autres pthreads, même celui dans le main().

J’ai pu voir sur des forums :

Effectivement sur le POSIX il est marqué : http://pubs.opengroup.org/onlinepubs/9699919799/functions/sleep.html :

The sleep() function shall cause the calling thread to be suspended from execution until either the number of realtime seconds specified by the argument seconds has elapsed or a signal is delivered to the calling thread and its action is to invoke a signal-catching function or to terminate the process.

Mais si beaucoup de personne se pose la question c’est que cela n’a pas toujours été le cas. Sauf problème de mémoire j’ai vu le changement entre la Redhat 8.0 et la Fédora 9.0.

Mes OS de développement ont été (dans l’ordre) :

  • Redhat 5.2 ( la seule version que j’ai acheté, misère – pour information la date de release est : 2 novembre 1998 ) : A l’université de Toulouse.
  • SuSE ? : Chez Centre Océanographique de Marseille.
  • Debian ? : Chez Cyber-workers / Alias .
  • Redhat ? : Chez Rightvision
  • Redhat 7.2 : Chez Honeywell / SeCOM
  • Redhat 8.0 : Chez Honeywell / SeCOM
  • Fédora 9.0 : Chez Honeywell / SeCOM
  • Fédora 14.0 : Chez Honeywell / SeCOM
  • Fédora 17.0 : Chez Honeywell / SeCOM
  • Oracle 7.0 : Chez Honeywell / SeCOM
  • Oracle 7.2 : Chez Honeywell / SeCOM
  • Oracle 7.3 : Chez Honeywell / SeCOM
  • Oracle 7.4 : Chez Honeywell / SeCOM
  • Oracle 7.5 & Fédora 26 sous Docker : Chez Honeywell / SeCOM
  • Ubuntu 16.04 :  Chez Honeywell / SeCOM

Chez moi c’est plutôt Raspbian STRETCH ( Débian )  : https://www.raspberrypi.org/downloads/raspbian/ .

Bref, cela fait seulement 20 ans que je suis sous Linux.

Ma version de Linux Ubuntu :

$ uname -a
Linux VirtualBox 4.15.0-36-generic #39~16.04.1-Ubuntu SMP Tue Sep 25 08:59:23 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

Au passage on peut aussi voir l’impact des directives de compilation sur la taille :

$ gcc test_pthread_test.c -lpthread -o test2
$ gcc test_pthread_test.c -lpthread -O2 -o test2-O2
$ gcc test_pthread_test.c -lpthread -O3 -o test2-O3
$ gcc test_pthread_test.c -lpthread -O -o test2-O
$ gcc test_pthread_test.c -lpthread -g -o test2-g
$ gcc test_pthread_test.c -lpthread -g -O3 -o test2-g-03
$ ls -l test2*
13208  test2
15024  test2-g
14880  test2-g-03
9120   test2-O
9120   test2-O2
9120   test2-O3

Voila.

(Bisous à Luc)