C 父子线程程序的怪异行为
我对粘贴在下面的程序副本有疑问。我在这里解释我对这个程序的理解:在这个程序中,家长创建一个孩子并等待它完成。然后,子线程创建一个线程并等待它完成。因此,在最后,变量“value”在子进程中的值为“5”,在父进程中的值为“0”,因为实际上变量“value”有两个副本,一个在父进程中,另一个在子进程中(因为fork实际上是将父进程的地址空间复制到子进程)。但是,在父级和子级中变量“value”的地址都是相同的。我不明白怎么做。如果有人能解释这种行为,我将不胜感激C 父子线程程序的怪异行为,c,unix,memory,parent-child,C,Unix,Memory,Parent Child,我对粘贴在下面的程序副本有疑问。我在这里解释我对这个程序的理解:在这个程序中,家长创建一个孩子并等待它完成。然后,子线程创建一个线程并等待它完成。因此,在最后,变量“value”在子进程中的值为“5”,在父进程中的值为“0”,因为实际上变量“value”有两个副本,一个在父进程中,另一个在子进程中(因为fork实际上是将父进程的地址空间复制到子进程)。但是,在父级和子级中变量“value”的地址都是相同的。我不明白怎么做。如果有人能解释这种行为,我将不胜感激 #include <stdio
#include <stdio.h>
#include <pthread.h>
int value = 0;
void *runner( void *param );
int main ()
{
int pid ;
pthread_t tid;
pthread_attr_t attr;
pid = fork();
if( pid == 0 ) /* child */
{
pthread_attr_init( &attr );
pthread_create( &tid, &attr, runner, NULL );
pthread_join(tid, NULL);
printf( "CHILD: value = %d, address = %p\n", value, &value );
}
else if( pid > 0 ) /* Parent */
{
wait(NULL);
printf( "PARENT: value = %d, address = %p\n", value, &value );
}
}
void *runner( void *param )
{
value = 5;
pthread_exit(0);
}
#包括
#包括
int值=0;
void*runner(void*param);
int main()
{
int-pid;
pthread_t tid;
pthread_attr_t attr;
pid=fork();
如果(pid==0)/*子级*/
{
pthread_attr_init(&attr);
pthread_create(&tid,&attr,runner,NULL);
pthread_join(tid,NULL);
printf(“子:值=%d,地址=%p\n”,值,&value);
}
否则,如果(pid>0)/*父级*/
{
等待(空);
printf(“父项:值=%d,地址=%p\n”,值,&value);
}
}
无效*流道(无效*参数)
{
数值=5;
pthread_退出(0);
}
现代操作系统为每个进程提供了一个虚拟地址空间,因此一个重合的地址并不意味着这两个变量存储在物理内存的同一个目标上
此外,大多数操作系统在分叉时使用写时拷贝技术。这意味着父进程的部分地址空间不会复制到子进程的地址空间,直到子进程尝试更改它们。桌面CPU和许多嵌入式CPU都有一种称为内存管理单元(MMU)的东西。MMU将虚拟地址转换为物理地址,因此每个进程在其自己的虚拟地址空间上运行,与其他进程分开 MMU允许操作系统使用一些重要的技术,如按需分页,以及上述进程之间的分离
fork()
的高效实现需要使用MMU:正如您刚刚发现的,父进程和子进程使用相同的虚拟地址,但在不同的虚拟地址空间中,因此通常(忽略内存映射文件和共享内存)映射到不同的物理地址。如果我错了,请纠正我。虚拟地址不应该是唯一的吗?这可能意味着地址0xDEADBEEF
转换为任意两个进程的不同内存位置。这是否意味着程序以某种方式打印偏移量?哪些地址被转换为物理地址?是的,这些是虚拟地址,由CPU转换为物理地址。