c - 用户堆栈上的机器代码 - 操作系统

标签 c assembly operating-system stack kernel

我正在使用 xv6 操作系统,我的类(class)正在致力于为其实现信号。

我已经弄清楚如何在内核中实现处理程序(这是前两个练习),但现在我必须弄清楚如何运行用户定义的处理程序。

程序调用一个如下所示的信号函数

signal(int signum, void (*handler)(int))

用户程序(例如alarmtest3.c)将其用户函数作为第二个参数传递:

signal (14, snooze); // 14 is the signum for alarm 

我需要弄清楚的是一旦进入signal,如何让内核调用另一个系统调用sigret()。我相信需要这个系统调用来存储内核堆栈的 trapframe 的副本。重点是在一切发生后返回到用户空间。

用户堆栈应如下所示:

|other stack frames|
|a few bytes of machine code to call sys_sigret|
|signum parameter for the handler function|
|address of the first byte of the code above|

我知道要存储什么机器代码,我在汇编文件中找到了它。我只是不知道“调用 sys_sigret 的几个字节的机器代码”是什么意思。如何将此机器代码存储在堆栈上?

感谢您的帮助!

最佳答案

将代码存储在堆栈上不一定是个好主意,但如果您需要这样做,那就这样吧。至于如何操作:只需在内核内存中创建所述机器代码,然后将其及其自己的地址复制到用户堆栈,以便在信号处理程序返回时执行它。

Linux 是这样做的:

static const struct {
        u16 poplmovl;
        u32 val;
        u16 int80;
} __attribute__((packed)) retcode = {
        0xb858,         /* popl %eax; movl $..., %eax */
        __NR_sigreturn,
        0x80cd,         /* int $0x80 */
};

/*
 * This is popl %eax ; movl $__NR_sigreturn, %eax ; int $0x80
 *
 * WE DO NOT USE IT ANY MORE! It's only left here for historical
 * reasons and because gdb uses it as a signature to notice
 * signal handler stack frames.
 */
err |= __put_user(*((u64 *)&retcode), (u64 *)frame->retcode);

关于c - 用户堆栈上的机器代码 - 操作系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29607647/

相关文章:

c - OpenCL 内核似乎没有获取全局 id "globally"

c - C 中 VLA 的问题

windows - 如何唯一标识计算机上的操作系统?

windows - 使用 Visual C++ 2010 制作的 Windows 控制台应用程序的最低操作系统是什么?

c - c中tan(90)的值?

c++ - 使用 {0}、{0、} 进行数组初始化?

c - 如何在C程序中打印堆栈的内容?

编译器代码生成比较

程序集 x86 标志标志

assembly - 对非常量 TSS 段使用 jmp 指令