Zaawansowane operacje wejścia/wyjścia

Podobne dokumenty
Zaawansowane operacje wejścia/wyjścia

Zaawansowane operacje wejścia/wyjścia

Zaawansowane operacje wejścia/wyjścia

Zwielokrotnianie wejścia wyjścia

Obsługa plików. Systemy Operacyjne 2 laboratorium. Mateusz Hołenko. 25 września 2011

Gniazda. S. Samolej: Gniazda 1

J. Ułasiewicz Łącza nienazwane, nazwane, select 1

4. Komunikacja pomiędzy procesami przez łącza nienazwane i nazwane

J. Ułasiewicz Łącza nienazwane, nazwane, select 1

Laboratorium Systemów Operacyjnych. Ćwiczenie 4. Operacje na plikach

Funkcje systemu Unix

Krótkie wprowadzenie do korzystania z OpenSSL

TCP - receive buffer (queue), send buffer (queue)

Pliki. Funkcje tworzące pliki i operujące na nich opisane są w części 2 pomocy systemowej. Tworzenie i otwieranie plików:

Obsługa plików Procesy

4.2 Sposób korzystania z l acza

Gniazda BSD. komunikacja bezpołączeniowa

Temat zajęć: Obsługa systemu plików.

Systemy Operacyjne - Operacje na plikach

Iteracyjny serwer TCP i aplikacja UDP

Programowanie sieciowe

J. Ułasiewicz Programowanie aplikacji współbieżnych 1

Sieciowa komunikacja procesów - XDR i RPC

Laboratorium z systemów operacyjnych. System plików - funkcje systemowe. Anna Wojak

3. Identyfikacja. SKŁADNIA #include <sys/socket.h> int getpeername(int socket, struct sockaddr *addr, int *addrlen);

SUMA KONTROLNA (icmp_cksum) NUMER KOLEJNY (icmp_seq)

Rys. 9-1 Procesy P1 i P2 komunikuję się poprzez wspólny obszar. pamięci.

Literatura uzupełniająca: W. Richard Stevens, Programowanie zastosowań sieciowych w systemie Unix WNT 1998

J. Ułasiewicz Programowanie aplikacji współbieżnych 1

Pobieranie argumentów wiersza polecenia

Łącza nienazwane(potoki) Łącza nienazwane mogą być używane tylko pomiędzy procesami ze sobą powiązanymi.

Kolejki komunikatów POSIX

Przykład aplikacji UDP

sposób wykonywania operacji zapisu i odczytu dane odczytywane z l acza usuwane (nie można ich odczytać ponownie),

Programowanie aplikacji równoległych i rozproszonych. Wykład 4

7. Sterowanie współbieżnością

1. Kolejki komunikatów POSIX

Programowanie proceduralne INP001210WL rok akademicki 2015/16 semestr letni. Wykład 6. Karol Tarnowski A-1 p.

Funkcje zawarte w bibliotece < io.h >

Gniazda - Wstęp. Oprogramowanie systemów równoległych i rozproszonych. Sposób komunikacji. Domena adresowa. olas@icis.pcz.pl

13. Kolejki komunikatów POSIX

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

Funkcje zawarte w bibliotece < io.h >

Zdalne wywołania procedur. Jarosław Kuchta Programowanie Współbieżne

1.1 Przykład znajdowanie liczb pierwszych leżących w zadanym zakresie, tryb bezpołączeniowy

Shared memory and messages. Functions. process 0. process 1. program 0. program 0. data 0. data 1. program 1. data 0. data 1.

Podstawy programowania w języku C++

eć dzielona standardu POSIX

Pliki w C/C++ Przykłady na podstawie materiałów dr T. Jeleniewskiego

1. Kolejki komunikatów POSIX

Wykład 15. Literatura. Kompilatory. Elementarne różnice. Preprocesor. Słowa kluczowe

Functionalization. Jeszcze o funkcjach i strukturze projektu. Marcin Makowski. 3 grudnia Zak lad Chemii Teoretycznej UJ

Uzupełnienie dot. przekazywania argumentów

Architektura typu klient serwer: przesyłanie pliku tekstowo oraz logowania do serwera za pomocą szyfrowanego hasła

Komunikacja międzyprocesowa. Krzysztof Banaś Systemy rozproszone 1

Unix: programowanie z użyciem w atków

Unix: programowanie z użyciem w atków

Komunikacja mi edzyprocesowa (IPC)

Ghost in the machine

J. Ułasiewicz Programowanie aplikacji współbieżnych 1

Programowanie Proceduralne

