我正在为操作系统课程做一个项目。任务是实现一个用于处理线程的库,类似于pthreads
,但要简单得多。它的目的是练习调度算法。最终产品是.a
文件。课程结束了,一切都很好(就功能而言)。
尽管如此,我还是对自己面临的一个问题感到好奇。在我的源文件的三个不同功能上,如果我添加以下行,例如:
fprintf(stderr, "My lucky number is %dn", 4);
我有一个分割错误。如果使用stdout
,或者格式中不包含任何变量,则不会发生同样的情况。
这给我留下了两个主要问题:
为什么它只发生在我代码的三个函数中,而不发生在其他函数中?
使用
getcontext()
和makecontext()
创建上下文,或者使用setcontext()
或swapcontext()
更改上下文,是否会干扰标准文件描述符?
我的直觉认为这些功能可能是造成这种情况的原因。当我的代码中发生这种情况的三个函数都是具有代码其他部分切换到的上下文的函数时,情况就更糟了。通常通过setcontext()
,尽管swapcontext()
用于进入调度程序,以选择另一个线程执行。
此外,如果是这种情况,那么:
- 使用这些函数创建线程的正确方法是什么
我目前正在做以下工作:
/*------------------------------------------------------------------------------
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的在线示例。
假设glibc,解释是具有未缓冲流的fprintf
(默认情况下为stderr
)在内部创建一个大小为BUFSIZE
字节的堆栈上缓冲区。参见stdio-common/vfprintf.c
中的函数buffered_vfprintf
。BUFSIZ
是8192,所以您最终会出现堆栈溢出,因为您创建的堆栈太小。