在Linux上从头开始创建一个线程

时间:2014-04-25 17:20:10

标签: linux loader

我想知道是否可以从头开始创建一个新线程。 (与fork()不同,它给我一个memorymap和registerstate等的副本。)从一个空的页表开始,我可以在其中映射代码和数据。我还需要一种方法来放置指令指针。

动机:在硬件模拟器中,我经常会找到像

这样的东西
uint32_t read32(uint32_t addr) {
    if (RAM1_BEGIN <= addr && addr < RAM1_END)
        return *(uint32_t*)(ram1 + (addr-RAM1_BEGIN));
    else if (RAM2_BEGIN <= addr && addr < RAM2_END)
        return *(uint32_t*)(ram2 + (addr-RAM2_BEGIN));
    ...
}

我认为当主机已有MMU时,模拟MMU会浪费时间。

我可以使用mmap()来获取硬件所在位置的可用内存,但我无法100%确定它是免费的。 (Loader任意放置二进制文件和库。)这就是为什么我得出结论我需要一个新的空线程(和地址空间)。

1 个答案:

答案 0 :(得分:2)

正如我评论的那样,你不应该考虑在不使用线程库的情况下从头开始线程(如pthreads

您可以使用(并研究)MUSL libc的源代码,这是一个更轻松,更易于阅读的libc库。

如果您想开发自己的线程库,则需要使用 clone(2)&amp; futex(2)并且您必须在汇编程序中编写几个代码(请参阅futex(7)解释原因,以及setcontext(3))。

如果你想开发自己的线程库(我强烈建议不要去那条路线),准备好花上好几个月的工作!您可能需要了解编译器的工作原理(它与线程实现有关),也许需要对其进行修补。

附加物

针对您设置某些特定地址空间的特定问题,您可以巧妙地使用mmap(2)munmap(2)(并禁用ASLR),但不要忘记{to { {3}}你的代码在其他地方并跳转到它...(这是一个棘手的问题,也许是静态链接和编译-fPIE可能会有所帮助;你需要准确理解relocate和你的libc正在做什么...)。如果你知道静态地你想要什么地址空间-e.g.如果RAM1_BEGIN等是编译时文字常量 - 您可以使用特定的ld指令或ELF在链接时强制执行它。