Кіріспе

Құрылғыға тән кіріс/шығыс операциялары үшін жүйелік шақыру

Компьютерлік есептеуде, ioctl (кіріс/шығыс басқаруының аббревиатурасы) – құрылғыға тән кіріс/шығыс операциялары және стандартты файл семантикасымен өрнектеуге болмайтын басқа операциялар үшін жүйелік шақыру. Ол сұрау кодын анықтайтын параметрді қабылдайды; шақырудың нәтижесі толығымен сұрау кодына байланысты. Сұрау кодтары көбінесе құрылғыға тән болады. Мысалы, физикалық құрылғыға диск шығаруды бұйыра алатын CD-ROM құрылғы драйвері, оны іске асыру үшін ioctl сұрау кодын ұсынады. Құрылғыдан тәуелсіз сұрау кодтары кейде пайдаланушы кеңістігінен ядролық функцияларға қол жеткізу үшін қолданылады, олар негізгі жүйелік бағдарламалық қамтамасымен ғана қолданылады немесе әлі де әзірлену үстінде. ioctl жүйелік шақыру алғаш рет Unix-тің 7-ші нұсқасында осы атаумен пайда болды. Ол Linux және macOS-ты қоса алғанда, көптеген Unix және Unix-қа ұқсас жүйелерде қолдауға ие, бірақ қол жетімді сұрау кодтары жүйеден жүйеге өзгеше болуы мүмкін. Microsoft Windows өзінің Win32 API-інде "DeviceIoControl" деп аталатын ұқсас функцияны ұсынады.

Өмірбаян

Кәдімгі операциялық жүйелерді екі қабатқа бөлуге болады: пайдаланушы кеңістігі және ядро. Мәтіндік редактор сияқты қолданбалық код пайдаланушы кеңістігінде орналасса, операциялық жүйенің желілік стек сияқты негізгі мүмкіндіктері ядрода болады. Ядролық код сезімтал ресурстарды басқарады және қолданбалар арасындағы қауіпсіздік пен сенімділік кедергілерін қамтамасыз етеді; осы себепті пайдаланушы режиміндегі қолданбаларға операциялық жүйе ядролық ресурстарға тікелей қол жеткізуге тыйым салады. Пайдаланушы кеңістігіндегі қолданбалар әдетте ядроға жүйелік шақырулар арқылы сұраулар жібереді, ал олардың коды ядролық қабатта орналасқан. Жүйелік шақыру көбінесе «жүйелік шақыру векторы» түрінде болады, онда қажетті жүйелік шақыру индекс нөмірімен белгіленеді. Мысалы, `exit` жүйелік шақыру нөмірі 1, ал `write` нөмірі 4 болуы мүмкін. Жүйелік шақыру векторы сұранысқа қажетті ядролық функцияны табу үшін қолданылады. Осылайша, кәдімгі операциялық жүйелер пайдаланушы кеңістігіне бірнеше жүз жүйелік шақыруды ұсынады. Стандартты ядролық мүмкіндіктерге қол жеткізу үшін бұл тиімді болғанымен, жүйелік шақырулар кейде стандартты емес аппараттық құрылғыларға қол жеткізу үшін қолайсыз. Қажеттілік бойынша, көптеген аппараттық құрылғылар (немесе құрылғылар) тікелей тек ядро ішінде ғана адрестеледі. Бірақ пайдаланушы коды құрылғылармен тікелей байланысқа түсуі керек болуы мүмкін; мысалы, әкімші Ethernet интерфейсіндегі медиа түрін конфигурациялауы мүмкін. Қазіргі операциялық жүйелер әртүрлі құрылғыларды қолдайды, олардың көптегені кең ауқымды мүмкіндіктерді ұсынады. Мұндай мүмкіндіктердің кейбіреулерін ядроны жобалаушылар ескермеуі мүмкін, сондықтан ядроның құрылғыларды пайдалану үшін жүйелік шақыруларды ұсынуы қиын. Бұл мәселені шешу үшін ядро кеңейтілмелі етіп жасалған, және ол ядролық кеңістікте жұмыс істейтін және құрылғыға тікелей қол жеткізе алатын құрылғы драйвері деп аталатын қосымша модульді қабылдауы мүмкін. `ioctl` интерфейсі – бұл бір жүйелік шақыру, арқылы пайдаланушы кеңістігі құрылғы драйверлерімен байланыса алады. Құрылғы драйверіне жасалған сұраулар осы `ioctl` жүйелік шақыруына қатысты векторланады, әдетте құрылғыға арналған тұтқа және сұрау нөмірі арқылы. Осылайша, базалық ядро пайдаланушы кеңістігіне құрылғы драйверіне құрылғының қолдайтын мүмкіндіктері туралы ештеңе білмей және жүйелік шақырулардың үлкен жиынтығына мұқтаж болмай-ақ кіруге мүмкіндік береді.

