LINUX.ORG.RU

Как возникает событие segfault в ядре/железе?

 , , ,


0

1

Когда процессор считывает машинное слово, что происходит дальше? Если страница памяти не принадлежит адресному пространству процесса, то как определяется данное исключение (что происходит в cpu/kernel)?



Последнее исправление: nerdogeek (всего исправлений: 1)

Шел бы ты учиться куда-нибудь.

tailgunner ★★★★★
()

Если страница памяти не принадлежит адресному пространству процесса, то как определяется данное исключение (что происходит в cpu/kernel)?

Происходит page fault. Вам сюда: http://wiki.osdev.org/Paging

no-such-file ★★★★★
()

Не смапяные виртуальные адреса в таблице страниц каждого процесса мапятса на нулевую страницу. На нулевой странице нету никаких прав. Когда происходит обращение к ней проц генерит исключительную ситуацию и передаёт управление обработчику, который часть ядра и работает с правами ядра. Ядро смотрит: ага! current раньше делал malloc, значит надо ему выделить страницу из пула свободных страниц. Вылеляется страница и делается запись в таблице страниц и управление возвращается процессу (man optimistic memory allocation). Если свободных страниц нет - и да прибудет оом киллер(man oom killer). Если malloc никто не делал, тогда процессу шлют sigsegv, обработчик которого скромно пишет в stderr segmentation fault и делает exit(-1) или что-то в этом духе.

nanoolinux ★★★★
()

Когда процессор считывает машинное слово, что происходит дальше?

читай даташит про процессор, там всё есть.

Если страница памяти не принадлежит адресному пространству процесса

такого не бывает. процесс физически не имеет доступ к несвоим страницам, т.к. у него нет прав менять таблицу страниц. А она устанавливается и обслуживается ядром.

что происходит в cpu

электроны бегут из одного места в другое.

что происходит в kernel

ну ты понял, да?

nanoolinux ★★★★
()
Ответ на: комментарий от nanoolinux

Ну, как я понял проц генерит прерывание на каждое обращение к памяти. Чтобы определить виртуальный адрес принадлежит таблице страниц виртуальной памяти процесса или нет, каждый раз выполняется лукап из этой таблицы, или там есть кэши?

nerdogeek
() автор топика
Ответ на: комментарий от nerdogeek

Ну, как я понял проц генерит прерывание на каждое обращение к памяти.

нет, не на каждое, только на неправильное обращение. Иначе процессор впадёт в бесконечный цикл, обработчик прерывания тоже ведь в памяти находится, и чтобы его выполнить, надо к памяти обращаться

Harald ★★★★★
()
Ответ на: комментарий от nanoolinux

раньше делал malloc

malloc

wut? Какой еще malloc, там просто устанавливается верхняя граница адресов процесса или я отстал от жизни?

no-such-file ★★★★★
()
Ответ на: комментарий от nanoolinux

Домыслы. А читаю Роберт Лав «Разработка ядра линукс»

nerdogeek
() автор топика
Ответ на: комментарий от anonymous

Буфер играет роль кеша. Если в нем нет свежей записи, то проц генерит прерывание. Т.е. в худшем случае всегда.

nerdogeek
() автор топика
Ответ на: комментарий от no-such-file

wut? Какой еще malloc, там просто устанавливается верхняя граница адресов процесса или я отстал от жизни?

Хорошие криокамеры. Glibc уже давно использует не только brk() но и mmap().

AptGet ★★★
()
Ответ на: комментарий от nerdogeek

Если в нем нет свежей записи, то проц генерит прерывание. Т.е. в худшем случае всегда.

ну нет же

Если адрес отсутствует в TLB, процессор обходит таблицы страниц и сохраняет полученный адрес в TLB, что занимает в 10-60 раз больше времени, чем получение адреса из записи, уже закешированной TLB.

Harald ★★★★★
()
Ответ на: комментарий от nerdogeek