Języki programowania. Przetwarzanie plików amorficznych Konwencja języka C. Część siódma. Autorzy Tomasz Xięski Roman Simiński

ISO/ANSI C - funkcje. Funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje. ISO/ANSI C - funkcje

Pliki. Informacje ogólne. Obsługa plików w języku C

Komunikacja sieciowa - interfejs gniazd

Semafory, pamięć dzielona i kolejki komunikatów

10. Synchronizacja użycia zasobów, Semafory Problem producenta i konsumenta

Języki i metodyka programowania. Typy, operatory, wyrażenia. Wejście i wyjście.

Łącza nienazwane(potoki)

ISO/ANSI C dostęp do plików ISO/ANSI C. ISO/ANSI C dostęp do plików. ISO/ANSI C dostęp do plików. ISO/ANSI C dostęp do plików

Wykład 1

Operacje wejścia/wyjścia (odsłona druga) - pliki

Temat zajęć: Obsługa łączy komunikacyjnych

Plik jest poj eciem, z którym spotyka si e niemal każdy użytkownik systemu komputerowego, nawet

5. Algorytmy serwera

pami eć operacyjna przechowuje dane do przetworzenia, tymczasowe dane pomocnicze,

dynamiczny przydział pamięci calloc() memset() memcpy( ) (wskaźniki!! )

Procesy. Systemy Operacyjne 2 laboratorium. Mateusz Hołenko. 9 października 2011

Komunikacja międzyprocesowa. Krzysztof Banaś Systemy rozproszone 1

Wstęp do programowania 1

1: ////////// 2: // test.c. 3: ssize_t ret = read(fd, buf, nbytes);

Podział programu na moduły

Paradygmaty programowania. Paradygmaty programowania

ISO/ANSI C dostęp do plików ISO/ANSI C. ISO/ANSI C dostęp do plików. ISO/ANSI C dostęp do plików. ISO/ANSI C dostęp do plików

Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1. Kraków 2013

wykład II uzupełnienie notatek: dr Jerzy Białkowski Programowanie C/C++ Język C - funkcje, tablice i wskaźniki wykład II dr Jarosław Mederski Spis

Pliki. Informacje ogólne. Obsługa plików w języku C

Podstawy informatyki. Informatyka stosowana - studia niestacjonarne. Grzegorz Smyk. Wydział Inżynierii Metali i Informatyki Przemysłowej

Wykład VI. Programowanie. dr inż. Janusz Słupik. Gliwice, Wydział Matematyki Stosowanej Politechniki Śląskiej. c Copyright 2014 Janusz Słupik

METODY I JĘZYKI PROGRAMOWANIA PROGRAMOWANIE STRUKTURALNE. Wykład 02

Programowanie Sieciowe 1

Funkcje. Piotr Zierhoffer. 7 października Institute of Computer Science Poznań University of Technology

Wykład 5_2 Algorytm ograniczania liczby serii za pomocą kopcowego rozdzielania serii początkowych

Podstawy programowania w języku C++

Podstawy programowania. Wykład Pętle. Tablice. Krzysztof Banaś Podstawy programowania 1

Programowanie przy użyciu gniazdek

Biblioteka standardowa - operacje wejścia/wyjścia

Co nie powinno być umieszczane w plikach nagłówkowych:

Serwer współbieżny połączeniowy

Programowanie sieciowe

Transkrypt:

