c - Child 和 Parent 的执行流程

标签 c memory-management binary gdb posix

在网上看到我无法真正确定哪个进程在 child 或 parent 之前运行后,我计划在我的 PC 上禁用 ASLR 并运行调试器以查看我是否可以生成模式关于执行,我所做的观察在下面是 GitGist 到 GDB disas(完整)以及源代码

#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main()
{
fork();
//fork();
printf("LINUX\n");
//printf("my pid is %d",(int) getpid());
fork();
printf("REDHAT\n");
//printf("my pid is %d",(int) getpid());

//fork();
return 0;
}

这是我在 gdb 中取消它时所说的代码,它给了我:-

gdb-peda$ disas main
Dump of assembler code for function main:
   0x000000000000068a <+0>: push   rbp
   0x000000000000068b <+1>: mov    rbp,rsp
   0x000000000000068e <+4>: call   0x560 <fork@plt>
   0x0000000000000693 <+9>: lea    rdi,[rip+0xaa]        # 0x744
   0x000000000000069a <+16>:    call   0x550 <puts@plt>
   0x000000000000069f <+21>:    call   0x560 <fork@plt>
   0x00000000000006a4 <+26>:    lea    rdi,[rip+0x9f]        # 0x74a
   0x00000000000006ab <+33>:    call   0x550 <puts@plt>
   0x00000000000006b0 <+38>:    mov    eax,0x0
   0x00000000000006b5 <+43>:    pop    rbp
   0x00000000000006b6 <+44>:    ret    
End of assembler dump.

所以基本上它给了我一个执行的固定模式,所以我认为这应该意味着程序应该总是以特定的顺序执行我尝试了 disas main 大约 3 次以查看顺序是否真的改变了但它没有当我最终运行生成的二进制文件时,它给了我不同的输出

root@localhost:~/os/fork analysis# ./forkagain
LINUX
REDHAT
LINUX
REDHAT
REDHAT
REDHAT
root@localhost:~/os/fork analysis# ./forkagain
LINUX
LINUX
REDHAT
REDHAT
REDHAT
REDHAT

这与我在disas中所做的观察不一致,请有人填补我理解中的空白吗?

Fork Analysis Full

最佳答案

i tried disas main about 3 times to see if the order actually ever changes

顺序在编译时是固定的,因此如果不重新编译程序,它永远不会改变。

此外,顺序由您的程序源固定——不允许编译器对您的输出重新排序。

然后您观察到的是操作系统由于调用 fork 而引入的不确定性——在 fork 之后,无法保证哪个进程将首先运行,或者多长时间。 parent 可能会跑完,然后是 child 。或者 child 可能先跑完。或者它们都可以按时间片运行,比如一次一行。

此外,当今大多数非古老的 ​​Linux 系统都运行在多处理器机器上,两个独立的进程在 fork 后可以同时运行。

另一个复杂的问题是你的程序没有明确定义,因为 stdio 缓冲。当您看到 6 行输出时,您可能很难解释这个结果:

./forkagain | wc -l
8
./forkagain > junk.out; cat junk.out
LINUX
REDHAT
LINUX
REDHAT
LINUX
REDHAT
LINUX
REDHAT

您应该在 fork 之前添加 fflush(stdout); 以避免这种复杂情况。

附言您还应该改掉以 root 身份运行的坏习惯——迟早您会犯下愚蠢的错误(例如在错误的目录中键入 rm -rf *),您会非常抱歉您以 root 身份执行此操作。

关于c - Child 和 Parent 的执行流程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46961726/

相关文章:

javascript - 如何将 LLVM IR br 转换回 while 循环

c - 打印存储为字符串的十六进制值会产生意外输出

c++ - 代码块未正确显示程序参数

C++ - 将 auto_ptr 放入 shared_ptr vector 中

ios - 发送到已释放实例的消息 - 视为属性

c++ - 如何通过分配器为 int a[10][10] 分配内存

c++ - 在C++中通过套接字接收二进制数据

linux - 节头列表指向哪个字符串表?

colors - 以这种方式表示颜色#ffffff 和 0xffffff 有什么区别?

c - C中的无限循环