Буфер играет роль кеша. Если в нем нет свежей записи, то проц генерит прерывание. Т.е. в худшем случае всегда.

это на спарках чтоль? на x86 page walk аппаратный, программисту никаких прерываний не видно

AptGet ★★★
()
Ответ на: комментарий от AptGet

Хорошие криокамеры

Да уж, не то, что ваши тормоза - речь вообще-то о ядре.

Ядро смотрит: ага! current раньше делал malloc

Таки ядро смотрит, что malloc?

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

Таки ядро смотрит, что malloc?

у ядра есть карта адресов процесса. Когда-то в антикварных юниксах одного program break для обработки исключений хватало, но уже давно память можно выделять в обход brk() и библиотечный malloc именно так память и выделяет. Используя mmap().

AptGet ★★★
()
Ответ на: комментарий от AptGet

библиотечный malloc именно так память и выделяет. Используя mmap().

Я в курсе что через mmap, вопрос в том, имеет ли процесс непрерывное пространство адресов (до brk) или теперь пространство процесса может иметь дыры?

no-such-file ★★★★★
()

Когда процессор считывает машинное слово, что происходит дальше? Если страница памяти не принадлежит адресному пространству процесса, то как определяется данное исключение (что происходит в cpu/kernel)?

как обычно. Прочитай про исключения процессора. Это подпрограмма, разница лишь в том, что она самим процессором вызывается, а не командой call.

drBatty ★★
()
Ответ на: комментарий от nerdogeek

Ну, как я понял проц генерит прерывание на каждое обращение к памяти.

нет. Пи обращении процессор смотрит кеш TLB, в поисках страницы, если нет, то в таблицу страниц смотрит. А вот если и там нет, то да, происходит исключение которое

  • создаёт новую страницу
  • выгружает страницу из swap на диске, если она там
  • выдаёт pagefault и рушит процесс, если прошлые исходы невозможны.
drBatty ★★
()
Ответ на: комментарий от no-such-file

wut? Какой еще malloc, там просто устанавливается верхняя граница адресов процесса или я отстал от жизни?

таки отстал. Читай про виртуальную память.

drBatty ★★
()
Ответ на: комментарий от AptGet

на x86 page walk аппаратный, программисту никаких прерываний не видно

смотря какому программисту. В пространстве ядра таки видно.

drBatty ★★
()
Ответ на: комментарий от no-such-file

Потому что процесс работает в плоской памяти.

плоская не значит «без дырок».

drBatty ★★
()
Ответ на: комментарий от no-such-file

Я в курсе что через mmap, вопрос в том, имеет ли процесс непрерывное пространство адресов (до brk) или теперь пространство процесса может иметь дыры?

пространство адресов процесса не непрерывное

$ ./test 
brk: 0x99a1000
brk: 0x99c2000, a: 0x99a1008
brk: 0x99c2000, b: 0xb760e008
003ec000-003ed000 r-xp 00000000 00:00 0          [vdso]
00a42000-00b9b000 r-xp 00000000 08:07 437169     /lib/tls/i686/cmov/libc-2.11.1.so
00b9b000-00b9d000 r--p 00159000 08:07 437169     /lib/tls/i686/cmov/libc-2.11.1.so
00b9d000-00b9e000 rw-p 0015b000 08:07 437169     /lib/tls/i686/cmov/libc-2.11.1.so
00b9e000-00ba1000 rw-p 00000000 00:00 0 
00c16000-00c31000 r-xp 00000000 08:07 437150     /lib/ld-2.11.1.so
00c31000-00c32000 r--p 0001a000 08:07 437150     /lib/ld-2.11.1.so
00c32000-00c33000 rw-p 0001b000 08:07 437150     /lib/ld-2.11.1.so
08048000-08049000 r-xp 00000000 08:07 1073466    /tmp/test
08049000-0804a000 r--p 00000000 08:07 1073466    /tmp/test
0804a000-0804b000 rw-p 00001000 08:07 1073466    /tmp/test
099a1000-099c2000 rw-p 00000000 00:00 0          [heap]
b760e000-b7710000 rw-p 00000000 00:00 0 
b7723000-b7726000 rw-p 00000000 00:00 0 
bff2d000-bff42000 rw-p 00000000 00:00 0          [stack]

