|
6.9.3. Селекторы в 80386Селектор сегмента загружается в сегментный регистр (cs, ds и т.д.), чтобы через сегментный регистр задать один из обычных сегментов в системе как один адрес. Формат селектора сегмента: 15 3 2 1 0 индекс TI RPL TI - индикатор таблицы: 0 означает, что индексы селектора относятся к GDT 1 означает, что индексы селектора относятся к LDT RPL - привилегированный уровень. Linux использует только два привилегированных уровня 0 означает ядро 1 означает пользователя Примеры: Сегмент кода ядра: TI = 0, индекс = 1, RPL = 0 поэтому сектор = 0х08 (GDT[1]) Сегмент данных пользователя TI = 1, индекс = 2, RPL = 3 поэтому сектор = 0х17 (LDT[2]) Cелекторы, используемые в Linux: TI index RPL selector segment 0 1 0 0x08 код ядра GDT[1] 0 2 0 0x10 данные/стек ядра GDT[2] 0 3 0 ??? ??? GDT[3] 1 1 3 0x0F код пользователя LDT[1] 1 2 3 0x17 данные/стек пользователя LDT[2] Селекторы для сегментов системы не предназначены для прямой загрузки в сегментные регистры. Напротив, должны быть загружены TR или LDTR. На входе системного вызова:
6.9.4. Дескрипторы сегментовИмеется дескриптор сегмента, используемый для описания каждого сегмента в системе. Имеются обычные и системные дескрипторы. Ниже представлен дескриптор во всей своей красоте. Такой странный формат создан специально для того, чтобы обеспечить совместимость с 286. Заметьте, что он занимает 8 байт 63-54 55 54 53 52 51-48 47 46 45 44-40 39-16 15-0 Base G D R U Limit P DPL S TYPE Segmet Base Segmet Limit 31-24 19-16 23-0 15-0 Разъяснения:
Системные дескрипторы в Linux TSS: P=1,DPL=0,S=0, type=9, limit=231 пространство для 1 tss_struct LDT: P=1,DPL=0,S=1, type=2, limit=23 пространство для 3 дескрипторов сегментов База устанавливается при выполнении fork(). Для каждой задачи есть свой TSS и LDT. Обычные дескрипторы ядра в Linux (head.S): код: P=1,DPL=0,S=1,G=1,D=1, type=a, base=0xc0000000, limit=0x3ffff данные: P=1,DPL=0,S=1,G=1,D=1, type=2, base=0xc0000000, limit=0x3ffff Состав LDT для task[0] (sched.h): код: P=1,DPL=3,S=1,G=1,D=1, type=a, base=0xc0000000, limit=0x9f данные: P=1,DPL=3,S=1,G=1,D=1, type=a, base=0xc0000000, limit=0x9f LDT, устанавливаемые по умолчанию для оставшихся задач (exec()): код: P=1,DPL=3,S=1,G=1,D=1, type=a, base=0, limit=0xbffff данные: P=1,DPL=3,S=1,G=1,D=1, type=2, base=0, limit=0xbffff Размер сегментов ядра 0х40000 страниц (4КВ страниц с G=1=1GB) тип подразумевает, что для кодового сегмента разрешается read-exec, а для сегмента данных read-write. Регистры, объединенные посредством сегментации. Формат сегментного регистра: (для программиста видимым является только селектор) 16 -бит 32-бит 32-бит селектор база физического адреса ограничения сегмента атрибуты Невидимую часть сегментного регистра более удобно рассматривать в формате, используемом во входах таблицы дескрипторов, которые устанавливает программист. Таблицы дескрипторов имеют связанные с ними регистры, которые используются при их размещении в памяти. GDTR (и IDTR) инициализируются при запуске и вместе с этим определяются таблицы. LDTR загружается при каждом переключении задачи. Формат GDTR (иIDTR): 32-бит 16-бит Линейный базовый адрес ограничение таблицы TR и LDTR загружаются из GDT и таким образом имеют формат других сегментных регистров. Регистр задач (TR) содержит дескриптор для TSS текущей выполняемой задачи. Выполнение перехода на селектор TSS вызывает сохранение состояния в старом TSS, в TR загружается новый дескриптор и регистры перезагружаются новым TSS. Эти действия реализуются программой-шедуллером при переключении задач пользователя. Отметим, что поле tss_struct.ltd содержит селектор для LDT этой задачи. Он используется для того, чтобы загрузить LDTR. (sched.h) |
helloworld.ru © 2001-2021 Все права защищены |
|
|