Жабдық құрылғысының конфигурациясы

IOCT-нің жиі қолданылатын мақсаты – аппараттық құрылғыларды басқару. Мысалы, Win32 жүйелерінде ioctl шақырулары USB құрылғыларымен байланыса алады немесе қосылған сақтау құрылғыларының дискінің геометриялық сипаттамалары туралы ақпаратты анықтай алады. OpenBSD және NetBSD жүйелерінде ioctl псевдо құрылғы драйвері мен bioctl утилитасы ifconfig-қа ұқсас, біріктірілген және сатушыға тәуелсіз интерфейс арқылы RAID томдарын басқару үшін қолданылады. NetBSD жүйесінде ioctl, sysmon фреймворкімен де қолданылады.

Терминалдар

IOCTl кодының соңғы пайдаланушы қолданбаларындағы бір қолданылуы – терминал I/O. Unix операциялық жүйелері дәстүрлі түрде командалық жол интерфейстерін кеңінен пайдаланған, бастапқыда тікелей VT100 сияқты аппараттық терминалдарды серийлік порттарға қосып, кейіннен терминал эмуляторларын және псевдотерминалдарды қолданатын қашықтан кіру серверлерін пайдаланған. Серийлік порт құрылғылары мен псевдотерминалдар екеуі де ioctl шақырулары арқылы басқарылады және конфигурацияланады. Мысалы, дисплейдің мөлшері TIOCSWINSZ шақыруы арқылы орнатылады. TIOCSTI (терминал I/O басқару, терминал кірісін имитациялау) ioctl функциясы бір таңбаны құрылғы ағынына жібере алады.

Жеделдетілген өзекшелер

Қолданбалар ядроны кеңейтуді қажет еткенде, мысалы, желілік өңдеуді жылдамдату үшін, ioctl шақырулары пайдаланушы кеңістігіндегі кодты ядролық кеңейтімдерге жалғаудың ыңғайлы жолын ұсынады. Ядролық кеңейтімдер файлдық жүйеде атаумен ашылатын орынды қамтамасыз ете алады, арқылы кез келген саны ioctl шақыруларын жіберуге болады, бұл кеңейтімді операциялық жүйеге жүйелік шақыруларды қосусыз бағдарламалауға мүмкіндік береді.

sysctl баламасы

OpenBSD әзірлеушісінің пікірінше, ioctl және sysctl – ядроны кеңейтуге арналған екі жүйелік шақыру, және sysctl олардың арасында ыңғайлырақ болуы мүмкін. NetBSD жүйесінде аппараттық мониторинг үшін қолданылатын sysmon envsys құрылғысы proplib арқылы ioctl-ді пайдаланады, ал OpenBSD және DragonFly BSD жүйелерінде оның орнына hw сенсорларының сәйкес құрылғысы үшін sysctl қолданылады. NetBSD-дегі envsys құрылғысының бастапқы нұсқасы proplib қолжетімді болмай тұрып ioctl арқылы іске асырылған, және құрылғының эксперименталды екенін, ал егер дамырылса, sysctl(8) интерфейсімен алмастырылуы керектігін көрсететін хабарлама болған, бұл OpenBSD-де sysctl-ді таңдауын және 2003 жылы hw сенсорларын енгізуін түсіндіруге болады. Алайда, envsys құрылғысы 2007 жылы proplib негізінде қайта құрылғанда, жүйелік шақыру ioctl ретінде қалды, ал хабарлама жойылды.

