Ще крашне
'>
Иначе това което ме стресна беше това:
...
iopl(3);
asm("cli");
...
Първото set-ва I/O привилегиите, второто изпълнява инструкцията CLI (която забранява прекъсванията).
По принцип CLI би следвало да може да се вика само в ring0 (kernel-mode). Използва се в критични секции от код (чието изпълнение не бива да се прекъсва), където случайно вдигане на прекъсване може да доведе до кофти проблеми. По този начин се забранява включително timer interrupt-a и следователно process scheduling-a не се случва. Дефакто cli превръща хубавата многозадачна система в нещо подобно на ДОС
'> Заради което кодът който се изпълнява между cli/sti трябва да се изпълнява максимално бързо и да е стабилен, защото забие ли, отнася го цялата система. И прост пример - например не искаш context switch-а да бъде прекъснат от току-що получен пакет от мрежовата карта, затова докато трае магията, прекъсванията се забраняват с cli после се разрешават с sti.
Дотук добре, ама се оказва че нещата били малко по-различни
'>
x86 архитектурата позволявала освен достъп до периферията (in/out), също така изпълняването на cli/sti инструкциите при условие че CPL<=IOPL. CPL не може да се промени, в линукс всички юзърски процеси имат cpl=3, демек работят в ring3.
IOPL....ами това се променя с iopl(). Ако I/O Privilege Level-a ти стане 3....тогава CPL=3, IOPL=3, CPL<=IOPL => имаш право да забраняваш прекъсванията в рамките на твоят процес!!!
Сега остава забавното, защо това е възможно в линукс.
Съществуването на iopl() е оправдано ЕДИНСТВЕНО заради някои определени X сървъри....както и заради особено великите модерни userspace драйвери.
В линукс съществуват само две положения....ring0 (CPL=0) - kernelspace....и ring3 (CPL=3) - userspace. Архитектурата позволява CPL=1 или 2, но линукс не се възползва от това. Доколкото съм чел обаче, уиндоус го прави.
Единственото хубаво нещо е че ядрото не ти позволява да си смениш IOPL ако не си привилегирован потребител (root).
Сега остават два въпроса:
1) Защо има ТОЛКОВА ОГРОМНО желание в линукс да се имплементират userspace драйвери, след като идейно нещата не са изчистени? Според мен може да се измисли един механизъм, в който въпросните драйвери да работят в ring1 и да има някакъв механизъм чрез който обикновен демон работещ в ring3 да ги изпълнява, да следи дали работят и да ги вдига ако паднат. Съответно да има някакъв механизъм чрез който авторизирани такива модули да могат да се зареждат.
2) Защо развиват теории според които юзърспейските драйвери са толкова стабилни и сигурни, след като един проблем в критична секция може отново да доведе до сриване на цялата система е отвъд моите разбирания.
П.П а ето и една миниатурна програма за крашване на линукс системи
'>
Примерен код |
#include <sys/io.h> void main() { iopl(3); asm("cli"); while (1) {} } |