𝗖 𝗶𝘀 𝘁𝗵𝗲 𝗺𝗼𝘀𝘁 𝗲𝗳𝗳𝗶𝗰𝗶𝗲𝗻𝘁 𝗽𝗿𝗼𝗴𝗿𝗮𝗺𝗺𝗶𝗻𝗴 𝗹𝗮𝗻𝗴𝘂𝗮𝗴𝗲, 𝘄𝗵𝗶𝗹𝗲 𝗣𝘆𝘁𝗵𝗼𝗻 𝗮𝗻𝗱 𝗣𝗲𝗿𝗹 𝗮𝗿𝗲 𝘁𝗵𝗲 𝗹𝗲𝗮𝘀𝘁 𝗲𝗻𝘃𝗶𝗿𝗼𝗻𝗺𝗲𝗻𝘁𝗮𝗹 𝗳𝗿𝗶𝗲𝗻𝗱𝗹𝘆 𝗽𝗿𝗼𝗴𝗿𝗮𝗺𝗺𝗶𝗻𝗴 𝗹𝗮𝗻𝗴𝘂𝗮𝗴𝗲
Artcile complet : https://medium.com/codex/what-are-the-greenest-programming-languages-e738774b1957
𝗖 𝗶𝘀 𝘁𝗵𝗲 𝗺𝗼𝘀𝘁 𝗲𝗳𝗳𝗶𝗰𝗶𝗲𝗻𝘁 𝗽𝗿𝗼𝗴𝗿𝗮𝗺𝗺𝗶𝗻𝗴 𝗹𝗮𝗻𝗴𝘂𝗮𝗴𝗲, 𝘄𝗵𝗶𝗹𝗲 𝗣𝘆𝘁𝗵𝗼𝗻 𝗮𝗻𝗱 𝗣𝗲𝗿𝗹 𝗮𝗿𝗲 𝘁𝗵𝗲 𝗹𝗲𝗮𝘀𝘁 𝗲𝗻𝘃𝗶𝗿𝗼𝗻𝗺𝗲𝗻𝘁𝗮𝗹 𝗳𝗿𝗶𝗲𝗻𝗱𝗹𝘆 𝗽𝗿𝗼𝗴𝗿𝗮𝗺𝗺𝗶𝗻𝗴 𝗹𝗮𝗻𝗴𝘂𝗮𝗴𝗲
Artcile complet : https://medium.com/codex/what-are-the-greenest-programming-languages-e738774b1957
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) :
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)
Quelle misère ce portage sur une Fédora 14 :
# make … /usr/bin/ld: cannot find -lmysqlclient # ldconfig -v | grep "mysql" /usr/lib/mysql: libmysqlclient.so.16 -> libmysqlclient.so.16.0.0 libmysqlclient_r.so.16 -> libmysqlclient_r.so.16.0.0 # rpm -qa | grep mysql mysql-devel-5.1.58-1.fc14.i686 mysql-5.1.58-1.fc14.i686 mysql-libs-5.1.58-1.fc14.i686 # ld -lmysqlclient --verbose GNU ld version 2.20.51.0.7-5.fc14 20100318 Supported emulations: elf_i386 i386linux elf_x86_64 elf_l1om using internal linker script: ================================================== /* Script for -z combreloc: combine and sort reloc sections */ OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") OUTPUT_ARCH(i386) ENTRY(_start) SEARCH_DIR("/usr/i686-redhat-linux/lib"); SEARCH_DIR("/usr/local/lib"); SEARCH_DIR("/lib"); SEARCH_DIR("/usr/lib"); SECTIONS { /* Read-only sections, merged into text segment: */ PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x08048000)); . = SEGMENT_START("text-segment", 0x08048000) + SIZEOF_HEADERS; .interp : { *(.interp) } .note.gnu.build-id : { *(.note.gnu.build-id) } .hash : { *(.hash) } .gnu.hash : { *(.gnu.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .gnu.version : { *(.gnu.version) } .gnu.version_d : { *(.gnu.version_d) } .gnu.version_r : { *(.gnu.version_r) } .rel.dyn : { *(.rel.init) *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) *(.rel.fini) *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) *(.rel.data.rel.ro* .rel.gnu.linkonce.d.rel.ro.*) *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) *(.rel.ctors) *(.rel.dtors) *(.rel.got) *(.rel.sharable_data .rel.sharable_data.* .rel.gnu.linkonce.shrd.*) *(.rel.sharable_bss .rel.sharable_bss.* .rel.gnu.linkonce.shrb.*) *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) *(.rel.ifunc) } .rel.plt : { *(.rel.plt) PROVIDE_HIDDEN (__rel_iplt_start = .); *(.rel.iplt) PROVIDE_HIDDEN (__rel_iplt_end = .); } .init : { KEEP (*(.init)) } =0x90909090 .plt : { *(.plt) *(.iplt) } .text : { *(.text.unlikely .text.*_unlikely) *(.text .stub .text.* .gnu.linkonce.t.*) /* .gnu.warning sections are handled specially by elf32.em. */ *(.gnu.warning) } =0x90909090 .fini : { KEEP (*(.fini)) } =0x90909090 PROVIDE (__etext = .); PROVIDE (_etext = .); PROVIDE (etext = .); .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } .eh_frame_hdr : { *(.eh_frame_hdr) } .eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) } .gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) } /* Adjust the address for the data segment. We want to adjust up to the same address within the page on the next page up. */ . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE)); /* Exception handling */ .eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) } .gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) } /* Thread Local Storage sections */ .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } .preinit_array : { PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array)) PROVIDE_HIDDEN (__preinit_array_end = .); } .init_array : { PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) PROVIDE_HIDDEN (__init_array_end = .); } .fini_array : { PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT(.fini_array.*))) KEEP (*(.fini_array)) PROVIDE_HIDDEN (__fini_array_end = .); } .ctors : { /* gcc uses crtbegin.o to find the start of the constructors, so we make sure it is first. Because this is a wildcard, it doesn't matter if the user does not actually link against crtbegin.o; the linker won't look for a file to match a wildcard. The wildcard also means that it doesn't matter which directory crtbegin.o is in. */ KEEP (*crtbegin.o(.ctors)) KEEP (*crtbegin?.o(.ctors)) /* We don't want to include the .ctor section from the crtend.o file until after the sorted ctors. The .ctor section from the crtend file contains the end of ctors marker and it must be last */ KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors)) KEEP (*(SORT(.ctors.*))) KEEP (*(.ctors)) } .dtors : { KEEP (*crtbegin.o(.dtors)) KEEP (*crtbegin?.o(.dtors)) KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors)) KEEP (*(SORT(.dtors.*))) KEEP (*(.dtors)) } .jcr : { KEEP (*(.jcr)) } .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } .dynamic : { *(.dynamic) } .got : { *(.got) *(.igot) } . = DATA_SEGMENT_RELRO_END (12, .); .got.plt : { *(.got.plt) *(.igot.plt) } .data : { *(.data .data.* .gnu.linkonce.d.*) SORT(CONSTRUCTORS) } .data1 : { *(.data1) } /* Sharable data sections. */ .sharable_data : ALIGN(CONSTANT (MAXPAGESIZE)) { PROVIDE_HIDDEN (__sharable_data_start = .); *(.sharable_data .sharable_data.* .gnu.linkonce.shrd.*) /* Align here to ensure that the sharable data section ends at the page boundary. */ . = ALIGN(. != 0 ? CONSTANT (MAXPAGESIZE) : 1); PROVIDE_HIDDEN (__sharable_data_end = .); } _edata = .; PROVIDE (edata = .); __bss_start = .; .bss : { *(.dynbss) *(.bss .bss.* .gnu.linkonce.b.*) *(COMMON) /* Align here to ensure that the .bss section occupies space up to _end. Align after .bss to ensure correct alignment even if the .bss section disappears because there are no input sections. FIXME: Why do we need it? When there is no .bss section, we don't pad the .data section. */ . = ALIGN(. != 0 ? 32 / 8 : 1); } /* Sharable bss sections */ .sharable_bss : ALIGN(CONSTANT (MAXPAGESIZE)) { PROVIDE_HIDDEN (__sharable_bss_start = .); *(.dynsharablebss) *(.sharable_bss .sharable_bss.* .gnu.linkonce.shrb.*) *(SHARABLE_COMMON) /* Align here to ensure that the sharable bss section ends at the page boundary. */ . = ALIGN(. != 0 ? CONSTANT (MAXPAGESIZE) : 1); PROVIDE_HIDDEN (__sharable_bss_end = .); } . = ALIGN(32 / 8); . = ALIGN(32 / 8); _end = .; PROVIDE (end = .); . = DATA_SEGMENT_END (.); /* Stabs debugging sections. */ .stab 0 : { *(.stab) } .stabstr 0 : { *(.stabstr) } .stab.excl 0 : { *(.stab.excl) } .stab.exclstr 0 : { *(.stab.exclstr) } .stab.index 0 : { *(.stab.index) } .stab.indexstr 0 : { *(.stab.indexstr) } .comment 0 : { *(.comment) } /* DWARF debug sections. Symbols in the DWARF debugging sections are relative to the beginning of the section so we begin them at 0. */ /* DWARF 1 */ .debug 0 : { *(.debug) } .line 0 : { *(.line) } /* GNU DWARF 1 extensions */ .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } /* DWARF 1.1 and DWARF 2 */ .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } /* DWARF 2 */ .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } /* SGI/MIPS DWARF 2 extensions */ .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } /* DWARF 3 */ .debug_pubtypes 0 : { *(.debug_pubtypes) } .debug_ranges 0 : { *(.debug_ranges) } .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) } /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) } } ================================================== attempt to open /usr/i686-redhat-linux/lib/libmysqlclient.so failed attempt to open /usr/i686-redhat-linux/lib/libmysqlclient.a failed attempt to open /usr/local/lib/libmysqlclient.so failed attempt to open /usr/local/lib/libmysqlclient.a failed attempt to open /lib/libmysqlclient.so failed attempt to open /lib/libmysqlclient.a failed attempt to open /usr/lib/libmysqlclient.so failed attempt to open /usr/lib/libmysqlclient.a failed # locate /libmysqlclient.so /usr/lib/mysql/libmysqlclient.so /usr/lib/mysql/libmysqlclient.so.16 /usr/lib/mysql/libmysqlclient.so.16.0.0 # ln -s /usr/lib/mysql/libmysqlclient.so /lib/libmysqlclient.so # make : undefined reference to `mysql_connect'
Ensuite il a fallu changer les fonctions mysql_connect par mysql_real_connect :
mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned long client_flag);
Il faut retenir que le ‘ld’ permet de voir où doivent être les librairies.
Frédéric.