• Nie Znaleziono Wyników

zapis do tych samych urządzeń, jeśli dane nie mogą być od razu przyjęte, zapisu gdy żaden proces nie ma go otwartego do odczytu, itp.

N/A
N/A
Protected

Academic year: 2022

Share "zapis do tych samych urządzeń, jeśli dane nie mogą być od razu przyjęte, zapisu gdy żaden proces nie ma go otwartego do odczytu, itp."

Copied!
7
0
0

Pełen tekst

(1)

Z a aw a n so w a n e o p e ra cj e w e ci a / w y ci a

WitoldPaluszyński witold.paluszynski@pwr.edu.pl http://www.kcir.pwr.edu.pl/ witold/ Copyrightc 2002–2003WitoldPaluszyński Allrightsreserved. Niniejszydokumentzawieramateriałydowykładunatematzaawansowanychoperacji wejścia/wyjściawsystemieUnix.Jestonudostępnionypodwarunkiemwykorzystania wyłączniedowłasnych,prywatnychpotrzebimożebyćkopiowanywyłączniewcałości, razemzniniejsząstronątytułową.

B lo k o w a n ie o p e ra cj i I/ O

Blokowanieoperacjiwejścia/wyjściaoznaczaoczekiwanienamożliwośćodczytania albozapisaniadanych.Przykładyblokowaniawejścia/wyjścia: •odczytzplikówurządzeń,gdyniemawnichjużdanych(potoki,terminale, gniazdka), •zapisdotychsamychurządzeń,jeślidaneniemogąbyćodrazuprzyjęte, •otwarcieplikublokujedomomentuspełnieniapewnychwarunków(np.otwarcie plikuterminaladochwilinawiązaniapołączeniaprzezmodem,otwarcieFIFOdo zapisugdyżadenprocesniemagootwartegodoodczytu,itp.), •operacjenaplikachzmandatoryrecordlocking, •iinne. Unix:zaawansowaneoperacjeI/O3

N ie b lo k u ce w e ci e / w yj śc ie

BlokowanieoperacjiI/Omożnakontrolować,toznaczymożnatakskonfigurować operacjewejścia/wyjścia,bywsytuacjiktóranormalniespowodowałabyblokowanie, funkcjawróciłaodrazuzkodemwskazującymniemożnośćwykonaniaoperacji. •openzflagąO_NONBLOCK •fcntlnaotwartymdeskryptorzeztąsamąflagą Wtedypowrótzfunkcjiread/writenastępujezbłędemwskazującym,żeoperacjaby blokowała. UWAGA:możnazastosowaćstarąflagęO_NDELAY,wtedyfunkcjeread/write zwracają0,cojednakpokrywasięzsygnalizacjąEOF(SystemV). Unix:zaawansowaneoperacjeI/O4

(2)

R ó w n o cz e sn e o p e ra cj e I/ O

Jakzorganizowaćoperacjewejścia/wyjścia,gdymamynp.jednocześniekilkaźródeł,z którychnadchodządane? Naprzykład,emulatorterminala,komunikującysięzjednejstronyzużytkownikiem,a zdrugiejzezdalnymsystemem: Możliwesąnastępującerozwiązania: •polling:nieblokującepróbyodczytunaprzemianzkolejnychdeskryptorów; wniektórychsystemachmożnateżużyćnagniazdkach: ioctl(fd,FIONREAD,&nread); •przełączanie(multiplexing):funkcjeselectipoll •asynchroniczneI/O:powiadamianieprocesuprzezjądro(przypomocysygnału)o gotowoścideskryptoradooperacjiI/O Unix:zaawansowaneoperacjeI/O5 Unix:zaawansowaneoperacjeI/O6

I/ O m u lt ip le xi n g

