为什么在处理ucontext时打印到stderr会导致分段错误?

时间:2018-12-23 01:34:24

标签: c posix ucontext

我正在为一个操作系统课程设计一个项目。任务是实现一个用于处理线程的库,类似于pthreads,但要简单得多。它的目的是练习调度算法。最终产品是.a文件。课程结束了,一切正常(就功能而言)。

尽管如此,我对自己遇到的问题感到好奇。在源文件的三个不同功能上,例如,如果添加以下行,则:

fprintf(stderr, "My lucky number is %d\n", 4);

我遇到了细分错误。如果改用stdout,或者格式不包含任何变量,则不会发生同样的情况。

这给我留下了两个主要问题:

  1. 为什么仅在我的代码的三个函数中而不是其他函数中发生?

  2. 使用getcontext()makecontext()创建上下文,或者使用setcontext()swapcontext()更改上下文是否会与标准文件描述符混淆? / p>

我的直觉说,这些功能可能是造成这种情况的原因。考虑到我的代码中发生的这三个函数是具有上下文环境的函数,代码其他部分会切换到该函数。通常由setcontext()使用,尽管swapcontext()用于转到调度程序,以选择另一个要执行的线程。

如果是这种情况,那么:

  1. 使用这些函数创建线程的正确方法是什么?

我目前正在执行以下操作:

/*------------------------------------------------------------------------------
Funct:  Creates an execution context for the function and arguments passed.
Input:  uc      -> Pointer where the context will be created.
        funct   -> Function to be executed in the context.
        arg     -> Argument to the function.
Return: If the function succeeds, 0 will be returned. Otherwise -1.
------------------------------------------------------------------------------*/
static int create_context(ucontext_t *uc, void *funct, void *arg)
{
    if(getcontext(uc) != 0) // Gets a context "model"
    {
        return -1;
    }
    stack_t *sp = (stack_t*)malloc(STACK_SIZE); // Stack area for the execution context
    if(!sp) // A stack area is mandatory
    {
        return -1;
    }
    uc->uc_stack.ss_sp = sp; // Sets stack pointer
    uc->uc_stack.ss_size = STACK_SIZE; // Sets stack size
    uc->uc_link = &context_end; // Sets the context to go after execution

    makecontext(uc, funct, 1, arg); // "Makes everything work" (can't fail)
    return 0;
}

此代码可能会稍作修改,但最初是有关如何使用u_context的在线示例。

1 个答案:

答案 0 :(得分:2)

假设使用glibc,则说明是fprintf具有未缓冲的流(默认情况下为stderr)在内部创建了一个堆栈缓冲区,其大小为BUFSIZE个字节。请参见buffered_vfprintf中的函数stdio-common/vfprintf.cBUFSIZ是8192,由于创建的堆栈太小,最终会导致堆栈溢出。