Linux, jádro, GNU libc, atd. Open Source Programování http://rtime.felk.cvut.cz/osp/ Pavel Píša <pisa@fel.cvut.cz> http://cmp.felk.cvut.cz/~pisa Michal Sojka František Vacek DCE FEL ČVUT Copyright 2004 2010, Pavel Píša, Michal Sojka, František Vacek, Free Electrons.com, GNU.org, kernel.org, Wikipedia.org Creative Commons BY SA 3.0 license Latest update: 24. IV 2013 1
A jak to bylo dál Unics 1969 1971 to 1973 1974 to 1975 Unix TSS5 to 6 1978 BSD 1.0 to 2.0 1979 Unix TSS7 BSD 3.0 to 4.1 Xenix 1.0 to 2.3 BSD4.2 BSD4.3 Linux Minix1.x Linux Unix TSS (Time Sharing BSD 4.3 Tahoe System) 9 to 10 BSD 4.3 Reno BSD NET/2 NEXT STEP/ OPEN STEP 1.0 to 4.0 System VR1 to R2 SCO Xenix BSD Net BSD0.8 to 1.0 4.4 to 4.4 lite 2 OpenBSD Net BSD1.1 to 1.2 1.0 to 2.2 Net BSD1.3 Linux Mac OS X Server Mac OS X 10.0 to 10.5 SCO XenixW286 System VR3 SCO XenixV386 System VR4 SCO XenixW386 HP/UX1.0 to 1.2 HP/UX2.0 to 3.0 Sun OS4 Free BSD3.0 to 3.2 1999 2000 2001 to 2004 2005 Minix3.x 2006 to 2008 AIX1.0 386BSD Free BSD 1.0 to 2.2.x Minix2.x Sun OS 1.2 to 3.0 System III Xenix3.0 Sun OS 1 to 1.1 Unix TSS8 1993 1994 1995 1996 1997 1998 PWB/Unix Unix 32v 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 Open Source Mixed/Shared Closed Source Unix TSS 1 to 4 Free BSD 3.3 to 7.0 Net BSD 1.3 to 4.x OpenBSD 2.3 to 4.x HP/UX 6 to 11 SCO Unix 3.2.4 AIX3.x to 6.x Unixware 1.x to 2.x Open Server Solaris2.1 Solaristo 10 5.0 to 5.0.4 2.1 to 10 Open Server 5.0.5 to 5.0.7 Unixware 7.x OpenServer 6.0 Open Solaris 2008.05 HP/UX 11i to 11i v3 2
Unix hlavní větve 1970 1980 1990 2000 FreeBSD BSD family OpenBSD BSD (Berkeley Software Distribution) NetBSD Bill Joy Bill Joy SunOS (Stanford University Network) NextStep Bell Labs (AT&T) Time GNU Richard Stallman MacOS X GNU / Linux Linus Torvalds Ken Thompson Dennis Ritchie (C language created to implement a portable OS) IRIX (SGI) SRV5 Ritchie, Thompson System V family HP UX Sun Solaris AIX (IBM) 3
Linux kernel Trocha historie 5.1. 1991 Linus Torvalds kupuje IBM PC V srpnu 1991 Linus informace o záměru napsat jádro 1991 verze 0.01 publikována na internetu 1994 verze 1.0 jeden i386 CPU 1996 verze 2.0 SMP pro aplikace, BKL pro jádro 1999 verze 2.2 spinlock, m68k a PowerPC 2001 verze 2.4 ISA PnP, USB, PC Cards, PA RISC, později Bluetooth, LVM, RAID, ext3 2003 verze 2.6 mainline µclinux, ARM a další, PAE, ALSA, preemption, Native POSIX Thread Library, Futex, později FUSE, JFS, XFS, ext4, robust mutex, prio inherit mutex, high resolution timers Okolo 2007 CONFIG_PREEMPT_RT, spinlock RT mutex, rušení BKL, IRQ thready, preemptible RCU 4
GNU/Linux od trpaslíků 5
po superpočítače IBM Roadrunner, Los Alamos National Laboratory Majitel: National Nuclear Security Administration, USA LINPACK/BLAS (Basic Linear Algebra Subprograms) systém Architectura: 12,960 IBM PowerXCell 8i CPUs, 6,480 AMD Opteron dual core processors, Infiniband, Linux Systém: Red Hat Enterprise Linux a Fedora Napájení: 2.35 MW Velikost: 296 stojanů 560 m2 Pamět: 103.6 TiB Výkon 1.042 petaflops Cena: USD $125M SGI SSI (single system image) Linux, 2048 Itanium CPU a 4TiB RAM 6
Top 500 Supercomputers Podle operačního systému 100 mac na/mixed bsd unix windows linux 90 80 70 60 Podle CPU architektury 50 40 30 20 0 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 10 http://www.top500.org/ 7
A prognóza pro vestavné systémy Operating system used in the previous project Proprietary OS: 39% Free of cost embedded Linux: 29% Embedded Linux with commercial support: 11% Home grown OS: 7% No OS: 11% Operating system planned for the next project Free of cost embedded Linux: 71% Embedded Linux with commercial support: 16% Proprietary OS: 12% Home grown OS: 1% Source: Venture Development Corp, October 2007 http://www.vdc corp.com/_documents/pressrelease/press attachment 1394.pdf 8
Architektura (unixových) systémů Graphical user applications Web browser, office, multimedia... Command line applications ls, mkdir, wget, ssh, gcc, busybox, shells (scripts)... User space Shared libraries libjpeg, libstdc++, libxml... C library GNU C library, uclibc... Operating system kernel Linux, Hurd... Hardware and peripherals Kernel Space Hardware Převzato z http://free electrons.com/docs/freesw (Michael Opdenacker) 9
Spodní vrstvy operačního systému App1 App2... User space C library System call interface Process management Memory management Filesystem support Device control Networking Character device drivers Network device drivers Filesystem types CPU support code CPU / MMU support code Storage drivers Kernel space Hardware CPU RAM Storage 10
Skutečné programování Mějme jednoduchý požadavek alokovat a uvolňovat unikátní čísla (např. PID) v určitém rozsahu (alloc_pid) int pid_used[max_pid]; int alloc_pid(void) { static int pid = 1; for(i = 1; i<max_pid; i++) { if (!pid_used[pid]) { pid_used[i] = 1; return i; else { pid = pid<max_pid 1?pid+1:1; Return 0; Na jednom CPU to jde, ale co cache na 2048 SSI (MSI, MOSI, MOESI si vzalo veškerý výkon) Kód asi není dobře Chybí SMP, přidáme zámky Ó to je pomalé Zkusíme atomické operace a bitové pole while (1) { if (!test_and_set_bit(...)) { atomic_dec(&nr_free); return pid; 11
Tak jak to stím PIDem je Ve skutečnosti je to mnohem složitější Protože jádro podporuje i jmenné prostory (lehká virtualizace), potřebujeme celý řetěz PIDů pro každý name space Nemůžeme použít statické pole, max user processes je jen administrátorem nastavitelná konstanta (ulimit u / a) Max 4 millióny PID na 64 bit arch., horní bity pro robust futex na 32 bit max 32 tisíc, CONFIG_BASE_SMALL 8 tisíc Vše tedy musí být dynamické, nelze zabrat tolik paměti zbytečně, zároveň použití PID jako jednoznačného ID je v jádře díky NS nemožné Řešení: struct pid zároveň slouží jako reference na a pro struct task_struct, uživatel vidí pid_t PIDMAP_ENTRIES ((PID_MAX_LIMIT+8*PAGE_SIZE 1)/PAGE_SIZE/8) Ukázka make cscope, kscope a make htmldocs 12
Jak na mutex, vezmi futex FUTEX fast userspace mutex Pro shared převod na vma+index+offs mezi procesy (get_futex_key) Základ pro pthread_mutex_init, _lock, _trylock, _unlock, _destroy Ale i sem_post, sem_wait a veškeré pthread_cond FUTEX_ + WAIT static inline int + WAKE usema_down(ulock_t *ulock) { + FD if (! ulock_down(ulock)) + REQUEUE return 0; + CMP_REQUEUE return sys_ulock_wait(ulock); + WAKE_OP + LOCK_PI static inline int + UNLOCK_PI usema_up(ulock_t *ulock) + TRYLOCK_PI { if (! ulock_up(ulock)) + WAIT_BITSET return 0; + WAKE_BITSET return sys_ulock_wakeup(ulock); + WAIT_REQUEUE_PI + CMP_REQUEUE_PI 13
Pospora v GLIBC Robust FUTEX od 2.6.17 (release 2006) Priority inheritance pro uživatelské procesy od 2.6.18 (2006) pthread_mutexattr_setprotocol (..., PTHREAD_PRIO_INHERIT) glibc/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h Ulrich Drepper: Futexes Are Tricky, Red Hat, Inc. 2011 http://people.redhat.com/drepper/futex.pdf Lightweight PI futexes http://lxr.linux.no/source/documentation/pi futex.txt Ingo Molnar a další: Robust Futex http://lxr.linux.no/source/documentation/robust futexes.txt MSDN Windows 8, Windows Server 2012 WaitOnAddress, WakeByAddressSingle, WakeByAddressAll Windows 8 / 2012 Server (žádné PI, robustness, requeue, chování na SHM nespecifikované) 14
První pokus o futex class mutex { public: mutex () : val (0) { void lock () { int c; while ((c = atomic_inc (val))!= 0) futex_wait (&val, c + 1); void unlock () { val = 0; futex_wake (&val, 1); private: int val; ; Špatně: livelocks caused by the unconditional change of the futex variable must be avoided the futex value must not overflow in case it is known no threads wait on the mutex the futex wake call should be avoided. 15
Druhý pokus o futex class mutex2 { public: mutex () : val (0) { void lock () { int c; if ((c = cmpxchg (val, 0, 1))!= 0) do { if (c == 2 cmpxchg (val, 1, 2)!= 0) futex_wait (&val, 2); while ((c = cmpxchg (val, 0, 2))!= 0); void unlock () { if (atomic_dec (val)!= 1) { val = 0; futex_wake (&val, 1); private: int val; ; Cena bez kolize Cena při kolizi 16
Finální řešení obyčejného futexu class mutex3 { public: mutex () : val (0) { void lock () { int c; if ((c = cmpxchg (val, 0, 1))!= 0) { if (c!= 2) c = xchg (val, 2); while (c!= 0) { futex_wait (&val, 2); c = xchg (val, 2); void unlock () { if (atomic_dec (val)!= 1) { val = 0; futex_wake (&val, 1); private: int val; ; Cena při kolizi 17
Pokračování o driverech a jádře Ulrich Drepper: Futexes are Tricky http://people.redhat.com/drepper/futex.pdf Embedded Linux driver development http://free electrons.com/docs/kernel 18