Scroll to navigation

MAKECONTEXT(3) Руководство программиста Linux MAKECONTEXT(3)

ИМЯ

makecontext, swapcontext - управляет пользовательским контекстом

СИНТАКСИС

#include <ucontext.h>

void makecontext(ucontext_t *ucp, void (*func)(), int argc, ...);

int swapcontext(ucontext_t *oucp, const ucontext_t *ucp);

ОПИСАНИЕ

In a System V-like environment, one has the type ucontext_t (defined in <ucontext.h> and described in getcontext(3)) and the four functions getcontext(3), setcontext(3), makecontext(), and swapcontext() that allow user-level context switching between multiple threads of control within a process.

Функция makecontext() изменяет контекст, на который указывает ucp (полученный из вызова getcontext(3)). Перед вызовом makecontext(), вызывающий должен выделить новый стек для этого контекста и присвоить его адрес ucp->uc_stack, и определить последующий контекст и присвоить его адрес ucp->uc_link.

Позднее, когда этот контекст активируется (с помощью setcontext(3) или swapcontext()), вызывается функция func и ей передаётся набор целочисленных аргументов (int), указанных после argc; вызывающий должен указать количество этих аргументов в argc. После возврата из функции активируется последующий контекст. Если указатель последующего контекста равен NULL, то нить завершается.

Функция swapcontext() сохраняет текущий контекст в структуру, на которую указывает oucp, и после этого активирует контекст, на который указывает ucp.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

При успешном выполнении swapcontext() не возвращает выполнение (но мы можем вернуться позднее при активации oucp и это будет выглядеть как если бы swapcontext() вернула 0). При ошибке swapcontext() возвращает -1 и изменяет errno соответствующим образом.

ОШИБКИ

Осталось недостаточно стекового пространства.

ВЕРСИИ

Функции makecontext() и swapcontext() появились в glibc начиная с версии 2.1.

АТРИБУТЫ

Описание терминов данного раздела смотрите в attributes(7).

Интерфейс Атрибут Значение
makecontext() Безвредность в нитях MT-Safe race:ucp
swapcontext() Безвредность в нитях MT-Safe race:oucp race:ucp

СООТВЕТСТВИЕ СТАНДАРТАМ

SUSv2, POSIX.1-2001. В POSIX.1-2008 удалены определения makecontext() и swapcontext() со ссылкой на проблемы с переносимостью и рекомендацией переписать приложение с использование нитей POSIX.

ЗАМЕЧАНИЯ

Назначение ucp->uc_stack подобно описанному в sigaltstack(2), а именно: данная структура содержит начало и размер области памяти, которая будет использоваться как стек, независимо от направления роста стека. То есть, в пользовательской программе нет необходимости учитывать это направление.

В архитектурах, где тип int и указатель имеют одинаковый размер (например, x86-32, оба типа имеют размер 32 бита), вы можете передавать указатели в аргументах makecontext() после argc. Однако, это не гарантирует переносимость, не определено в стандарте и не работает на архитектурах, где указатели больше int. Тем не менее, начиная с версии 2.8, в glibc внесены изменения в makecontext(), которые позволяют это и на некоторых 64-битных архитектурах (например, x86-64).

ПРИМЕРЫ

В программе, показанной далее, демонстрируется использование getcontext(3), makecontext() и swapcontext(). Вот результат запуска этой программы:


$ ./a.out
main: swapcontext(&uctx_main, &uctx_func2)
func2: запущена
func2: swapcontext(&uctx_func2, &uctx_func1)
func1: запущена
func1: swapcontext(&uctx_func1, &uctx_func2)
func2: возврат
func1: возврат
main: выход

Исходный код программы

#include <ucontext.h>
#include <stdio.h>
#include <stdlib.h>
static ucontext_t uctx_main, uctx_func1, uctx_func2;
#define handle_error(msg) \

do { perror(msg); exit(EXIT_FAILURE); } while (0) static void func1(void) {
printf("func1: запущена\n");
printf("func1: swapcontext(&uctx_func1, &uctx_func2)\n");
if (swapcontext(&uctx_func1, &uctx_func2) == -1)
handle_error("swapcontext");
printf("func1: возврат\n"); } static void func2(void) {
printf("func2: запущена\n");
printf("func2: swapcontext(&uctx_func2, &uctx_func1)\n");
if (swapcontext(&uctx_func2, &uctx_func1) == -1)
handle_error("swapcontext");
printf("func2: возврат\n"); } int main(int argc, char *argv[]) {
char func1_stack[16384];
char func2_stack[16384];
if (getcontext(&uctx_func1) == -1)
handle_error("getcontext");
uctx_func1.uc_stack.ss_sp = func1_stack;
uctx_func1.uc_stack.ss_size = sizeof(func1_stack);
uctx_func1.uc_link = &uctx_main;
makecontext(&uctx_func1, func1, 0);
if (getcontext(&uctx_func2) == -1)
handle_error("getcontext");
uctx_func2.uc_stack.ss_sp = func2_stack;
uctx_func2.uc_stack.ss_size = sizeof(func2_stack);
/* последующий контекст — f1(), если argc > 1 */
uctx_func2.uc_link = (argc > 1) ? NULL : &uctx_func1;
makecontext(&uctx_func2, func2, 0);
printf("main: swapcontext(&uctx_main, &uctx_func2)\n");
if (swapcontext(&uctx_main, &uctx_func2) == -1)
handle_error("swapcontext");
printf("main: выход\n");
exit(EXIT_SUCCESS); }

СМ. ТАКЖЕ

sigaction(2), sigaltstack(2), sigprocmask(2), getcontext(3), sigsetjmp(3)

ЗАМЕЧАНИЯ

Эта страница является частью проекта Linux man-pages версии 5.10. Описание проекта, информацию об ошибках и последнюю версию этой страницы можно найти по адресу https://www.kernel.org/doc/man-pages/.

ПЕРЕВОД

Русский перевод этой страницы руководства был сделан aereiae <aereiae@gmail.com>, Alexey <a.chepugov@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitriy S. Seregin <dseregin@59.ru>, Dmitry Bolkhovskikh <d20052005@yandex.ru>, ITriskTI <ITriskTI@gmail.com>, Max Is <ismax799@gmail.com>, Yuri Kozlov <yuray@komyakino.ru>, Иван Павлов <pavia00@gmail.com> и Малянов Евгений Викторович <maljanow@outlook.com>

Этот перевод является бесплатной документацией; прочитайте Стандартную общественную лицензию GNU версии 3 или более позднюю, чтобы узнать об условиях авторского права. Мы не несем НИКАКОЙ ОТВЕТСТВЕННОСТИ.

Если вы обнаружите ошибки в переводе этой страницы руководства, пожалуйста, отправьте электронное письмо на man-pages-ru-talks@lists.sourceforge.net.

21 декабря 2020 г. GNU