Sdílená a mapovaná paměť Dočasné soubory Závěr Práce s pamětí Tématicky zaměřený vývoj aplikací v jazyce C skupina Systémové programování – Linux Jiří Novosad Fakulta informatiky Masarykova univerzita novosad@fi.muni.cz Brno, 24. 12. 2014 J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 1 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Hrátky s pamětí Sdílená a mapovaná paměť J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 2 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Sdílená paměť jeden ze základních konceptů meziprocesové komunikace dva a více procesů sdílejí tutéž oblast v paměti velikost sdílené paměti je vždy násobkem velikosti stránky v systému (viz man 3 sysconf a _SC_PAGESIZE) nejrychlejší způsob komunikace (nevstupuje se do kernel-space, nekopírují se žádná data) je ale třeba důsledně řídit přístup k paměti! J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 3 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Sdílená paměť jeden ze základních konceptů meziprocesové komunikace dva a více procesů sdílejí tutéž oblast v paměti velikost sdílené paměti je vždy násobkem velikosti stránky v systému (viz man 3 sysconf a _SC_PAGESIZE) nejrychlejší způsob komunikace (nevstupuje se do kernel-space, nekopírují se žádná data) je ale třeba důsledně řídit přístup k paměti! Princip fungování 1 jeden z procesů alokuje segment paměťi požadované velikosti pro konkrétní klíč 2 ostatní procesy se k alokovanému segmentu připojují – musí znát identifikátor segmentu, který získají buď předáním ID nebo pomocí klíče a shmget() 3 po skončení práce se všechny procesy odpojí od alokovaného segmentu 4 jeden z procesů paměť nakonec dealokuje J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 3 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Sdílená paměť – vytvoření / získání segmentu #include #include #include int shmget(key_t key, size_t size, int shmflg); key_t ftok(const char *pathname, int proj_id); key – identifikátor segmentu, IPC_PRIVATE vytvoří nový segment shmflg – IPC_CREAT, IPC_EXCL, přístupová práva pathname – cesta k existujícímu souboru proj_id – 1 – 255 J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 4 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Sdílená paměť – použití segmentu #include #include #include void *shmat(int shmid, const void *shmaddr, int shmflg); int shmdt(const void *shmaddr); int shmctl(int shmid, int cmd, struct shmid_ds *buf); shmflg – SHM_RND, SHM_RDONLY cmd – IPC_STAT, IPC_RMID (exit nechává paměť alokovanou!), IPC_SET, . . . Ladění pomocí příkazu ipcs -m, odstranění příkazem ipcrm. J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 5 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Sdílená paměť – ukázka /* prepare key */ key_t shmkey = ftok("./somefile", 1); /* get a piece of memory */ size_t page_size = sysconf(_SC_PAGESIZE); int shmid = shmget(shmkey, page_size, IPC_CREAT | S_IRUSR | S_IWUSR); /* attach to the process address space */ void *shared_memory = shmat(shmid, NULL, 0); /* do the job */ /* declare memory to be destroyed */ if (shmctl(shmid, IPC_STAT, &shm) == -1 || shmctl(shmid, IPC_RMID, &shm) == -1) { perror("shmctl FAILURE"); } /* detach the memory */ shmdt(shared_memory); J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 6 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr úkol Program uloží do sdílené paměti řetězec (parametr programu), který následně každou sekundu v cyklu vypisuje Při spuštění další instance programu začnou všechny předchozí instance vypisovat nový řetězec J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 7 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Mapovaná paměť opět jeden z nástrojů meziprocesové komunikace dva a více procesů komunikují pomocí sdíleného souboru (paměťový segment se jménem) druhým (častějším) použitím je urychlení práce se souborem (se souborem budeme pracovat jako s pamětí) Linux vytvoří asociaci mezi souborem a pamětí a obsah souboru namapuje do stránek v paměti Rozpadá se konzistence mezi namapovaným souborem a skutečným souborem na disku J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 8 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Mapovaná paměť #include void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); int munmap(void *addr, size_t length); prot – PROT_READ, PROT_WRITE, PROT_EXEC, PROT_NONE flags – MAP_LOCKED, MAP_PRIVATE, MAP_SHARED, MAP_ANONYMOUS offset – násobek sysconf(_SC_PAGE_SIZE) #include int msync(void *addr, size_t length, int flags); flags – MS_ASYNC, MS_SYNC, MS_INVALIDATE J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 9 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Mapovaná paměť – ukázka opening file if ((fd = open("./mapped_file", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) == -1) { perror("open failed"); } map the file into the memory mm_addr = (char *)mmap(NULL, length, PROT_WRITE, MAP_SHARED, fd, 0); if (mm_addr == MAP_FAILED) { perror("mmap failed"); } J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 10 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Mapovaná paměť – ukázka opening file if ((fd = open("./mapped_file", O_CREAT | O_RDWR, S_IRUSR | S_IWUSR)) == -1) { perror("open failed"); } getting space in the file ftruncate(fd, length); map the file into the memory mm_addr = (char *)mmap(NULL, length, PROT_WRITE, MAP_SHARED, fd, 0); if (mm_addr == MAP_FAILED) { perror("mmap failed"); } J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 10 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr úkol reimplementujte předchozí úkol pomocí mapované paměti J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 11 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr úkol reimplementujte předchozí úkol pomocí mapované paměti přidejte synchronizaci procesů, například pomocí čtecích/zápisových zámků souborů J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 11 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Přístupová práva k paměti Změna práv nastavených pomocí parametru prot funkce mmap #include int mprotect(const void *addr, size_t len, int prot); J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 12 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Uzamykání stránek ve fyzické paměti #include int mlock(const void *addr, size_t len); int munlock(const void *addr, size_t len); int mlockall(int flags); int munlockall(void); zabránění přesunu dat z RAM do SWAPu uzamykají se pouze celé stránky zamykat může proces do velikosti RLIMIT_MEMLOCK, s právy superuživatele neomezeně požadavek na nízkou latenci (RT) požadavek na bezpečnost J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 13 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Vytváření dočasných souborů J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 14 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Vytváření dočasných souborů #include int mkstemp(char *template); char *mkdtemp(char *template); int mkostemp(char *template, int flags); int mkstemps(char *template, int suffixlen); int mkostemps(char *template, int suffixlen, int flags); FILE *tmpfile(void); bezpečné vytváření dočasných souborů (adresářů) – řešení problému souběhu template je modifikován, takže nesmí jít o konstantní řetězec formát template je ’jmenoXXXXXX’ nepoužívat: mktemp(3), tempnam(3), tmpnam(3) J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 15 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Závěr shrnutí, domácí úkoly a zdroje J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 16 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Domácí úkol Dokončete úlohy ze cvičení J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 17 / 18 Sdílená a mapovaná paměť Dočasné soubory Závěr Zdroje beej.us/guide/bgipc/output/html/multipage/mmap.html www.cs.cf.ac.uk/Dave/C/node27.html www.tldp.org/HOWTO/Secure-Programs-HOWTO/avoid-race.html J. Novosad 9 – Práce s pamětí Brno, 24. 12. 2014 18 / 18