linux - uClibc vfork() 导致段错误

标签 linux libc openwrt uclibc

我使用armv7进行openwrt开发,遇到了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... */

一切似乎都运行良好。

感谢大家的帮助!

最佳答案

人(3)vfork

The vfork() function shall be equivalent to fork(), except that the behavior is undefined if the process created by vfork() either modifies any data other than a variable of type pid_t used to store the return value from vfork(), or returns from the function in which vfork() was called, or calls any other function before successfully calling _exit() or one of the exec family of functions.

因此,在子进程中,您可以调用 _exitexec。就是这样。

关于linux - uClibc vfork() 导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24603406/

相关文章:

c - 为什么没有 strnspn() 或 strncspn()?

linux - 查找以太网设备的物理端口 - OPENWRT

javascript - 如何在 nodejs Linux 上判断/更改 javascript 的版本

linux - 为什么 Perforce 不能在 Linux 上设置环境变量?

c++ - 静态链接新的 libc 符号以与较低的 libc 版本一起使用

c++ - 为什么这个 C++ 'new' 运算符的实现有效?

linux - 如何从 Shell 脚本逆向 SSH

linux - 如何在 linux AP 中获取 RSSI(iw 站转储不起作用)

linux - 如何判断用户是否选择了 "Run In Terminal"

linux - 术语:c_oflag 中的 OFILL 标志有何用途?