Zaawansowane operacje wejścia/wyjścia Witold Paluszyński witold.paluszynski@pwr.edu.pl http://www.kcir.pwr.edu.pl/ witold/ Copyright c 2002 2003 Witold Paluszyński All rights reserved. Niniejszy dokument zawiera materia ly do wyk ladu na temat zaawansowanych operacji wejścia/wyjścia w systemie Unix. Jest on udostepniony pod warunkiem wykorzystania wy l acznie do w lasnych, prywatnych potrzeb i może być kopiowany wy lacznie w ca lości, razem z niniejsza strona tytu low a. Blokowanie operacji I/O Blokowanie operacji wejścia/wyjścia oznacza oczekiwanie na możliwość odczytania albo zapisania danych. Przyk lady blokowania wejścia/wyjścia: odczyt z plików urzadzeń, gdy nie ma w nich już danych (potoki, terminale, gniazdka), zapis do tych samych urzadzeń, jeśli dane nie moga być od razu przyjete, otwarcie pliku blokuje do momentu spe lnienia pewnych warunków (np. otwarcie pliku terminala do chwili nawiazania po laczenia przez modem, otwarcie FIFO do zapisu gdy żaden proces nie ma go otwartego do odczytu, itp.), operacje na plikach z mandatory record locking, i inne. Nieblokujace wejście/wyjście Blokowanie operacji I/O można kontrolować, to znaczy można tak skonfigurować operacje wejścia/wyjścia, by w sytuacji która normalnie spowodowa laby blokowanie, funkcja wróci la od razu z kodem wskazujacym niemożność wykonania operacji. open z flaga O_NONBLOCK fcntl na otwartym deskryptorze z ta sama flaga Wtedy powrót z funkcji read/write nastepuje z b ledem wskazujacym, że operacja by blokowa la. UWAGA: można zastosować stara flage O_NDELAY, wtedy funkcje read/write zwracaja 0, co jednak pokrywa sie z sygnalizacja EOF (System V). Równoczesne operacje I/O Jak zorganizować operacje wejścia/wyjścia, gdy mamy np. jednocześnie kilka źróde l, z których nadchodza dane? Na przyk lad, emulator terminala, komunikujacy sie z jednej strony z użytkownikiem, a z drugiej ze zdalnym systemem: Możliwe sa nastepuj ace rozwiazania: polling: nieblokujace próby odczytu na przemian z kolejnych deskryptorów; w niektórych systemach można też użyć na gniazdkach: ioctl(fd,fionread,&nread); prze laczanie (multiplexing): funkcje select i poll asynchroniczne I/O: powiadamianie procesu przez j adro (przy pomocy sygna lu) o gotowości deskryptora do operacji I/O

I/O multiplexing Ten mechanizm nie jest objety norma POSIX, jednak funkcja select() istnieje w Unixach AT&T i BSD od dawna i jest dość standardowa. Funkcja poll() jest nowa, i w niektórych systemach jest zaimplementowana przez select. struct timeval time_t tv_sec; /* seconds */ suseconds_t tv_usec; /* and microseconds */ ; int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *errorfds, struct timeval *timeout); Funkcja select() zwraca liczbe deskryptorów gotowych do operacji I/O. Po powrocie wynikajacym z up lyniecia zadanego czasu funkcja zeruje wszystkie zbiory deskryptorów w systemie V, lecz pozostawia je niezmienione w systemie BSD. Te systemy również inaczej licza deskryptory gotowe do I/O (AT&T liczy je w sensie mnogościowym, a BSD sumuje arytmetycznie liczności wszystkich trzech zbiorów deskryptorów). Ponadto, niektóre systemy w przypadku gotowości deskryptora ustawiaja w strukturze timeval czas pozosta ly do wyczerpania (Linux). Do tworzenia odpowiednich zbiorów deskryptorów, a także sprawdzania otrzymanych wyników, istnieja makra: void FD_SET(int fd, fd_set *fdset); void FD_CLR(int fd, fd_set *fdset); int FD_ISSET(int fd, fd_set *fdset); void FD_ZERO(fd_set *fdset); Funkcja poll zapewnia podobne dzia lanie lecz inny interface programisty: struct pollfd int fd; /* file descriptor */ short events; /* requested events */ short revents; /* returned events */ int poll(struct pollfd fds[], nfds_t nfds, int timeout); Tablica struktur pollfd określa wszystkie deskryptory i zdarzenia, na które chcemy oczekiwać (czas określany jest tu w milisekundach). Wartość zwracana z funkcji daje liczbe gotowych deskryptorów. #include <sys/time.h> #include <stdio.h> #include <fcntl.h> #include <sys/ioctl.h> #include <unistd.h> char buffer[128]; int result, nread; fd_set inputs, testfds; struct timeval timeout; FD_ZERO(&inputs); FD_SET(0,&inputs); while(1) testfds = inputs; timeout.tv_sec = 2; timeout.tv_usec = 500000; Funkcja select przyk lad result = select(fd_setsize, &testfds, (fd_set *)0, (fd_set *)0, &timeout); switch(result) case 0: printf("timeout\n"); break; case -1: perror("select"); exit(1); default: if (FD_ISSET(0,&testfds)) ioctl(0,fionread,&nread); if (nread == 0) printf("keyboard done\n"); nread = read(0,buffer,nread); buffer[nread] = 0; printf("read %d from keyboard: %s", nread, buffer); break; #include <sys/socket.h> #include <stdio.h> #include <netinet/in.h> #include <sys/time.h> #include <sys/ioctl.h> #include <unistd.h> Funkcja select inny przyk lad int server_sockfd, client_sockfd; int server_len, client_len; struct sockaddr_in server_address; int result; fd_set readfds, testfds; server_sockfd = socket(af_inet, SOCK_STREAM, 0); server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = htonl(inaddr_any); server_address.sin_port = htons(9734); server_len = sizeof(server_address); bind(server_sockfd, (struct sockaddr *)&server_address, server_len); listen(server_sockfd, 5); FD_ZERO(&readfds); FD_SET(server_sockfd, &readfds); while(1) char ch; int fd, nread; testfds = readfds; printf("server waiting\n"); result = select(fd_setsize, &testfds, (fd_set *)0, (fd_set *)0, (struct timeval *) 0); if(result < 1) perror("server5"); exit(1); for(fd = 0; fd < FD_SETSIZE; fd++) if(fd_isset(fd,&testfds)) if(fd == server_sockfd) client client_sockfd = accept(server_sockfd, 0, 0); FD_SET(client_sockfd, &readfds); printf("adding client on fd %d\n", client_sockfd);

