Важно е да се отбележи, че програмирането на ядрото се различава значително от програмирането в потребителското пространство. Ядрото е самостоятелен обект, който не може да използва библиотеки с потребителско пространство, дори libc на Linux или kernel32.dll на Windows. В резултат на това обичайните функции, използвани в потребителското пространство (printf, malloc, free, open, read, write, memcpy, strcpy и т.н.), вече не могат да се използват.
В заключение, програмирането на ядрото се основава на напълно нов и независим API, който не е свързан с API в потребителското пространство, независимо дали говорим за POSIX , Win32 или ANSI C. Важна разлика в програмирането на ядрото е как да получите достъп до него. и разпределение на паметта. Поради факта, че програмирането на ядрото се извършва на ниво, много близко до физическата машина, има важни правила относно управлението на паметта.
Първо, работи с няколко типа памет:
– физическа памет
– виртуална памет в адресното пространство на ядрото
– виртуална памет от адресното пространство на процес
– резидентна памет – знаем със сигурност, че достъпните страници присъстват във физическата памет
Виртуалната памет в адресното пространство на процес не може да се счита за резидентна поради механизмите за виртуална памет, внедрени от операционната система: страниците може да са в суап или да не присъстват във физическата памет в резултат на механизма за страниране на заявката.
Паметта в адресното пространство на ядрото може или не може да бъде резидентна. Сегментите с данни и код на модул и стекът на ядрото на процес са резидентни.
Динамичната памет може или не може да бъде резидентна, в зависимост от това как е разпределена. Когато работите с резидентна памет, нещата са прости: паметта може да бъде достъпна по всяко време. Въпреки това, ако работите с нерезидентна памет, тя може да бъде достъпна само от определени контексти.
Нерезидентната памет може да бъде достъпна само от контекста на процеса. Достъпът до нерезидентната памет от контекста на прекъсването има непредвидими резултати и следователно, когато операционната система открие такъв достъп, тя ще предприеме драстични мерки: блокиране или нулиране на системата, за да предотврати сериозна повреда.
До виртуалната памет на процес не може да се осъществи директен достъп от ядрото. По принцип е напълно обезкуражено да се осъществява достъп до адресното пространство на процес, но има ситуации, в които драйвер на устройство трябва да го направи. Типичният случай е, когато драйверът на устройството трябва да има достъп до буфер от потребителското пространство. В този случай драйверът на устройството трябва да използва специални функции и да не осъществява директен достъп до буфера. Това е необходимо, за да се предотврати достъп до невалидни области на паметта.
Друга разлика от програмирането в потребителско пространство, свързана с работата с памет, се дължи на стека, стека, чийто размер е фиксиран и ограничен. В Ядрото на Linux по подразбиране се използва 4K стек, а в Windows се използва 12K стек. Поради тази причина трябва да се избягва разпределянето на големи структури в стека или използването на рекурсивни извиквания.
По отношение на режима на изпълнение в ядрото, ние разграничаваме два контекста: контекст на процес и контекст на прекъсване. Ние сме в контекста на процеса, когато изпълняваме код след системно извикване или когато изпълняваме в контекста на нишка на ядрото. Когато работим в рутината на работа с прекъсване или отложено действие, ние работим в контекст на прекъсване.
Една от най-важните характеристики на програмирането на ядрото е паралелизмът. Както Linux, така и Windows поддържат SMP системи с множество процесори, но също така ядрото превантивно поддържа множество процесори. Това прави програмирането на ядрото по-трудно, тъй като достъпът до глобалните променливи трябва да бъде синхронизиран със спинлок или блокиращи примитиви.
Както Linux, така и Windows използват превантивни ядра. Понятието превантивна многозадачност не трябва да се бърка с понятието превантивно ядро. Понятието превантивна многозадачност се отнася до факта, че операционната система прекъсва изпълнението на процес по принудителен начин, когато той е изтекъл времето и се изпълнява в потребителското пространство, за да стартира друг процес.
За програмиране в Ядрото на Linux, конвенцията, използвана за извикване на функции за указване на успех, е идентична с тази в програмирането на UNIX: 0 за успех или стойност, различна от 0 за неуспех.