我正在使用armv7進行openwrt開發,並面臨由vfork引起的段錯誤。uClibc vfork()導致段錯誤
我已經寫了一個小測試程序有以下部分:
...
pid_t child_t;
if((child_t = vfork()) < 0)
{
printf("error!\n");
return -1;
}
else if(child_t == 0)
{
printf("in child:pid =%d\n",getpid());
sleep(2);
_exit(0);
}
else
{
printf("in parent:child_t id = %d,pid = %d\n",child_t,getpid());
}
...
的了vfork()函數總是會導致段錯誤,這是GDB調試跟蹤:
...
(gdb) c
Breakpoint 1, main (argc=1, argv=0xbefffed4) at handler.c:33
33 if((child_t = vfork()) < 0)
(gdb) stepi
0x00008474 in vfork() at libpthread/nptl/sysdeps/unix/sysv/linux/arm/../../../../../../../libc/sysdeps/linux/arm/vfo rk.S:71
71 SAVE_PID
(gdb) l
66
67 #else
68 __vfork:
69
70 #ifdef __NR_vfork
71 SAVE_PID
72 DO_CALL (vfork)
73 RESTORE_PID
74 cmn r0, #4096
75 IT(t, cc)
(gdb) b libpthread/nptl/sysdeps/unix/sysv/linux/arm/../../../../../../../libc/sysdeps/linux/arm/vfo rk.S:72
Breakpoint 2 at 0xb6fcf930: file libpthread/nptl/sysdeps/unix/sysv/linux/arm/../../../../../../../libc/sysdeps/linux/arm/vfo rk.S, line 72.
(gdb) disassemble
0x00008584 <+40>: bl 0x8444 <puts>
=> 0x00008588 <+44>: bl 0x8474 <vfork>
0x0000858c <+48>: str r0, [r11, #-12]
(gdb)stepi
...
(gdb) stepi
0x00008474 in vfork() at libpthread/nptl/sysdeps/unix/sysv/linux/arm/../../../../../../../libc/sysdeps/linux/arm/vfo rk.S:71
71 SAVE_PID
(gdb) disassemble
Dump of assembler code for function vfork:
=> 0x00008474 <+0>: add r12, pc, #0, 12
0x00008478 <+4>: add r12, r12, #8, 20 ; 0x8000
0x0000847c <+8>: ldr pc, [r12, #796]! ; 0x31c
(gdb) stepi
…
(gdb) disassemble
Dump of assembler code for function vfork:
0x00008474 <+0>: add r12, pc, #0, 12
0x00008478 <+4>: add r12, r12, #8, 20 ; 0x8000
=> 0x0000847c <+8>: ldr pc, [r12, #796]! ; 0x31c
(gdb)c
Continuing.
Program received signal SIGSEGV, Segmentation fault.
0xffff0fe0 in ??()
(gdb)
我還發現在vfork.S的vfork的代碼: __vfork:
#ifdef __NR_vfork
SAVE_PID
DO_CALL (vfork)
RESTORE_PID
cmn r0, #4096
IT(t, cc)
#if defined(__USE_BX__)
bxcc lr
#else
movcc pc, lr
#endif
/* Check if vfork even exists. */
ldr r1, =-ENOSYS
teq r0, r1
bne __error
#endif
/* If we don't have vfork, use fork. */
DO_CALL (fork)
cmn r0, #4096
/* Syscall worked. Return to child/parent */
IT(t, cc)
#if defined(__USE_BX__)
bxcc lr
#else
movcc pc, lr
#endif
__error:
b __syscall_error
#endif
一些更信息 - 繞過vfork的時候像這樣的 -
VFORK_LOCK;
- if ((pid = vfork()) == 0) { /* Child of vfork... */
+ // if ((pid = vfork()) == 0) { /* Child of vfork... */
+ pid = syscall(__NR_fork, NULL);
+ if (pid == 0) { /* Child of vfork... */
一切似乎很好地工作。
謝謝大家的幫助!
TL; DR:不要調用'vfork()'。這不適合你。 :) – duskwuff
vfork()用於uClibc實現。我可以控制它嗎? –