else ioctl(fd, FIONREAD, &nread); if(nread == 0) close(fd); FD_CLR(fd, &readfds); printf("removing client on fd %d\n", fd); else read(fd, &ch, 1); sleep(5); printf("serving client on fd %d\n", fd); ch++; write(fd, &ch, 1); Asynchroniczne I/O Dla każdego deskryptora, dla którego chcemy oczekiwać na dane, należy ustawić powiadamianie przez jadro odpowiednim sygna lem. Ten mechanizm również nie jest jednak objety norma POSIX i jest troche inny w systemach AT&T i BSD. AT&T Mechanizm dzia la dla wszystkich urzadzeń opartych na systemie streams. Należy ustawić sygna l sigpoll dla deskryptora funkcja ioctl(fd,i_setsig,flags), gdzie argumentem flags określa sie jakie wydarzenie powinno spowodować wys lanie sygna lu. BSD Tu mamy do dyspozycji dwa sygna ly: sigio (dla zwyk lych operacji I/O), i sigurg (dla danych out-of-band z po l aczeń sieciowych). Należy ustawić proces lub grupe procesów, która ma otrzymać sygna l dla deskryptora (funkcja fcntl z komenda F_SETOWN), oraz ustawić flage O_ASYNC dla deskryptora (funkcja fcntl z komenda F_SETFL). W chwili otrzymania sygna lu nadal nie wiemy, który deskryptor jest gotów do wykonywania operacji I/O i musimy to i tak po kolei sprawdzać. Odwzorowanie plików do pamieci Użycie odwzorowania pliku do pamieci pozwala wykonywać operacje I/O na pliku przez manipulacje na pamieci. Zamiast przesuwać kursor pliku funkcja lseek, wystarczy obliczyć inny adres w pamieci. Odwzorowanie realizuje funkcja mmap. Poniższe wywo lanie powoduje odwzorowanie sekcji otwartego pliku fildes od pozycji off o d lugości len do obszaru pamieci od adresu addr. Adres ten może być określony jako 0, wtedy funkcja sama wybiera obszar pamieci i zwraca jego adres. pa = mmap(addr, len, prot, flags, fildes, off); Argument prot określa prawa dostepu do regionu pamieci i musi być zgodny z trybem otwarcia pliku. Argument flags określa różne atrybuty mapowanego regionu: MAP_SHARED operacje zapisu do pamieci powoduja zapis do pliku MAP_PRIVATE operacje zapisu do pamieci nie powoduja modyfikacji pliku tworzona jest robocza kopia pliku MAP_FIXED wymusza przydzia l adresu zadany argumentem (normalnie jest on tylko wskazówka dla jadra) MAP_FILE flaga wymagana w systemie BSD Operacje I/O na plikach odwzorowanych do pamieci Wykonywanie operacji I/O przez odwzorowana pamieć pozwala na wykorzystanie kana lów DMA, co daje duża szybkość operacji I/O i odciażenie g lównego procesora. Jeśli różne procesy odwzoruja ten sam plik do swoich przestrzeni adresowych, to uzyskuja dzieki temu obszar pamieci pozwalajacy na komunikacje miedzyprocesow a. Ze wzgledu na efektywność, system nie wykonuje natychmiast operacji I/O wynikajacych z zapisów do odwzorowanej pamieci. Można wymusić wykonanie tych operacji funkcja msync(). Synchronizacje można wywo lać w dowolna strone, tzn. zarówno zapis zawartości pamieci do pliku, jak i wczytanie zawartości pliku do pamieci. Zwyk le zamkniecie odwzorowanego pliku nie kasuje odwzorowania mmap, należy w tym celu wywo lać: res = munmap(addr, len); Skasowanie odwzorowania nie powoduje żadnych operacji I/O do pliku. Zapis do pliku w trybie MAP_SHARED odbywa sie na bieżaco w trakcie operacji na obszarze pamieci.

