Lataa esitys
Esittely latautuu. Ole hyvä ja odota
JulkaistuHannes Lehtinen Muutettu yli 9 vuotta sitten
1
TEKNIIKAN JA TALOUDEN YLIOPISTO www.lut.fi
2
Luku 23 – Signal Driven IO Periaate Esimerkki
3
Signal Driven IO Kernel lähettää ohjelmalle signaalin, kun jotain tapahtuu descriptorille Signal Driven IO:ta kutsuttu joskus virheellisesti asynkroniseksi IO:ksi SIGIO signaali
4
Vaiheet SIGIO käsittelijän määritteleminen Socketin omistaja pitää määritellä F_SETOWN komennolla fcntl kutsulle Signal Driven IO täytyy kytkeä päälle F_SETFL komennolla fcntl kutsulle (tai FIOASYNC ioctl)
5
SIGIO UDP sockettien kanssa SIGIO signaali lähetetään prosessille kun: Datagrammi vastaanotetaan Asynkroninen virhe tapahtuu
6
SIGIO ja TCP – Onko järkee vai ei? - EI! koska SIGIO lähetetään useasta syystä, eikä voida päätellä mitä socketille on tapahtunut
7
Signal Driven IO:n käyttötarkoitukset Ainoa tunnettu käyttö NTP palvelimessa, joka saa signaalien avulla tarkan tiedon pakettien saapumisajankohdista SIGIO käsittelijä vastaanottaa datagrammit ja lisää ne jonoon, jota palvelimen pääsilmukka tyhjentää (kuva s. 665)
8
Esimerkki: Jonon tietorakenne ja globaalit määrittelyt typedef struct { void*dg_data;/* ptr to actual datagram */ size_tdg_len;/* length of datagram */ struct sockaddr *dg_sa;/* ptr to sockaddr{} w/client's address */ socklen_tdg_salen;/* length of sockaddr{} */ } DG; static DGdg[QSIZE];/* queue of datagrams to process */ static longcntread[QSIZE+1];/* diagnostic counter */ static intiget;/* next one for main loop to process */ static intiput;/* next one for signal handler to read into */ static intnqueue;/* # on queue for main loop to process */ static socklen_t clilen;/* max length of sockaddr{} */ static voidsig_io(int); static voidsig_hup(int);
9
dg_echo (1/2) void dg_echo(int sockfd_arg, SA *pcliaddr, socklen_t clilen_arg) { inti; const inton = 1; sigset_tzeromask, newmask, oldmask; sockfd = sockfd_arg; clilen = clilen_arg; for (i = 0; i < QSIZE; i++) {/* init queue of buffers */ dg[i].dg_data = Malloc(MAXDG); dg[i].dg_sa = Malloc(clilen); dg[i].dg_salen = clilen; } iget = iput = nqueue = 0; Signal(SIGHUP, sig_hup); Signal(SIGIO, sig_io); Fcntl(sockfd, F_SETOWN, getpid()); Ioctl(sockfd, FIOASYNC, &on); Ioctl(sockfd, FIONBIO, &on); Sigemptyset(&zeromask);/* init three signal sets */ Sigemptyset(&oldmask); Sigemptyset(&newmask); Sigaddset(&newmask, SIGIO);/* signal we want to block */ Sigprocmask(SIG_BLOCK, &newmask, &oldmask);
10
dg_echo(2/2) for ( ; ; ) { while (nqueue == 0) sigsuspend(&zeromask);/* wait for datagram to process */ /* 4unblock SIGIO */ Sigprocmask(SIG_SETMASK, &oldmask, NULL); Sendto(sockfd, dg[iget].dg_data, dg[iget].dg_len, 0, dg[iget].dg_sa, dg[iget].dg_salen); if (++iget >= QSIZE) iget = 0; /* 4block SIGIO */ Sigprocmask(SIG_BLOCK, &newmask, &oldmask); nqueue--; }
11
SIGIO käsittelijä static void sig_io(int signo) { ssize_tlen; intnread; DG*ptr; for (nread = 0; ; ) { if (nqueue >= QSIZE) err_quit("receive overflow"); ptr = &dg[iput]; ptr->dg_salen = clilen; len = recvfrom(sockfd, ptr->dg_data, MAXDG, 0, ptr->dg_sa, &ptr->dg_salen); if (len < 0) { if (errno == EWOULDBLOCK) break;/* all done; no more queued to read */ else err_sys("recvfrom error"); } ptr->dg_len = len; nread++; nqueue++; if (++iput >= QSIZE) iput = 0; } cntread[nread]++;/* histogram of # datagrams read per signal */ }
Samankaltaiset esitykset
© 2024 SlidePlayer.fi Inc.
All rights reserved.