Szavazás és kiválasztás

E hívások bármelyikének támogatásához az eszközvezérlő támogatást igényel. Ez a támogatás (mind a három hívásnál) a poll driver módszerrel (polling) történik. Ez a módszer a következő prototípussal rendelkezik:







unsigned int (* poll) (struct fájl * filp, poll_table * vár);

A meghajtó módszerét akkor hívják meg, amikor a felhasználói térprogram végrehajtja a lekérdezési rendszerhívást. válassza ki vagy írja be az illesztőprogramhoz tartozó fájlleírást. A készülék módszere felelős e két műveletért:

1. Hívja a poll_wait egy vagy több várakozási sorra, ami jelezheti a lekérdezési állapot változását. Ha jelenleg nincs I / O fájlleíró, akkor a rendszermag a folyamatban lévő várakozási sorban várakozik a rendszerhíváson átadott összes fájlleíró számára.

2. Adjon vissza egy olyan maszkot, amely leírja a műveleteket (ha vannak ilyenek), amelyek azonnal blokkolás nélkül végrehajthatók.

Mindkét művelet általában egyszerű és nagyon hasonlít az egyik vezetőtől a másikig. Feltételezzük azonban, hogy csak az illesztőprogram adhatja meg ezt az információt, ezért azokat minden egyes vezetőnek egyedileg kell végrehajtania.

void poll_wait (struct fájl * filp, wait_queue_head_t * wait_queue, poll_table * várjon);

A második feladatot a lekérdezés módszere végzi el egy bitmaszk leírásának visszaadásával, amely műveletek azonnal elvégezhetők; ez is egyszerű. Például ha a készüléknek van adatai, az olvasás alvás nélkül történik; a közvélemény-kutatás módszerének meg kell mutatnia ezt a helyzetet. Az esetleges műveletek jelzésére több zászlót használnak (a ):

Ezt a bitet akkor kell beállítani, ha a "normál" adatok olvashatók. Az olvasandó eszköz visszatér (POLLIN | POLLRDNORM).

Ez a bit azt jelzi, hogy a logikai kapcsolaton kívüli adatok (a segéd segédcsatornától) rendelkezésre állnak az eszközről történő leolvasáshoz. Jelenleg csak egy helyen használják a Linux kernelben (DECnet kód), és általában nem vonatkozik az eszközillesztőkre.

Ha a készülék olvasása során a fájl végét látja, az illesztőprogramnak meg kell határoznia a POLLHUP (hang) beállítást. A folyamat kiválasztása azt jelzi, hogy a készülék olvasható, ahogy azt a választott funkció határozza meg.

Hiba történt a készüléken. Amikor a lekérdezést hívják, az eszközről olvasható és írható, és az olvasás és az írás visszaállítja a hibakódot blokkolás nélkül.

Ez a bit a visszatérési értékben van beállítva, ha az eszköz zárolás nélkül írható.

Ez a bitnek ugyanaz a jelentése, mint a POLLOUT, és néha ugyanaz a szám. Az írható eszköz visszatér (POLLOUT | POLLWRNORM).

Érdemes megismételni, hogy a POLLRDBAND és a POLLWRBAND csak akkor érdemes a socketekhez tartozó fájlleírókkal kapcsolatban: az eszközillesztők általában nem használják ezeket a zászlókat.

A lekérdezés felmérése sok helyet foglal el a viszonylag könnyen használható gyakorlatban. Tekintse meg a szavazási módszer végrehajtását a scullpipe-ben:

statikus aláíratlan int scull_p_poll (struct fájl * filp, poll_table * vár)

struct scull_pipe * dev = filp-> private_data;

aláírás nélküli int mask = 0;

* Ez a puffer körkörös; teljesnek tekinthető

* ha a "wp" közvetlenül az "rp" mögött van, és üres, ha

poll_wait (filp, dev-> inq, várjon);

poll_wait (filp, dev-> outq, várj);

ha (dev-> rp! = dev-> wp)

maszk | = POLLIN | POLLRDNORM; / * olvasható * /

maszk | = POLLOUT | POLLWRNORM; / * írva * /

Ez a kód csak két várakozási sorot ad a poll_tablehez. majd beállítja a megfelelő bitmaszkot attól függően, hogy az adatok olvashatók-e vagy írhatók-e.

A megjelenített lekérdezési kód nem támogatja a "fájl végét", mert a scullpipe nem támogatja a "fájlvég" állapotot. A legtöbb valódi eszköz esetében a szavazásnak vissza kell térnie a POLLHUP-hoz. ha az adatok már nem (vagy nem). Ha a hívó a kiválasztott rendszerhívást használta. ez a fájl olvasható. Függetlenül attól, hogy a felmérést vagy a választást használták-e. Az alkalmazás tudja, hogy az olvasás örökre várakozás nélkül olvasást eredményezhet, és az olvasási módszer visszatér, jelezve 0-at a fájl végének.