Odwzorowanie pamieci przyk lady #include <sys/stat.h> #include <sys/mman.h> /* mmap() */ #include <fcntl.h> #ifndef MAP_FILE /* 44BSD defines this & requires it to mmap files */ #define MAP_FILE 0 /* to compile under systems other than 44BSD */ #endif int main(int argc, char *argv[]) int fdin, fdout; char *src, *dst; struct stat statbuf; if ( (src = mmap(0, statbuf.st_size, PROT_READ, MAP_FILE MAP_SHARED, fdin, 0)) == (caddr_t) -1) err_sys("mmap error for input"); if ( (dst = mmap(0, statbuf.st_size, PROT_READ PROT_WRITE, MAP_FILE MAP_SHARED, fdout, 0)) == (caddr_t) -1) err_sys("mmap error for output"); memcpy(dst, src, statbuf.st_size); /* does the file copy */ if (argc!= 3) err_quit("usage: a.out <fromfile> <tofile>"); if ( (fdin = open(argv[1], O_RDONLY)) < 0) /*... */; if ( (fdout = open(argv[2], O_RDWR O_CREAT O_TRUNC, FILE_MODE)) < 0) /*... */; if (fstat(fdin, &statbuf) < 0) /* need size of input file */; if (lseek(fdout, statbuf.st_size - 1, SEEK_SET) == -1) err_sys("lseek error"); if (write(fdout, "", 1)!= 1) /* set size of output file */ err_sys("write error"); typedef struct int integer; char string[12]; RECORD; #define NRECORDS (100) RECORD record, *mapped; int i, f; FILE *fp; f = open("records.dat",o_rdwr); read(f,&record,sizeof(record)); mapped = (RECORD *)mmap(0, NRECORDS*sizeof(record), PROT_READ PROT_WRITE, MAP_SHARED, f, 0); mapped[43].integer = 243; sprintf(mapped[43].string,"record-%d",mapped[43].integer); msync((void *)mapped, NRECORDS*sizeof(record), MS_ASYNC); munmap((void *)mapped, NRECORDS*sizeof(record)); close(f); fp = fopen("records.dat","w+"); for(i=0; i<nrecords; i++) record.integer = i; sprintf(record.string,"record-%d",i); fwrite(&record,sizeof(record),1,fp); fclose(fp); fp = fopen("records.dat","r+"); fseek(fp,43*sizeof(record),seek_set); fread(&record,sizeof(record),1,fp); record.integer = 143; sprintf(record.string,"record-%d",record.integer); fseek(fp,43*sizeof(record),seek_set); fwrite(&record,sizeof(record),1,fp); fclose(fp); #include <stropts.h> Przekazywanie otwartych deskryptorów int send_fd(int clifd, int fd) char buf[2]; /* send_fd()/recv_fd() 2-byte protocol */ buf[0] = 0; /* null byte flag to recv_fd() */ if (fd < 0) buf[1] = -fd; /* nonzero status means error */ if (buf[1] == 0) buf[1] = 1; /* -256, etc. would screw up protocol */ else buf[1] = 0; /* zero status means OK */ if ( (n = strlen(msg)) > 0) if (writen(clifd, msg, n)!= n) /* send the error message */ if (errcode >= 0) errcode = -1; /* must be negative */ if (send_fd(clifd, errcode) < 0) return(0); if (write(clifd, buf, 2)!= 2) if (fd >= 0) if (ioctl(clifd, I_SENDFD, fd) < 0) return(0); int send_err(int clifd, int errcode, const char *msg) int n;

#include <stropts.h> int recv_fd(int servfd, ssize_t (*userfunc)(int, const void *, size_t)) int newfd, nread, flag, status = -1; char *ptr, buf[maxline]; struct strbuf dat; struct strrecvfd recvfd; for ( ; ; ) dat.buf = buf; dat.maxlen = MAXLINE; flag = 0; if (getmsg(servfd, NULL, &dat, &flag) < 0) err_sys("getmsg error"); nread = dat.len; if (nread == 0) err_ret("connection closed by server"); for (ptr = buf; ptr < &buf[nread]; ) if (*ptr++ == 0) if (ptr!= &buf[nread-1]) err_dump("message format error"); status = *ptr & 255; if (status == 0) if (ioctl(servfd, I_RECVFD, &recvfd) < 0) newfd = recvfd.fd; /* new descriptor */ else newfd = -status; nread -= 2; if (nread > 0) if ((*userfunc)(stderr_fileno, buf, nread)!= nread) if (status >= 0) /* final data has arrived */ return(newfd); /* descriptor, or -status */