[英]Should child class override the constructors if they have identical parameter as the parent class?
[英]Why do objects in parent/child processes have identical addresses?
我对以下代码有两个问题:
守则 :
#include <unistd.h>
#include <semaphore.h>
#include <iostream>
int main(int argc, char **argv)
{
sem_t sem;
int var = 0;
/* create, initialize semaphore */
if( sem_init(&sem,1,1) < 0)
{
perror("semaphore initilization");
exit(0);
}
int pid = fork();
static const size_t loopLen = 5;
if (0 == pid)
{ /* child process */
for (size_t i = 0; i < loopLen; ++i)
{
sem_wait(&sem);
std::string str("Child");
std::cout << str << " process: &var(" << (void*)(&var) << ") var(" << var++ << ") &sem(" << (void*)(&sem) << ")" << std::endl;
sem_post(&sem);
}
}
else
{ /* parent process */
for (size_t i = 0; i < loopLen; ++i)
{
sem_wait(&sem);
std::string str("Parent");
std::cout << str << " process: &var(" << (void*)(&var) << ") var(" << var++ << ") &sem(" << (void*)(&sem) << ")" << std::endl;
sem_post(&sem);
}
}
}
输出 :
Parent process: &var(0xffffcbdc) var(0) &sem(0xffffcbe0)
Child process: &var(0xffffcbdc) var(0) &sem(0xffffcbe0)
Parent process: &var(0xffffcbdc) var(1) &sem(0xffffcbe0)
Child process: &var(0xffffcbdc) var(1) &sem(0xffffcbe0)
Parent process: &var(0xffffcbdc) var(2) &sem(0xffffcbe0)
Child process: &var(0xffffcbdc) var(2) &sem(0xffffcbe0)
Parent process: &var(0xffffcbdc) var(3) &sem(0xffffcbe0)
Child process: &var(0xffffcbdc) var(3) &sem(0xffffcbe0)
Parent process: &var(0xffffcbdc) var(4) &sem(0xffffcbe0)
Child process: &var(0xffffcbdc) var(4) &sem(0xffffcbe0)
问题 :
从父进程和子进程打印时,为什么var
和sem
的地址相同? 我知道子进程获取了父内存空间内容的副本 ,但我认为进程有独立且不同的地址空间,因此没有变量会在同一个内存位置 - 但这个输出似乎表明不是这样。
问题 :
这段代码实际上是在同步两个进程吗? 我持怀疑态度。 虽然我用pshared
标志非零调用sem_init
,但它似乎再次是子进程应该获取信号量的副本 。 我没有看到sem
在父进程和子进程之间“共享”的机制:信号量没有命名,我不明白在父进程和子进程之间如何共享信号量。 我怀疑每个进程只是获取并释放自己的信号量“副本”,但我不确定。
谢谢。
关于地址,这是因为子进程最初是父进程的完全重复 。 精确复制包括(虚拟)内存映射。 阅读fork
手册页以获取更多信息。
关于信号量,如果你阅读sem_init
手册页,你会看到
如果
pshared
非零,那么信号量在进程之间共享,并且应该位于共享内存的区域中
这个位于共享内存中的位置由你来处理,但这并不是你自动完成的。
除了SingerOfTheFall的答案之外,我想补充说fork(2)
制作了父进程的精确副本 - 相同的内存映射,相同的信号掩码,相同的文件描述符表 - 所以你实际上得到了你的进程的真实副本。
这些进程确实有不同的地址空间,但是为了理解为什么修改其中一个进程不会影响另一个进程,你应该记住虚拟和物理地址之间的区别以及所有进程(甚至是amd64上的内核)在虚拟地址空间中执行。
长话短说 - 简而言之,CPU中有对应表(称为页表),每当您尝试访问给定地址时,CPU都会查找有问题地址的实际物理地址。 内核为每个进程填充页表,并为每个进程提供相同的地址(如果未启用ASLR)。
我无法确定为什么父母和孩子之间共享信号量,但如果你的初始化是正确的,那么它就不应该从外部世界获得。
参看
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.