$ cat test.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
	char buf[1024];
	printf("brk: %p\n", sbrk(0));

	int *a = malloc(100);
	*a = 1;

	printf("brk: %p, a: %p\n", sbrk(0), a);

	int *b = malloc(1024 * 1024);
	*b = 1;
	printf("brk: %p, b: %p\n", sbrk(0), b);

	snprintf(buf, sizeof(buf), "cat /proc/%d/maps", getpid());	

	system(buf);
}
AptGet ★★★
()
Ответ на: комментарий от AptGet

Ок. Я затупил немного, я про другие дыры - про дыры именно в куче. Т.е. brk определяет конец сегмента данных программы. Допустим malloc выделяет память через mmap, но эта область должна куда-то заммапится в виртуальных адресах. Выше brk? А что если после этого сделать sbrk? Или ммапится под стек? Или как-то по другому? В любом случае я думаю, что ммапится должно последовательно без пропусков, т.к. как такие пропуски потом сложно использовать.

no-such-file ★★★★★
()
Ответ на: комментарий от no-such-file

судя по этому кусочку стрейса

mmap2(NULL, 1052672, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb767d000
write(1, "brk: 0x9c21000, b: 0xb767d008\n", 30brk: 0x9c21000, b: 0xb767d008) = 30
mmap2(NULL, 26218496, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb5d7c000
write(1, "brk: 0x9c21000, c: 0xb5d7c008\n", 30brk: 0x9c21000, c: 0xb5d7c008) = 30

ядро само выбирает адрес новой области памяти, в данном случае выше brk и ниже стека, далее выделяет в сторону уменьшения адресов, без пропусков

AptGet ★★★
()
Ответ на: комментарий от drBatty

смотря какому программисту. В пространстве ядра таки видно.

Нигде не видно, x86 при TLB miss сам ходит по таблицам страниц. Для SPARC, AFAIK по TLB miss нужно вручную загрузить соответствующие записи в TLB.

AptGet ★★★
()
Ответ на: комментарий от AptGet

выше brk и ниже стека, далее выделяет в сторону уменьшения адресов, без пропусков

Теперь все ясно. Спасибо.

no-such-file ★★★★★
()
Ответ на: комментарий от AptGet

Нигде не видно, x86 при TLB miss сам ходит по таблицам страниц.

я знаю. Я про случай, если в таблице страниц такого адреса нет.

drBatty ★★
()
Ответ на: комментарий от no-such-file

да, ты прав, man brk и всё такое. это я так, что бы поддавану понятней было.

прочитал тред, походу я и сам от жизни отстал немного :/

nanoolinux ★★★★
()
Последнее исправление: nanoolinux (всего исправлений: 1)
Ответ на: комментарий от nanoolinux

да, ты прав, man brk и всё такое

Как оказалось, внезапно, ты тоже прав ибо malloc может ммапить отдельные области вне общей кучи.

поддавану

Главное, много не поддавать.

no-such-file ★★★★★
()

Когда процессор считывает машинное слово

Он его декодирует и помещает в очередь команд.

Если страница памяти

Страницы памяти имеют дескриптор (битовое поле), которое содержит: признак присутствия в памяти (для работы виртуалки), доступ (чтение/запись), уровень (емнип) и т.д.

то как определяется данное исключение

Как ты и написал - по любому поводу возникает исключение. Обработчик решает (на примере работы виртуалки) - настоящее исключение или нет. Если нет - молча подгружает страничку с диска.

ziemin ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.