Valódi FIFO-kkal például az olvasó látja a fájl végét, amikor minden író bezárja ezt a fájlt, míg a scullpipe olvasó soha nem látja a fájl végét. A viselkedés azért különbözik, mert a FIFO két folyamat közötti kommunikációs csatorna, és a scullpipe egy szemetes, ahol mindenkinek adhat adatokat, miközben van legalább egy olvasó. Ezenkívül nincs értelme a kernelben már rendelkezésre álló újratelepítésnek, ezért példánkban újabb viselkedést választottunk a megvalósításhoz.

Végrehajtása „fájl vége”, valamint a FIFO, az lenne, hogy csinál egy átvilágítás dev-> nwriters olvasható és közvélemény-kutatás, és jelentse a „fájl végén” (a fentiek szerint), ha nincs folyamatban, amely a készülék nyitott írásra. Sajnos, ha egy ilyen kivitelezés, ha egy olvasó nyitott scullpipe készüléket, mielőtt az író, akkor lásd: „a végén a fájl” anélkül, hogy esélyt kell várni az adatokat. A probléma megoldásának legmegfelelőbb módja a nyitott zár. mint a valódi FIFO-k; ez a feladat az olvasó feladata marad.







Kapcsolat és olvasás

A lekérdezés és a kiválasztott hívások célja előre meghatározni, hogy az I / O művelet blokkolva van-e. E tekintetben kiegészítik az olvasást és az írást. Ennél is fontosabb, hogy a közvélemény-kutatás és a kiválasztás hasznos, mivel lehetővé teszik az alkalmazás számára, hogy egyidejűleg több adatfolyamot is várjon, bár ezt a funkciót nem használjuk a pontozási példákban. A munka helyes elvégzéséhez három hívás helyes végrehajtására van szükségünk. Bár a következő szabályokat már többé-kevésbé mondták, itt összegeztük.

Adatok olvasása az eszközről

• Ha az adatokat a bemeneti puffert, az olvasási hívás vissza kell azonnal, anélkül, hogy bármilyen érzékelhető késés, még ha kevesebb adatot tartalmaz, mint alkalmazás igényelt és a vezető arról, hogy a fennmaradó adatok érkeznek a közeljövőben. Mindig kevesebb információt küldhet a kértnél, legalább egy bájt, ha valamilyen oknál fogva kényelmes (megcsináltuk). Ebben az esetben a lekérdezésnek vissza kell állnia a POLLIN | POLLRDNORM.

• Ha a bemeneti pufferben nincs adat, alapértelmezés szerint az olvasást le kell tiltani, amíg legalább egy bájt van. Másrészt, ha az O_NONBLOCK telepítve van. az olvasás azonnal visszaadódik az -EAGAIN értékkel (bár a System V néhány régebbi verziójában ebben az esetben 0 értéket ad vissza). Ezekben az esetekben a felmérésnek azt kell jelentenie, hogy az eszköz nem olvasható, amíg legalább egy bájtot nem fogad. Amint néhány adat jelenik meg a pufferben, visszalépünk az előző esetre.

• Ha a fájl végén állunk, az olvasásnak azonnal vissza kell térnie a 0 visszatérési értékével, függetlenül az O_NONBLOCK értéktől. Ebben az esetben a közvélemény-kutatásnak tájékoztatnia kell a POLLHUP-ot.

Írás az eszközre

• Ha a kimeneti pufferben hely van, akkor az írásnak késedelem nélkül vissza kell térnie. Kevesebb adatot fogad el, mint a kért hívás, de legalább egy bájtot kell elfogadnia. Ebben az esetben a lekérdezés azt jelenti, hogy az eszköz írható a POLLOUT | POLLWRNORM.

• Ha a kimeneti puffer megtelt, akkor az írás alapértelmezés szerint blokkolódik, amíg egy szabad területet meg nem szabad. Ha az O_NONBLOCK telepítve van. az írás azonnal visszaadódik az -EAGAIN értékkel (az öreg V rendszer visszaküldött 0). Ezekben az esetekben a felmérésnek azt kell jelentenie, hogy a fájl nem írható. Ha viszont az eszköz nem fogad el semmilyen további adatot, akkor az O_NONBLOCK beállításától függetlenül írja meg a -ENOSPC ("Nincs hely maradt az eszközön").

• Soha ne várjon az írási hívásra várni az adatátvitelre, még mielőtt visszatérne, még akkor is, ha az O_NONBLOCK törlésre került. Számos alkalmazás használja a választást. Annak megállapítása, hogy az írás blokkolódik-e. Ha a készüléket a rögzítéshez rendelkezésre állnak, a hívást nem szabad blokkolni. Ha a programot használó program meg akarja győződni arról, hogy a kimeneti pufferben lévő sorból származó adatok ténylegesen elhaladnak, akkor ennek az illesztőprogramnak biztosítania kell az fsync módszert. A cserélhető eszköz például egy fsync belépési ponttal rendelkezik.

Bár ez egy jó közös szabály, akkor azt is fel kell ismernünk, hogy minden eszköz egyedi, és néha kissé módosítani kell a szabályokat. Például az írásközpontú eszközök (például szalagos meghajtók) nem végezhetnek részleges írásokat.

