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

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

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

Gniazda. S. Samolej: Gniazda 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:

Gniazda BSD. komunikacja bezpołączeniowa

4.2 Sposób korzystania z l acza

Obsługa plików Procesy

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

Systemy Operacyjne - Operacje na plikach

Sieciowa komunikacja procesów - XDR i RPC

Iteracyjny serwer TCP i aplikacja UDP

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

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

Programowanie sieciowe

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

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

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

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

Pobieranie argumentów wiersza polecenia

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

SUMA KONTROLNA (icmp_cksum) NUMER KOLEJNY (icmp_seq)

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),

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

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

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

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

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

PROGRAMOWANIE SYSTEMÓW CZASU RZECZYWISTEGO

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

Funkcje zawarte w bibliotece < io.h >

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

1. Kolejki komunikatów POSIX

Podstawy programowania w języku C++

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

13. Kolejki komunikatów POSIX

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

Uzupełnienie dot. przekazywania argumentów

eć dzielona standardu POSIX

Unix: programowanie z użyciem w atków

Unix: programowanie z użyciem w atków

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

Komunikacja mi edzyprocesowa (IPC)

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

Ghost in the machine

1. Kolejki komunikatów POSIX

Programowanie Proceduralne

Komunikacja międzyprocesowa. Krzysztof Banaś Systemy rozproszone 1

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

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

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

Łącza nienazwane(potoki)

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

Wykład 1

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

Komunikacja międzyprocesowa. Krzysztof Banaś Systemy rozproszone 1

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.

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

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

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

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

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

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

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

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

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,

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

Wstęp do programowania 1

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

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

Podział programu na moduły

Programowanie przy użyciu gniazdek

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

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

Gniazda UDP. Bartłomiej Świercz. Łódź, 3 kwietnia Katedra Mikroelektroniki i Technik Informatycznych. Bartłomiej Świercz Gniazda UDP

Programowanie Sieciowe 1

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

Katedra Elektrotechniki Teoretycznej i Informatyki. wykład 12 - sem.iii. M. Czyżak

Ćwiczenie 4. Obsługa plików. Laboratorium Podstaw Informatyki. Kierunek Elektrotechnika. Laboratorium Podstaw Informatyki Strona 1.

Sockety TCP/IP - podstawy. Sieci Komputerowe II Wyk ład 2

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. 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. 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. 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 jadro (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/types.h> #include <sys/time.h> #include <stdio.h> #include <fcntl.h> #include <sys/ioctl.h> #include <unistd.h> int main() { 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); #include <sys/types.h> #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 main() { 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); 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"); exit(0); nread = read(0,buffer,nread); buffer[nread] = 0; printf("read %d from keyboard: %s", nread, buffer); break; 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 #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> /* mmap() */ #include <fcntl.h> Odwzorowanie pamieci przyk lady #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 (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"); 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. 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 */ exit(0); 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.

typedef struct { int integer; char string[12]; RECORD; #define NRECORDS (100) int main() { RECORD record, *mapped; int i, f; FILE *fp; 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 <sys/types.h> #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 (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; 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); exit(0); 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);

#include <sys/types.h> #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 */