Что содержит каждая запись в структуре Jmp_buf? - PullRequest
10 голосов
/ 01 декабря 2009

Я использую Ubuntu 9.10 (Karmic Koala), и я взглянул на структуру jmp_buf, которая представляет собой просто массив из 12 дюймов Когда я использую setjmp и передаю структуру jmp_buf - 4 из 12 записей сохраняются. Эти 4 записи - указатель стека, указатель кадра, счетчик программы и адрес возврата. Для чего нужны остальные 8 записей? Они зависят от машины? Является ли другая запись базовым регистром таблицы сегментов? Что еще нужно для правильного восстановления среды потока / процесса? Я просмотрел справочную страницу, другие источники, но не смог найти код сборки для setjmp.

Ответы [ 2 ]

9 голосов
/ 01 декабря 2009

В MacOS X 10.6.2 заголовок <setjmp.h> заканчивается использованием <i386/setjmp.h>, и там говорится:

#if defined(__x86_64__)
/*
 * _JBLEN is number of ints required to save the following:
 * rflags, rip, rbp, rsp, rbx, r12, r13, r14, r15... these are 8 bytes each
 * mxcsr, fp control word, sigmask... these are 4 bytes each
 * add 16 ints for future expansion needs...
 */
#define _JBLEN ((9 * 2) + 3 + 16)
typedef int jmp_buf[_JBLEN];
typedef int sigjmp_buf[_JBLEN + 1];

#else

/*
 * _JBLEN is number of ints required to save the following:
 * eax, ebx, ecx, edx, edi, esi, ebp, esp, ss, eflags, eip,
 * cs, de, es, fs, gs == 16 ints
 * onstack, mask = 2 ints
 */

#define _JBLEN (18)
typedef int jmp_buf[_JBLEN];
typedef int sigjmp_buf[_JBLEN + 1];

#endif

Вероятно, вы найдете аналогичные требования для Linux - jmp_buf содержит достаточно информации для хранения необходимого состояния. И, чтобы использовать его, вам действительно не нужно знать, что он содержит; все, что вам нужно сделать, это поверить, что разработчики поняли это правильно. Если вы хотите изменить реализацию, вам, конечно, нужно это понять.

Обратите внимание, что setjmp и longjmp очень специфичны для машины. Прочитайте Plauger " Стандартная библиотека C " для обсуждения некоторых вопросов, связанных с их реализацией. Более современные чипы затрудняют реализацию очень хорошо.

5 голосов
/ 01 декабря 2009

setjmp / longjmp / sigsetjmp сильно зависят от архитектуры процессора, операционной системы и модели потоков. Первые две функции, известные (или печально известные - в зависимости от вашего POV), появились в исходном ядре Unix как «структурированный» способ выхода из сбойного системного вызова, например, из-за ошибки ввода-вывода или других неприятных ситуаций.

Комментарии структуры в /usr/include/setjmp.h (Linux Fedora) говорят Среда вызова, плюс, возможно, сохраненная маска сигнала. Включает /usr/include/bits/setjmp.h для объявления jmp_buf должен иметь массив из шести 32-битных целых чисел, явно относящихся к семейству x86.

Хотя я не смог найти источник, отличный от реализации PPC , комментарии там разумно подсказывают, что настройки FPU должны быть сохранены. Это имеет смысл, поскольку не удастся восстановить режим округления, размер операнда по умолчанию, обработку исключений и т. Д.

Для системных инженеров характерно резервировать немного больше места, чем фактически требуется в такой структуре. Несколько лишних байтов вряд ли что-то потеют, особенно учитывая редкость фактического использования setjmp / longjmp. Слишком мало места определенно является опасностью. Самая важная причина, по которой я могу придумать, заключается в том, чтобы иметь дополнительные, а не точечные, в том, что если версия библиотеки времени выполнения изменена так, что ей требуется больше места в jmp_buf, то есть уже зарезервировано дополнительное пространство, нет необходимости перекомпилировать программы, ссылающиеся на это.

...