fork()实现使用svc调用

时间:2015-10-07 06:44:49

标签: ios c fork inline-assembly

我实现了syscall宏来调用软件中断调用。它适用于许多系统调用。但是,它不适用于#define SYSCALL0(N) ({ \ register int ip asm("ip") = N; \ register int r0 asm("r0"); \ asm volatile("swi 0x80" : "=r"(r0) : "r"(ip) : "memory"); \ r0; \ }) int main(int argc, char * argv[]) { NSLog(@"--beginning of program\n"); int counter = 0; pid_t pid = SYSCALL0(2); if (pid == 0) { NSLog(@"pid = %d", getpid()); // child process for (int i = 0; i < 3; ++i) NSLog(@"child process: counter=%d\n", ++counter); } else if (pid > 0) { NSLog(@"pid = %d", getpid()); // parent process for (int i = 0; i < 3; ++i) NSLog(@"parent process: counter=%d\n", ++counter); } else { // fork failed NSLog(@"fork() failed!\n"); return 1; } NSLog(@"--end of program--\n"); } 。父进程和子进程的返回pid是相同的。摘录如下:

2015-10-11 21:29:43.666 Training[2564:907] --beginning of program
2015-10-11 21:29:43.669 Training[2564:907] pid = 2650
2015-10-11 21:29:43.670 Training[2564:907] parent process: counter=1
2015-10-11 21:29:43.670 Training[2564:907] parent process: counter=2
2015-10-11 21:29:43.669 Training[2564:907] pid = 2650
2015-10-11 21:29:43.671 Training[2564:907] parent process: counter=3
2015-10-11 21:29:43.671 Training[2564:907] --end of program--
2015-10-11 21:29:43.671 Training[2564:907] parent process: counter=1
2015-10-11 21:29:43.672 Training[2564:907] parent process: counter=2
2015-10-11 21:29:43.673 Training[2564:907] parent process: counter=3
2015-10-11 21:29:43.674 Training[2564:907] --end of program--

输出:

viewHolder.button.settag(position);

经过测试的环境是在armv7上运行的iOS监狱(它不会在非越狱上运行)。 我想我可能没有完成swi调用的返回,所以它不能返回0表示子进程。我错过了什么?我如何让它正常工作?

2 个答案:

答案 0 :(得分:2)

你不会那样做系统调用。正如您刚才注意到的那样,系统调用的用户空间包装器会做更多的工作。因此要么找到操作系统的源代码,要弄清楚系统调用是如何包装的,也要做同样的事情,或者只使用为你方便地提供的包装器。

我很确定iOS仍然会以BSD的方式进行系统调用。我碰巧知道fork使用两个返回值syscall接口,一个寄存器包含进程是子进程,另一个包含返回值。

此外,你的包装器可能没有正确地进行错误处理(通常通过你必须特别处理的标志来发出信号)。并且至少有一些操作系统(不知道iOS是否是其中之一)确切地知道哪些寄存器保存在系统调用包装器中并且不需要保存它们,因此内联系统调用可能会破坏您的寄存器。

答案 1 :(得分:2)

我明白了。事实证明,在svc调用之后,如果后续代码是子代或父代,则将r1设置为指示符。代码段更改如下:

#include <dlfcn.h>
int svc_fork() {
    register int r3 asm("r3") = (int)dlsym(RTLD_DEFAULT, "_current_pid");
    register int r12 asm("r12") = 2;
    register int r1 asm("r1") = 1;
    register int r0 asm("r0");
    asm volatile("swi   0x80                        \n"
                 "cmp   r1, #0                      \n"
                 "beq   Lparent                     \n"
                 "mov   r0, #0                      \n"
                 "str r0, [r3]                      \n"
                 "Lparent:                          \n"
                 : "=r"(r0)
                 : "r"(r1), "r"(r12), "r"(r3)
                 : "memory");
    return r0;
}