Басқа векторлық шақыру интерфейстері

Құрылғылар мен ядролық кеңейтулер қосымша жаңа жүйелік шақыруларды пайдаланып, пайдаланушы кеңістігімен байланыстырылуы мүмкін, бірақ бұл тәсіл сирек қолданылады, себебі операциялық жүйелерді әзірлеушілер жүйелік шақыру интерфейсін назарда ұстап, тиімділігін сақтауға тырысады. Unix операциялық жүйелерінде тағы екі векторлық шақыру интерфейсі кең таралған: fcntl ("файлды басқару") жүйелік шақыру ашық файлдарды конфигурациялайды және бұғатталмаған кіріс-шығыс (I/O) сияқты жағдайларда қолданылады; ал setsockopt ("сокет опциясын орнату") жүйелік шақыру ашық желілік сокеттерді конфигурациялайды, бұл BSD Unix жүйелерінде ipfw пакеттік брандмауэрін конфигурациялау үшін қолданылады.

Жады картасы

Unix құрылғы интерфейстері мен енгізу/шығару мүмкіндіктері кейде жадқа бейімделген файлдарды пайдалану арқылы қамтамасыз етіледі. Құрылғылармен байланысатын бағдарламалар, ioctl шақыруларындағыдай, құрылғыға сәйкес келетін файлдық жүйедегі бір орнына қол жеткізеді, бірақ содан кейін жадты бейімдеу жүйелік шақыруларын пайдаланып, өздерінің адрестік кеңістігінің бір бөлігін ядроның кеңістігімен байланыстырады. Бұл интерфейс құрылғы мен пайдаланушы кеңістігі арасында үлкен көлемдегі деректерді берудің әлдеқайда тиімді жолы болып табылады; жеке ioctl немесе оқу/жазу жүйелік шақырулары, пайдаланушы кеңістігінен ядроға қайта-қайта ауысудан туындаған қосымша шығындарға себеп болады, ал жадқа бейімделген адрестер диапазонына қол жеткізу мұндай қосымша шығындарға себеп болмайды. Win32 буферленген IO әдістерін немесе атаулы файлдық бейімдеу нысандарын қолдануға болады; алайда, қарапайым құрылғы драйверлері үшін стандартты DeviceIoControl әдісіне қол жеткізу жеткілікті.

Желілік байланыс

Netlink — процестер аралық байланыс (IPC) үшін сокет сияқты механизм, ол ioctl-дің көбірек икемді ізбасары ретінде әзірленген.

Күрделілігі

