c-当您用“与”符号调用同一进程时,会发生什么



我正在玩ampersand “&”。我知道在bash shell脚本中

安培数用于分叉进程,但将在后台运行。这很有用,因为它允许您立即返回提示,并在后台运行进程

请遵守以下代码:

#include <stdio.h>
#include <unistd.h>
int x=5;
void main()
{
   int pid = getpid();
   int y=6;
   printf("[%d] [%p] x = %dn", pid, &x, x++);
   printf("[%d] [%p] y = %dn", 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. 某些打印语句以不同顺序出现的原因取决于操作系统调度程序首先启动了哪个进程
  2. 由于变量x是全局的,并且似乎在所有运行/实例中都保持相同的地址。为什么在自动增量之后,它的价值没有在进程之间共享?为什么ANY进程不打印递增的x值

每个进程在虚拟内存中都有自己的地址空间(多亏了处理器的MMU)。因此,变量x对于您的3个进程不是全局;每个进程都有自己的CCD_ 3;因此过程4436中的地址0x601058(x的打印地址)与过程4435中的"相同"地址0x60105不是同一位置。

所以(虚拟)内存是每个进程特有的。进程可以使用mmap(2)更改其地址空间。您可以使用一些高级技术在多个进程之间建立一些共享内存(但之前会学习一些Linux编程)。参见shm_overview(7)&sem_overview(7)。您不应该(作为一个新手)因为同步问题而想要使用共享内存。

阅读《高级Linux编程》,它有几个章节与您的问题有关。

一个多线程进程有几个线程共享相同的地址空间(以及其他东西,如当前目录、打开的文件描述符等)。另请阅读一些POSIX线程(也称为pthread)教程。每个线程都有自己的调用堆栈。

请注意,由于ASLR的原因,地址可能无法从一次运行复制到下一次运行。

Linux内核有一个处理任务的调度器。计划任务是一个线程或(单线程)进程。调度器可以在任意时刻抢占任务,在多核处理器上,您可能有多个任务并行运行(在不同的核上)。

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

您还可以使用strace(1),或者尝试strace a.out查看相关的系统调用(2)。

当然,请多次阅读fork(2)和execve(2)的文档

由于bashshell是免费软件,您可以研究它的源代码。它确实经常调用fork

最新更新