我实现了系统调用宏来调用软件中断调用。对于许多系统调用来说它运行良好。然而,这并不是为了fork()
。父进程和子进程的返回 pid 相同。片段如下:
#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");
}
Output:
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--
测试环境是在armv7上运行的越狱iOS(非越狱版无法运行)。
我想我可能对 swi 调用的返回做得不够,所以它无法返回 0 来指示子进程。我错过了什么?我怎样才能让它正常工作?
你不会那样做系统调用。正如您刚刚注意到的,系统调用的用户态包装器所做的工作远不止于此。因此,要么找到您的操作系统的源代码,弄清楚系统调用是如何包装的并执行相同的操作,要么只使用为您方便提供的包装器。
我非常确定 iOS 仍然以 BSD 方式进行系统调用。我碰巧知道fork使用两个返回值syscall接口,一个寄存器包含进程是否是子进程,另一个包含返回值。
此外,您的包装器可能无法正确执行错误处理(这通常通过您必须专门处理的标志来发出信号)。至少某些操作系统(不知道 iOS 是否是其中之一)确切地知道哪些寄存器保存在系统调用包装器中,并且不费心保存它们,因此像这样的内联系统调用可能会破坏您的寄存器。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)