ioctl шақырулары ядроның жүйелік шақыру интерфейсінің күрделілігін азайтады. Дегенмен, ioctl шақырулары әзірлеушілерге ядролық бағдарламалау интерфейстерінің бөліктерін "сақтауға" мүмкіндік беретіндіктен, ол пайдаланушы мен ядро арасындағы API-ді күрделендіреді. Бірнеше жүз жүйелік шақыруды ұсынатын ядро, бірнеше мың ioctl шақыруын ұсынуы мүмкін. IOCTL шақыруларының интерфейсі дәстүрлі жүйелік шақырулардан сәл өзгеше болғанымен, іс жүзінде ioctl шақыруы мен жүйелік шақыру арасында айтарлықтай айырмашылық жоқ – ioctl шақыруы – әртүрлі жіберу механизмін қолданатын жүйелік шақыру ғана. Сондықтан, ядроның жүйелік шақыру интерфейсін кеңейтуге қарсы келтірілген көптеген аргументтер ioctl интерфейстеріне де қатысты болуы мүмкін. Қолданба дамытушылар үшін жүйелік шақырулар, қолданбаның ішкі процедураларынан ешқандай айырмашылығы жоқ, олар аргументтерді қабылдап, нәтижелерді қайтаратын функция шақырулары ғана. Операциялық жүйенің орындалу кітапханалары жүйелік шақыруларды шақырудың күрделілігін жасырады. Алайда, орындалу кітапханалары ioctl шақыруларын соншалықты түсінікті етпейді. Машинаның IP-адрестерін анықтау сияқты қарапайым операциялар көбінесе ioctl шақыруларының күрделі тізбегін қажет етеді, олардың әрқайсысы "магиялық" сандар мен аргументтік құрылымдарды талап етеді. Libpcap және libdnet – пакеттерді түсіру және пакеттік кіріс-шығыс үшін ioctl интерфейстерінің күрделілігін жасыруға арналған үшінші тараптың Unix кітапханаларының екі мысалы.

Қауіпсіздік

Негізгі операциялық жүйелердің пайдаланушы мен ядро арасындағы интерфейстері кодтағы қателер мен қауіпсіздікке қатысты осал жерлерді анықтау үшін шығарылмас бұрын мұқият тексеріледі. Бұл тексерулер әдетте жақсы құжатталған жүйелік шақыру интерфейстеріне бағытталған; мысалы, тексерушілер пайдаланушы идентификаторын өзгерту сияқты маңызды қауіпсіздік шақыруларын тек әкімшілік құқықтары бар пайдаланушылар ғана орындай алатынын қамтамасыз етуі мүмкін. IOCTL интерфейстері жүйелік шақыруларға қарағанда күрделірек, алуан түрлірек және тексеруге қиын. Сонымен қатар, IOCTL шақыруларын үшінші тарап әзірлеушілер көбінесе негізгі операциялық жүйе шығарылғаннан кейін ұсынады, сондықтан IOCTL шақыруларын іске асыру аз тексерілуі мүмкін, демек, оларда осал жерлер көп болуы мүмкін. Соңында, көптеген IOCTL шақырулары, әсіресе үшінші тараптың құрылғы драйверлері үшін, құжатталмаған. IOCTL шақыруын өңдеуші тікелей ядролық режимде орналасқандықтан, пайдаланушы кеңістігінен келетін деректерді мұқият тексеру қажет. Құрылғы драйверлеріндегі осал жерлер жергілікті пайдаланушылар IOCTL шақыруларына жарамсыз буферлерді жіберу арқылы пайдаланылуы мүмкін. Win32 және Unix операциялық жүйелері құрылғыға қолданылатын нақты кіру бақылаулары арқылы пайдаланушы кеңістігіндегі құрылғы атауын қолданбалардың кіруінен қорғай алады. Құрылғы драйверін жасаушылар пайдаланушы кеңістігіне қолжетімді объектіге тиісті кіру бақылауларын қолданбаған жағдайда қауіпсіздік проблемалары туындауы мүмкін. Кейбір заманауи операциялық жүйелер жүйелік шақыруларды пайдалану арқылы ядроны жаугершілік пайдаланушы кеңістігі кодын (мысалы, буфер асып кетуден зақымданған қолданбалар) қорғайды. Жүйелік шақыру орамалары рөлге негізделген кіруді бақылауды іске асырады, яғни қандай жүйелік шақыруларды қай қолданба шақыра алатынын анықтайды; мысалы, орамаларды пошта бағдарламасының басқа бағдарламаларды іске қосу құқығын "жою" үшін пайдалануға болады. IOCTL интерфейстері жүйелік шақыру орамаларын күрделілендіреді, себебі олардың саны көп, әрқайсысы әртүрлі аргументтерді қабылдайды, соның ішінде кейбіреулері қалыпты бағдарламаларға қажет болуы мүмкін.