Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/59.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 用户级线程_C - Fatal编程技术网

C 用户级线程

C 用户级线程,c,C,我正在尝试创建用户级线程。这是我的代码示例。有人能帮我解决这个项目的问题吗 #include<stdio.h> #include<ucontext.h> int thread_counter = 0; int thread1, thread2; int who_am_i; struct TCB { ucontext_t context; void (* fun_ptr)(); }; struct TCB tcb[3]; char stack[2][81

我正在尝试创建用户级线程。这是我的代码示例。有人能帮我解决这个项目的问题吗

#include<stdio.h>
#include<ucontext.h>

int thread_counter = 0;
int thread1, thread2;
int who_am_i;

struct TCB {
    ucontext_t context;
    void (* fun_ptr)();
};
struct TCB tcb[3];
char stack[2][8192];


//----------------------
int thread_create(void (*fun)()) {
    static volatile int s;
    thread_counter++;
    s = 0;
    getcontext(&tcb[thread_counter].context);

    if(!s) {
        tcb[thread_counter].context.uc_stack.ss_sp   = stack[thread_counter];
        tcb[thread_counter].context.uc_stack.ss_size = sizeof(stack[thread_counter]);
        tcb[thread_counter].context.uc_link          = &tcb[0].context;
        tcb[thread_counter].fun_ptr                  = fun;
        s = 1;
    }
    else {
        tcb[who_am_i].fun_ptr();
    }

    return thread_counter;
}


void thread_yield(int next_thread) {
    static volatile int switched;
    switched = 0;
    getcontext(&tcb[who_am_i].context);

    if(!switched) {
        switched = 1;
        who_am_i = next_thread;
        setcontext(&tcb[next_thread].context);
    }
}


//----------------------
void f1() {
    printf("start f1\n");
    thread_yield(thread2);
    printf("finish f1:\n");
}

void f2() {
    printf("start f2\n");
    thread_yield(thread1);
    printf("finish f2\n");
}


//----------------------
int main() {
    thread1 = thread_create(f1);
    thread2 = thread_create(f2);

    who_am_i = 0;
    thread_yield(thread1);
    return 0;
}
谢谢

您有一个未定义的行为情况

thread\u create
中,首先要增加
thread\u计数器。因此,当您创建第二个线程时,线程计数器将是
2
。然后访问
堆栈[2]
,这将为您提供未定义的行为


您还可以将上下文的
uc\u链接
成员硬编码到
&tcb[0]。上下文
,由于
线程计数器
的“过早”增量,它从未初始化


但主要的问题是,您实际上并没有创建一个新的上下文,而是获取当前线程的上下文。您应该为每个线程使用。

thread\u yield
函数中,为什么要切换
变量
static
?无论如何,每次调用时都将该值设置为零。与
thread\u create
函数中的变量
s
相同。在代码中使用s和swithed没有任何意义。@JoachimPileborg。让
static
关键字被删除。但它给出了相同的输出。@Koushik<代码>无法直接检测getcontext()的返回是来自第一次调用,还是通过setcontext()调用。用户必须发明自己的簿记设备
。变量
s
switched
用于此目的。谢谢Joachim Pileborg。你是对的。但是,即使我将代码
stack[thread\u counter]
更改为
stack[thread\u counter-1]
,o/p也没有任何变化。@Ravi用其他问题更新了我的答案。谢谢JoachimPileborg的帮助,但是1。我不明白你所说的“创建上下文”是什么意思
tcb[0]。默认情况下,当第一次调用
thread\u yield
时,将初始化上下文。对于
makecontext
,我们仅限于根据我们的要求使用
getcontext
setcontext
。@Ravi在这种情况下,它很可能是一个旧答案,现在已删除,即主线程在两个子线程完成之前退出。在屈服于第一个线程之后,主程序应该进入一个循环,并屈服于所有未完成的线程,只要存在未完成的线程。当所有线程首先退出时,主程序可能会退出。
start f1
start f2
finish f2