视觉上当您使用&符号调用相同的进程时会发生什么

时间:2014-11-10 17:13:37

标签: c shell ubuntu terminal

我正在玩 ampersand “&” 。我理解在bash shell脚本中

  

&符号用于 fork 进程,但将在后台中运行。这很有用,因为它可以让你立即回复 在后台运行

请注意以下代码:

#include <stdio.h>
#include <unistd.h>

int x=5;

void main()
{
   int pid = getpid();
   int y=6;

   printf("[%d] [%p] x = %d\n", pid, &x, x++);
   printf("[%d] [%p] y = %d\n", pid, &y, y++);
}

编译成功后,我运行代码:

> ./a.out & ./a.out & ./a.out

首次输出的输出:

[4436] [0x601058] x = 5
[4435] [0x601058] x = 5
[4436] [0x7fff2d481bd8] y = 6
[4435] [0x7fff7ecadd88] y = 6
[4437] [0x601058] x = 5
[4437] [0x7fff6e0741d8] y = 6

第二轮的输出:

[4469] [0x601058] x = 5
[4469] [0x7fffa00048b8] y = 6
[4470] [0x601058] x = 5
[4470] [0x7fffd447a798] y = 6
[4468] [0x601058] x = 5
[4468] [0x7fffc35dc7b8] y = 6

观察:

  • 某些打印报表按不同顺序显示,因为每个进程同时运行。
  • 变量x的地址在所有实例上都是相同的,因为它是一个全局变量。
  • x的值在所有实例中都是相同的,因为它每次都会重置为5。
  • 变量y只是main()的本地,因此它的地址在每个进程中都是唯一的。

以下是我的问题:

  1. 某些打印语句以不同顺序出现的原因取决于OS调度程序首先启动哪个进程?
  2. 由于变量x是全局的,并且似乎在所有运行/实例中保持相同的地址。在自动增量之后,为什么它的值不在进程之间共享?为什么任何进程都不打印增量值x?

1 个答案:

答案 0 :(得分:3)

每个processaddress space中都有拥有的virtual memory (感谢处理器的MMU)。所以变量x不是全局到你的3个进程;每个进程都有自己的x;因此,进程4436中的地址0x601058(x的打印地址)与进程4435中的“相同”地址0x601058的位置不同。

因此(虚拟)内存特定于每个进程。进程可以使用mmap(2)更改其地址空间。您可以使用一些高级技术在多个进程之间设置一些shared memory(但之前要了解一些Linux编程)。见shm_overview(7)&amp; sem_overview(7)。由于同步问题,你不应该(作为新手)想要使用共享内存。

阅读Advanced Linux Programming,它有几章与您的问题相关。

多线程进程有几个threads共享相同的地址空间(以及其他内容,如当前目录,打开的文件描述符等...)。另请阅读一些POSIX线程(a.k.a pthread) tutorial。每个帖子都有自己的call stack

请注意,由于ASLR,地址可能无法从一次运行再现到下一次运行。

Linux kernel有一个scheduler正在处理tasks。计划任务是线程或(单线程)进程。调度程序可以在任意时刻preempt执行任务,在多核处理器上,您可以并行运行多个任务(在不同的核心上)。

您还可以使用proc(5)播放(在Linux上)。如果你让你的进程睡觉,例如10秒,您可以在进程4436仍在运行(或睡眠)时键入(例如在不同的终端中)cat /proc/4436/maps

您也可以使用strace(1),也可以尝试strace a.out查看相关的syscalls(2)

当然,请多阅读fork(2)execve(2)

的文档

由于bash shell为free software,您可以研究其源代码。它会调用fork很多!