A kimenetre alaphelyzetbe állítás a lemezre

Láttuk, hogy az írási módszer maga nem veszi figyelembe az adatátvitel összes igényét. Fsync funkció. Az azonos nevű rendszerhívással hívja fel ezt a rést. A prototípus módszere

int (* fsync) (struct fájl * fájl, struct dentry * dentry, int datasync);

Ha minden alkalmazásnak mindig biztosnak kell lennie abban, hogy az adatokat elküldték az eszközre, akkor az fsync módszert kell végrehajtani függetlenül attól, hogy telepítve van-e az O_NONBLOCK. Az fsync hívásnak csak akkor kell visszatérnie, ha az eszközre vonatkozó adatok teljesen át vannak adva (vagyis a kimeneti puffer üres), még akkor is, ha eltart egy ideig. Az adatszinkron argumentumot használják az fsync és az fdatasync rendszerhívások megkülönböztetésére; mint ilyen, csak a fájlrendszer kódját érinti, és az illesztőprogramok figyelmen kívül hagyhatják.

Az alapul szolgáló adatszerkezet

A szavazás tényleges végrehajtása és a rendszerhívások kiválasztása elég egyszerű ahhoz, aki érdekli, hogyan működik; Az epoll egy kicsit bonyolultabb, de ugyanazon a mechanizmuson alapul. Amikor egy felhasználói alkalmazás hívást kezdeményez. select vagy epoll_ctl (* Ez egy olyan funkció, amely belső e-struktúrát hoz létre a jövőbeli epoll_wait hívásokhoz.). a rendszermag felhívja a rendszerhívás által hivatkozott fájlok lekérdezési módját, és mindegyikük ugyanazt a poll_table-t adja át. A poll_table szerkezet csak egy olyan funkció köré tekergő, amely egy valós adatszerkezetet hoz létre. A lekérdezéshez és a kiválasztáshoz ez a szerkezet egy linkelt lista a memória oldalakról, amelyek a poll_table_entry struktúrákat tartalmazzák. Minden poll_table_entry tartalmaz egy fájlstruktúrát, és a wait_queue_head_t mutatók átkerülnek a poll_wait-hez a társított sorobjektummal együtt. A poll_wait hívás néha ezt a folyamatot is hozzáadja ehhez a várakozási sorhoz. Általánosságban elmondható, hogy a teljes struktúrát a rendszermagnak kell javítania, hogy ezt a folyamatot a szavazás előtt eltávolíthassa az összes ilyen sorból, vagy kiválaszthatja a visszatérést.

Ha a lekérdezett meghajtók közül egyik sem mutatja, hogy az I / O blokkolás nélkül előfordulhat, a szavazás egyszerűen alszik, amíg az egyik (esetleg sok) várakozási sor nem ébreszti fel.

Érdekes a felmérés végrehajtása, hogy a szavazó-meghajtó módszerét a NULL mutatóval mint poll_table argumentummal lehet hívni. Ez a helyzet több okból is előfordulhat. Ha az alkalmazás hívja a szavazást. elhalasztotta az időtúllépés 0 értékét (ami azt jelzi, hogy nincs várakozás), nincs ok a várólisták összegyűjtésére, és a rendszer csak nem tesz semmit. A poll_table mutatót azonnal a NULL-ra állítja be, miután a meghajtók lekérdeztek, jelezve, hogy az I / O lehetséges. Mivel mostantól a rendszermag tudja, hogy nem lesz várakozás, nem építi fel a várólisták listáját.

Miután a lekérdezési hívás befejeződött, a poll_table szerkezet felszabadul és a szavazóasztalhoz hozzáadott összes várakozási sorobjektum eltávolításra kerül az asztalról és a várakozási sorokból.

A 6-1. Ábrán megpróbáltuk bemutatni a felmérésben részt vevő adatstruktúrákat; ez a szám egy egyszerű adatszerkezet egyszerűsített ábrázolása, mivel figyelmen kívül hagyja a lekérdezési táblázat többoldalú jellegét, és figyelmen kívül hagyja az összes poll_table_entry részét képező fájlmutatót. Erősen ösztönözni kell a tényleges megvalósítás iránt érdeklődő olvasót és fs / select.c.

Szavazás és kiválasztás

6-1. Ábra. A szavazás mögé rejtődő adatszerkezet

Abban a pillanatban megértheted az új rendszerhívó epoll motívumát. A közvélemény-kutatás vagy a hívásválasztás jellemzően csak kis számú fájlleírást tartalmaz, így az adatszerkezet létrehozásának költsége kicsi. Azonban vannak olyan alkalmazások, amelyek több ezer fájlleíróval dolgoznak. Mindazonáltal az adatstruktúra létrehozása és törlése az egyes I / O műveletek között megfizethetetlenül drága. Az epoll rendszerhívás családja lehetővé teszi az ilyen alkalmazások számára, hogy csak egyszer készítsenek belső rendszermagot, és sokszor használják.




Kapcsolódó cikkek