栈切换Format

滩主 · · 1359 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

golang实现非协作式抢占调度基于此
在线程由于时钟中断从睡眠状态中醒来时,内核栈切换到用户栈执行中断处理函数,可以在此时修改用户栈的布局以及用户下一条指令

/* Example of using sigaction() to setup a signal handler with 3 arguments
 * including siginfo_t.
 */
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <string.h>
#include <stdint.h>


struct stackt {
    char*   ss_sp;
    uint64_t    ss_size;
    int32_t ss_flags;
    char    pad_cgo_0[4];
};

struct ucontext {
    int32_t uc_onstack;
    uint32_t uc_sigmask;
    struct stackt uc_stack;
    struct ucontext* uc_link;    
    uint64_t uc_mcsize;
    struct mcontext64* uc_mcontext; 
};

struct exceptionstate64 {
    uint16_t trapno;
    uint16_t cpu;
    uint32_t err;
    uint64_t faultvaddr;
};



struct regs64 {
    uint64_t    rax;
    uint64_t    rbx;
    uint64_t    rcx;
    uint64_t    rdx;
    uint64_t    rdi;
    uint64_t    rsi;
    uint64_t    rbp;
    uint64_t    rsp;
    uint64_t    r8;
    uint64_t    r9;
    uint64_t    r10;
    uint64_t    r11;
    uint64_t    r12;
    uint64_t    r13;
    uint64_t    r14;
    uint64_t    r15;
    uint64_t    rip;
    uint64_t    rflags;
    uint64_t    cs;
    uint64_t    fs;
    uint64_t    gs;
};



struct mcontext64 {
    struct exceptionstate64 es; 
    struct regs64 ss;
    // fs        floatstate64
    // pad_cgo_0 [4]byte
};

void hi() 
{
    printf("hi\n");
}
 
static void hdl (int sig, siginfo_t *siginfo, void* context)
{
    printf ("Sending PID: %ld, UID: %ld\n",
            (long)siginfo->si_pid, (long)siginfo->si_uid);

    struct ucontext* uctx = (struct ucontext*)context;

    struct regs64* reg = &(uctx->uc_mcontext->ss);

    printf("%llu\n", reg->rip);

    uint64_t pc = reg->rip;
    uint64_t sp = reg->rsp;

    sp -= sizeof(uint64_t);

    *((uint64_t*)sp) = pc;

    reg->rsp = sp;
    reg->rip = hi;
}
 
int main (int argc, char *argv[])
{
    struct sigaction act;
 
    memset (&act, '\0', sizeof(act));
 
    /* Use the sa_sigaction field because the handles has two additional parameters */
    act.sa_sigaction = &hdl;
 
    /* The SA_SIGINFO flag tells sigaction() to use the sa_sigaction field, not sa_handler. */
    act.sa_flags = SA_ONSTACK | SA_SIGINFO ;
 
    if (sigaction(SIGINT, &act, NULL) < 0) {
        perror ("sigaction");
        return 1;
    }
 
    while (1)
    {}
    
 
    return 0;
}


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:滩主

查看原文:栈切换Format

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1359 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传