TenmechanizmniejestobjętynormąPOSIX,jednakfunkcjaselect()istnieje wUnixachAT&TiBSDoddawnaijestdośćstandardowa.Funkcjapoll()je nowa,iwniektórychsystemachjestzaimplementowanaprzezselect. structtimeval{ time_ttv_sec;/*seconds*/ suseconds_ttv_usec;/*andmicroseconds*/ }; intselect(intnfds,fd_set*readfds,fd_set*writefds, fd_set*errorfds,structtimeval*timeout); Funkcjaselect()zwracaliczbędeskryptorówgotowychdooperacjiI/O.Pop wynikającymzupłynięciazadanegoczasufunkcjazerujewszystkiezbiorydeskry wsystemieV,leczpozostawiajeniezmienionewsystemieBSD.Tesystemyró inaczejlicządeskryptorygotowedoI/O(AT&Tliczyjewsensiemnogościowym BSDsumujearytmetycznielicznościwszystkichtrzechzbiorówdeskryptorów). Ponadto,niektóresystemywprzypadkugotowoścideskryptoraustawiająwstru timevalczaspozostałydowyczerpania(Linux). Unix:zaawansowaneoperacjeI/O Dotworzeniaodpowiednichzbiorówdeskryptorów,atakżesprawdzaniaotrzym wyników,istniejąmakra: voidFD_SET(intfd,fd_set*fdset); voidFD_CLR(intfd,fd_set*fdset); intFD_ISSET(intfd,fd_set*fdset); voidFD_ZERO(fd_set*fdset); Funkcjapollzapewniapodobnedziałanieleczinnyinterfaceprogramisty: structpollfd{ intfd;/*filedescriptor*/ shortevents;/*requestedevents*/ shortrevents;/*returnedevents*/ } intpoll(structpollfdfds[],nfds_tnfds,inttimeout); Tablicastrukturpollfdokreślawszystkiedeskryptoryizdarzenia,naktórech oczekiwać(czasokreślanyjesttuwmilisekundach).Wartośćzwracanazfunkcj liczbęgotowychdeskryptorów. Unix:zaawansowaneoperacjeI/O

(3)

F u n k cj a s e l e c t p rz yk ła d

#include<sys/types.h> #include<sys/time.h> #include<stdio.h> #include<fcntl.h> #include<sys/ioctl.h> #include<unistd.h> intmain(){ charbuffer[128]; intresult,nread; fd_setinputs,testfds; structtimevaltimeout; FD_ZERO(&inputs); FD_SET(0,&inputs); while(1){ testfds=inputs; timeout.tv_sec=2; timeout.tv_usec=500000; result=select(FD_SETSIZE,&testfds,(fd_set*)0, (fd_set*)0,&timeout); Unix:zaawansowaneoperacjeI/O9 switch(result){ case0: printf("timeout\n"); break; case-1: perror("select"); exit(1); default: if(FD_ISSET(0,&testfds)){ ioctl(0,FIONREAD,&nread); if(nread==0){ printf("keyboarddone\n"); exit(0); } nread=read(0,buffer,nread); buffer[nread]=0; printf("read%dfromkeyboard:%s",nread,buffer); } break; } } } Unix:zaawansowaneoperacjeI/O10

F u n k cj a s e l e c t in n y p rz yk ła d

#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> intmain(){ intserver_sockfd,client_sockfd; intserver_len,client_len; structsockaddr_inserver_address; intresult; fd_setreadfds,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,(structsockaddr*)&server_address,server_len); listen(server_sockfd,5); Unix:zaawansowaneoperacjeI/O11 FD_ZERO(&readfds); FD_SET(server_sockfd,&readfds); while(1){ charch; intfd,nread; testfds=readfds; printf("serverwaiting\n"); result=select(FD_SETSIZE,&testfds,(fd_set*)0, (fd_set*)0,(structtimeval*)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("addingclientonfd%d\n",client_sockfd); } Unix:zaawansowaneoperacjeI/O12

(4)

else{ ioctl(fd,FIONREAD,&nread); if(nread==0){ close(fd); FD_CLR(fd,&readfds); printf("removingclientonfd%d\n",fd); } else{ read(fd,&ch,1); sleep(5); printf("servingclientonfd%d\n",fd); ch++; write(fd,&ch,1); } } } } } } Unix:zaawansowaneoperacjeI/O13 Unix:zaawansowaneoperacjeI/O14

A sy n ch ro n ic zn e I/ O

•Dlakażdegodeskryptora,dlaktóregochcemyoczekiwaćnadane,należyusta powiadamianieprzezjądroodpowiednimsygnałem.Tenmechanizmrównieżnie jednakobjętynormąPOSIXijesttrochęinnywsystemachAT&TiBSD. AT&TMechanizmdziaładlawszystkichurządzeńopartychnasystemie„strea Należyustawićsygnałsigpolldladeskryptorafunkcją ioctl(fd,I_SETSIG,flags),gdzieargumentemflagsokreślasięjakie wydarzeniepowinnospowodowaćwysłaniesygnału. BSDTumamydodyspozycjidwasygnały:sigio(dlazwykłychoperacjiI/O), sigurg(dladanychout-of-bandzpołączeńsieciowych).Należyustawićpr grupęprocesów,któramaotrzymaćsygnałdladeskryptora(funkcjafcntl zkomendąF_SETOWN),orazustawićflagęO_ASYNCdladeskryptora(funkcja fcntlzkomendąF_SETFL). •Wchwiliotrzymaniasygnałunadalniewiemy,którydeskryptorjestgotówdo wykonywaniaoperacjiI/Oimusimytoitakpokoleisprawdzać. Unix:zaawansowaneoperacjeI/O Unix:zaawansowaneoperacjeI/O

