我想知道是否有可能在Linux上的用户空间中的单个进程内实现本机代码的抢占式多任务处理。 (也就是说,从外部暂停一些正在运行的本机代码,保存上下文,在不同的上下文中交换,以及恢复执行,所有这些都由用户空间协调,但使用可能进入内核的调用。)我以为这可以使用信号来完成SIGALRM
处理程序和*context()
系列但事实certificate整个*context()
系列是异步信号不安全的,因此无法保证方法有效。 我确实找到了实现这个想法的要点 ,所以显然它确实在Linux上运行,至少有时候,即使POSIX也不需要工作。 gist将其安装为SIGALRM
上的信号处理程序,它会进行多次*context()
调用:
void timer_interrupt(int j, siginfo_t *si, void *old_context) { /* Create new scheduler context */ getcontext(&signal_context); signal_context.uc_stack.ss_sp = signal_stack; signal_context.uc_stack.ss_size = STACKSIZE; signal_context.uc_stack.ss_flags = 0; sigemptyset(&signal_context.uc_sigmask); makecontext(&signal_context, scheduler, 1); /* save running thread, jump to scheduler */ swapcontext(cur_context,&signal_context); }
Linux是否提供任何使此方法正确的保证? 有没有办法让这个正确? 是否有完全不同的方法正确地做到这一点?
(通过“在用户空间中实现”我并不是说我们永远不会进入内核。我的意思是与内核实现的抢先式多任务进行对比。)
您无法可靠地更改信号处理程序内的上下文。 (如果你是从某个信号处理程序那样做的,它通常会在实践中起作用,但并非总是如此,因此它是未定义的行为 )。
您可以在信号处理程序中设置一些volatile sig_atomic_t
标志(读取sig_atomic_t
)(参见signal(7) , signal-safety(7) , sigreturn(2) ……)并定期检查该标志(例如每隔几次至少检查一次)在你的代码中,例如在大多数调用之前,或者在你的事件循环中,如果你有一个等等……那么它就变成了合作的用户 – 土地调度。
如果您可以更改代码,例如当您设计一些发出C代码的编译器(一种常见做法 ),或者您破解C编译器发出此类测试时,则更容易做到。 然后,您将更改代码生成器,以便有时在生成的代码中发出此类测试。
您可能希望禁止阻塞系统调用,并将其替换为非阻塞变体或包装器。 另见poll(2) , fcntl(2)与F_SETFL
和O_NONBLOCK
等…
您可能希望代码生成器避免使用大型调用堆栈,例如GCC的-fsplit-stack
检测选项 (请参阅GCC中的-fsplit-stack
)。
如果你生成(或写一些)汇编程序,你可以使用这些技巧。 AFAIK Go编译器对其goroutines使用类似的东西。 研究你的ABI ,例如从这里开始 。
但是,内核启动的抢占式调度更可取(并且在Linux上仍会在进程或内核任务之间发生,请参阅clone(2) )。
PS。 如果使用类似技巧的垃圾收集技术对您感兴趣,请查看MTA上的 MPS和Cheney (例如,进入Chicken Scheme )。
以上就是c/c++开发分享可以在Linux上的用户空间中实现本机代码的抢占式多任务处理吗?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/560299.html