博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于进程和线程对于全局变量共享的问题学习总结
阅读量:4056 次
发布时间:2019-05-25

本文共 1186 字,大约阅读时间需要 3 分钟。

                             进程和线程的共享

本文档可以说明以下几个问题:

问题一:多进程编程中,不同进程是否可以通过全局变量来通信?

问题二:多线程编程中,不同线程是否可以通过全局变量来通信?

 

在说明这两个问题之前,首先说明对于进程使用的内存的分段结构(高地址--->低地址):

   环境变量:   存放进程的环境变量信息。

   :                临时变量、返回地址、函数入参等。

   堆:                malloc就在这地方申请。

   BSS:        存放未初始化的全局变量,未初始化的静态变量(无论该静态变量在函数内定义还是函数外定义,都存放在这里)。

   数据段(DS):存放初始化过的全局变量,初始化过的静态变量。

   代码段(CS):存放程序的代码。

 

【问题一】

对于兄弟的进程或者父子进程中有一方使用了exec族函数(进程的代码、数据全部被替换,实际使用的物理内存也是重新申请的),进程的代码段、数据段、堆栈段都是独立的,没有任何关系,当然系统会为为他们各自都维护页目录和页表信息(每个进程有自己的页目录和页表)。

对于父子进程,假设我们在代码中定义了一个全局变量g_test =1;当使用fork()系统调用时,子进程使用的页目录和页表是复制父进程的,所有此时父子进程共享所有数据(当然fork()的返回值不一样,信号位图也不一样),所以这个时候父子进程读取全局变量g_test的值以及地址都是一样的,因为g_test是被共享的,g_test这块内存在两个进程的页表中都映射了同一块物理内存。

如果之后父子进程中有一方执行了写操作(比如子进程进行g_test++),子进程在在查找页表时会发现这页内存是共享的(内存引用计数大于1),这时候就触发了写时复制COW机制,系统会为子进程申请一页新内存,并拷贝父进程g_test所在内存页的数据到子进程新申请的内存中,并更新子进程中页表信息(g_test所对应的线性地址映射到新内存),然后再执行g_test++操作。

此时父子进程访问g_test时,虽然变量名一样,变量的线性地址一样(printf(&g_test)),但是他们的值是不一样的,因为这个时候,父子进程的g_test被映射到了不同的物理内存中。

 

【问题二】

首先对于不同进程的线程而言,他们没有什么关系的(代码段、数据段等都不同),所以不能通过全局变量来通信。

但是对于同一进程内的线程,他们是可以通过全局变量来通信的。

同一进程内的线程,他们都共享进程的代码段、数据段、BSS段。页目录和页表应该是使用进程的页目录和页表。

 

对于上面的描述,又产生一个新问题:我们在编写驱动程序的时候,对于全局变量的使用一般都要考虑并发,也就是说这时候全局变量是共享的,这和问题一有出入。

实际上,当进程进入内核执行时,所有进程共享内核的代码段和数据段,所以在内核中,全局变量是共享的,访问时要考虑并发和竞态。(所有进程共享内核的页目录和页表结构)

转载地址:http://zxlci.baihongyu.com/

你可能感兴趣的文章
LED恒流驱动芯片
查看>>
驱动TFT要SDRAM做为显示缓存
查看>>
使用file查看可执行文件的平台性,x86 or arm ?
查看>>
qt 创建异形窗体
查看>>
简单Linux C线程池
查看>>
内存池
查看>>
gstreamer相关工具集合
查看>>
RS232 四入四出模块控制代码
查看>>
linux 驱动开发 头文件
查看>>
container_of()传入结构体中的成员,返回该结构体的首地址
查看>>
ipconfig,ifconfig,iwconfig
查看>>
opensuse12.2 PL2303 minicom
查看>>
网络视频服务器移植
查看>>
Encoding Schemes
查看>>
移植QT
查看>>
如此调用
查看>>
计算机的发展史
查看>>
带WiringPi库的交叉编译如何处理一
查看>>
带WiringPi库的交叉笔译如何处理二之软链接概念
查看>>
Spring事务的七种传播行为
查看>>