(5)

O d w zo ro w a n ie p li k ó w d o p a m ci

UżycieodwzorowaniaplikudopamięcipozwalawykonywaćoperacjeI/Onaplikuprzez manipulacjenapamięci.Zamiastprzesuwaćkursorplikufunkcjąlseek,wystarczy obliczyćinnyadreswpamięci.Odwzorowanierealizujefunkcjammap. Poniższewywołaniepowodujeodwzorowaniesekcjiotwartegoplikufildesodpozycji offodługościlendoobszarupamięciodadresuaddr.Adrestenmożebyćokreślony jako0,wtedyfunkcjasamawybieraobszarpamięciizwracajegoadres. pa=mmap(addr,len,prot,flags,fildes,off); Argumentprotokreślaprawadostępudoregionupamięciimusibyćzgodnyztrybem otwarciapliku. Argumentflagsokreślaróżneatrybutymapowanegoregionu: MAP_SHAREDoperacjezapisudopamięcipowodujązapisdopliku MAP_PRIVATEoperacjezapisudopamięciniepowodująmodyfikacjipliku— tworzonajestroboczakopiapliku MAP_FIXEDwymuszaprzydziaładresuzadanyargumentem(normalniejeston tylkowskazówkądlajądra) MAP_FILEflagawymaganawsystemieBSD Unix:zaawansowaneoperacjeI/O17

O p e ra cj e I/ O n a p li k a ch o d w zo ro w a n yc h d o p a m ci

WykonywanieoperacjiI/Oprzezodwzorowanąpamięćpozwalanawykorzystanie kanałówDMA,codajedużąszybkośćoperacjiI/Oiodciążeniegłównegoprocesora. Jeśliróżneprocesyodwzorujątensamplikdoswoichprzestrzeniadresowych,to uzyskujądziękitemuobszarpamięcipozwalającynakomunikacjęmiędzyprocesową. Zewzględunaefektywność,systemniewykonujenatychmiastoperacjiI/O wynikającychzzapisówdoodwzorowanejpamięci.Możnawymusićwykonanietych operacjifunkcjąmsync().Synchronizacjęmożnawywołaćwdowolnąstronę,tzn. zarównozapiszawartościpamięcidopliku,jakiwczytaniezawartościplikudopamięci. Zwykłezamknięcieodwzorowanegoplikuniekasujeodwzorowaniammap,należywtym celuwywołać: res=munmap(addr,len); SkasowanieodwzorowanianiepowodujeżadnychoperacjiI/Odopliku.Zapisdopliku wtrybieMAP_SHAREDodbywasięnabieżącowtrakcieoperacjinaobszarzepamięci. Unix:zaawansowaneoperacjeI/O18

O d w zo ro w a n ie p a m ci p rz yk ła d y

#include<sys/types.h> #include<sys/stat.h> #include<sys/mman.h>/*mmap()*/ #include<fcntl.h> #ifndefMAP_FILE/*44BSDdefinesthis&requiresittommapfiles*/ #defineMAP_FILE0/*tocompileundersystemsotherthan44BSD*/ #endif intmain(intargc,char*argv[]) { intfdin,fdout; char*src,*dst; structstatstatbuf; 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)/*needsizeofinputfile*/; if(lseek(fdout,statbuf.st_size-1,SEEK_SET)==-1) err_sys("lseekerror"); if(write(fdout,"",1)!=1)/*setsizeofoutputfile*/ err_sys("writeerror"); Unix:zaawansowaneoperacjeI/O19 if((src=mmap(0,statbuf.st_size,PROT_READ, MAP_FILE|MAP_SHARED,fdin,0))==(caddr_t)-1) err_sys("mmaperrorforinput"); if((dst=mmap(0,statbuf.st_size,PROT_READ|PROT_WRITE, MAP_FILE|MAP_SHARED,fdout,0))==(caddr_t)-1) err_sys("mmaperrorforoutput"); memcpy(dst,src,statbuf.st_size);/*doesthefilecopy*/ exit(0); } Unix:zaawansowaneoperacjeI/O20

Cytaty