有两个程序A和B,它们都使用了同一个动态库。
先运行程序A,程序A调用动态库中的 X函数 进行初始化,被初始化的是动态库中的一个全局变量,这个全局变量是个结构体,记录着某些有用的数据,如果 X函数 再次被调用,那么就对这个结构体中的成员变量的值进行修改。
在程序A里打开程序B,但不是直接调用system之类的函数运行这个程序,而是先创建一个线程,在这个线程内,使用某种方式,类似于dlopen函数和dlsym函数一样,打开程序B的可执行文件,获取函数指针,这个函数指针就是指向程序B的main函数;
程序B作为程序A的子线程运行,子线程中运行的程序B的main函数也会调用动态库中的 X函数 进行初始化,被调用两次的 X函数 所使用的是不是同一个全局变量?
主要是想实现多个进程间的变量共享,这个变量是一个结构体A,结构体A中有指针数组,指针数组中每个指针指向每个进程的结构体B,而结构体B中也有指针,指针由该进程使用的malloc之类的函数申请了不定量的内存空间,用于储存数据。
但是,网上搜索到的相关资料,有的是说多进程间不能共享指针,因为指针指向的内存空间是属于一个进程的,其它进程不能使用这个指针访问其它进程中的数据。
51 个解决方案
#1
不是很懂 帮顶
#2
#3
#4
理论是应该是同一个全局变量。
可以写两个程序验证一下!
可以写两个程序验证一下!
#5
当然可以 如果你编写的是c语言 你可以编写好一个.h文件的函数,把它放到c的.h目录下,然后用#include"yourself.h"进行引用
#6
#7
remote procedure call
#8
可是,这“ 某种方式”未知, dlopen函数和dlsym函数是用于打开动态链接库并获取指定函数指针的,不知道可不可以获取可执行文件中的main函数的函数指针。
#9
我觉得不可以,每个进程都有自己的代码段、数据段和栈吧,这个代码段或许会重合(这个我不确定),但数据段、栈是不可能共享的,要不然这进程间通讯的机制是不是太儿戏了。
#10
动态库里面的函数都是可以重定位的, 不知道main可不可以重定位, 如果可以, 理论上来说就和库里面的一样了
#11
看来不行,gcc -shared生成的动态库不能直接执行,但是不加-shared生成的执行文件用dlopen会失败。
不知道在Windows下可不可以。
#12
使用进程间通信(IPC),解决方案有很多种。
远程进程调用(remote procedure call)可以实现一个进程对另外一个进程数据读写,以下为远程进程调用需要用到的函数:
OpenProcess,VirtualAllocEx,WriteProcess,ReadProcessMemory,CreateRemoteThread
windows中有消息机制可以从一个程序通知另外一个程序信息。
但是所有的解决方案都需要对数据进行同步,CreateEvent,或者CreateMute可以实现多进程之间对同一数据同步。
以上。
远程进程调用(remote procedure call)可以实现一个进程对另外一个进程数据读写,以下为远程进程调用需要用到的函数:
OpenProcess,VirtualAllocEx,WriteProcess,ReadProcessMemory,CreateRemoteThread
windows中有消息机制可以从一个程序通知另外一个程序信息。
但是所有的解决方案都需要对数据进行同步,CreateEvent,或者CreateMute可以实现多进程之间对同一数据同步。
以上。
#13
那么,可不可以将 程序A 作为一个软件平台,而 程序B 就作为这个平台的一个软件,把 程序B 编译成动态库,没有main函数,但里面有个my_mian函数,供该平台在打开 程序B 时调用。
浏览器之类的软件的插件是不是这个原理?
#14
linux系统环境下该用什么函数呢?
#15
#16
把B封装成库当然可以了,A加载B后,同属一个进程空间。
不过IPC不是有很多办法吗
#17
肯定是不行的。
两个进程,其地址空间都是独立的,看变量名字相同,其内存地址可不一样的。
两个进程,其地址空间都是独立的,看变量名字相同,其内存地址可不一样的。
#18
开线程调用程序B中的函数,那么就是一个进程运行两个程序。
#19
IPC有很多办法???
请指教!!
#20
答复是很肯定的,不是同一个变量,只是同一套代码而已。正如你的一个程序运行两次,就相当于起了两个进程,这两个进程里的全局变量是没有关系的。进程之间通信还是需要使用IPC的。
IPC的方法很多,比如socket,命名管道,共享内存,消息队列,等等。
IPC的方法很多,比如socket,命名管道,共享内存,消息队列,等等。
#21
我说的是程序A的进程开一个子线程,把程序B当成动态库一样,调用里面的函数,而不是开子进程运行程序B。
#22
怎么都把我说的理解成了:程序A将程序B作为一个新的进程运行?
我表达的是:程序A 是一个进程,在程序A里调用程序B,程序A 会创建一个线程,在这个线程里,像调用动态库中的函数一样调用 程序B 中的main函数,由于全局变量可以在线程间共享,那么在线程中调用的函数应该也能使用 程序A 的进程中的全局变量。
如果不是在程序A里调用程序B,而是直接运行程序B的可执行文件,那么程序B就是一个新进程。
#23
请看1楼下半部分的内容:
但是,网上搜索到的相关资料,有的是说多进程间不能共享指针,因为指针指向的内存空间是属于一个进程的,其它进程不能使用这个指针访问其它进程中的数据。
#24
1、如你所说,这个问题就不是一个多进程的问题,仍然是一个进程。那么一个进程内部,所有线程的地址空间共享,全局变量自然能共用。
2、main函数估计不成,一个进程只能有一个main函数。
#25
网上的说法没有问题。进程和线程之间的区别,其实就是进程之间地址空间相互独立,而线程共用同一个地址空间。
也就是说进程A的一个指针(或地址),在进程B中没有任何意义。
还是不明白你究竟想干什么?
#26
可以改变程序B的main函数名称为my_main之类的,然后程序A在线程里使用my_main函数的函数指针来调用它。
#27
我想知道那些用qt、gtk等实现的图形界面系统是如何管理各个程序显示的窗口的,又如何获取它们的图形数据并绘制到屏幕上的?这个图形界面系统应该有个核心程序,主要是用于统一绘制多个程序的界面,并能进行管理。
#28
除非设置共享数据段,否则,所有的动态链接库中的全局变量,都会自己的进程空间拷贝一份副本
也就是说,这这种情况下每个进程看到的全局变量,是互相独立的
对于*nix平台,共享数据段只有偶尔几个平台支持,对于windows平台,可以设置seg_share来实现。
也就是说,这这种情况下每个进程看到的全局变量,是互相独立的
对于*nix平台,共享数据段只有偶尔几个平台支持,对于windows平台,可以设置seg_share来实现。
#29
不懂图形界面系统是怎么实现的。但我觉得肯定不是使用全局变量进行访问的。你想想看,数十个进程并发的访问同一个全局变量,来显示自己,这需要多强的一套冲突处理机制啊!
我觉得这样做简单一些。界面显示系统,提供绘制界面的服务,从一个固定的消息队列中接收消息,并根据消息的内容绘图;其他进程使用这种服务,把要绘制的内容组织成消息,放到消息队列中。
我觉得这样做简单一些。界面显示系统,提供绘制界面的服务,从一个固定的消息队列中接收消息,并根据消息的内容绘图;其他进程使用这种服务,把要绘制的内容组织成消息,放到消息队列中。
#30
嗯,实现消息队列,里面描述如何绘制界面,让界面显示系统来绘制。
#31
不过win32k子系统很多地方就是用的一个全局变量记录当前线程,所以进去就得加锁,包括user和gdi
#32
可是分析消息并做相应的工作有点困难,消息种类、以及相关的参数,统一用一个函数将消息添加至队列,统一用一个函数分析消息,并调用相关函数实现。
话说,可以用函数指针,用一个结构体存储“消息”,第一个成员变量是个函数指针,第二个表示该函数的参数个数,第三个就是指向该函数的不定参数列表的指针。
在主循环里处理“消息”时,直接调用函数指针指向的函数,并传递不定参数。
不知这样是否可行。
#33
那么为什么 B 不直接做成一个 .so 供动态调用?
#34
但是我又想让程序A和B都可以直接运行。
#35
不可行,你还是想用指针,进程A里的指针在进程B里是没有意义的。。。。。
你可以在程序B里,对绘图函数进行编号function_id;进程A给B发消息,把function_id给发过去,进程B根据编号,调用不同的绘图函数。
#36
B 的功能写成一个 .so,然后另外写一个进程包装在这个 .so 外面供单独调用。
#37
#38
《程序员的自我修养——链接、装载与库》
使用数据和代码分离技术
进程间共享数据的最简单方法是利用共享临时文本文件。
使用数据和代码分离技术
进程间共享数据的最简单方法是利用共享临时文本文件。
#39
可是想共享指针呢?这个指针经过malloc之类的函数分配过不定量的内存空间。
#40
函数指针也是指针,我把这个给忘了。。。
#41
表情选错了。
#42
两个进程共享二进制内存
复杂,共享临时文本文件
简单。
凡是能用二进制内存表示的信息,一定可以用文本文件表示。
查看一段二进制内存的值以及解释其意义 难,查看共享临时文本文件的内容以及解释其意义 易。
何去何从楼主自便。
凡是能用二进制内存表示的信息,一定可以用文本文件表示。
查看一段二进制内存的值以及解释其意义 难,查看共享临时文本文件的内容以及解释其意义 易。
何去何从楼主自便。
#43
提醒:共享临时文件还能跨机甚至越洋呢!
#44
你先确定你把一个exe的main函数作为一个线程函数来运行能不能陈功再问这个问题吧。
#45
那只有使用动态库了,把这些程序作为主程序的插件,运行主程序后,就可以在主程序里使用这些程序的功能。
#46
对啊。 那你何必还要把B写成exe然后在拐几个弯子去找main函数呢?
可以告诉你 你要是直接找exe函数,就算你找到了,也是不可能当作线程来运行的。
除非你自己在A中实现一个PE Loader负责把B.exe的相关段载入到内存的合适位置。
不过这还是不能保证B就是以一个线程来运行。。
不知道你为啥非要这样来做。
用动态库才是解决你这个问题的标准解决方案。
如果要保证所有加载此动态库的进程都共享这一个变量
请使用
#pragma data_seg (".shared")
int sharedbar = 0;//共享数据
#pragma data_seg()
#pragma comment(linker,"/SECTION:.shared,RWS")
#47
之前是想自己实现GUI系统,本以为使用同一动态库的多个程序,可以共享动态库中的全局变量。
于是就写代码。。。
直到最近才领悟到,动态库并没有这个功能,之前为实现GUI,是直接用全局变量(一个结构体)记录每个程序相关的数据(窗口排列顺序之类的),而每个程序在进入主循环后,只负责生成界面图形,显示图形的话,会有一个线程专门来处理图形显示,全局变量中通过指针来使用每个程序生成的界面图形,也就是通过使用相应的指针来将每个程序储存的图形数据绘制到屏幕上。
由于多个程序使用的同一动态库中的全局变量不是同一个,那么它们绘制的图形都会互相干扰,因为都是各做各的事,并不知道还有其它程序显示了界面。
为了让代码修改量尽量少,于是就有了1楼描述的想法,程序在调用库中的函数初始化,初始化时会将该程序记录到全局变量中,如果该程序是第一个初始化的,那么就设定它为本GUI的“核心”程序,并且,在该“核心”程序中调用其它程序,就会创建一个线程,并调用程序中的函数,由于线程是共享全局变量的,那么图形就会被正常绘制到屏幕上。
但是,还没有写出适合成为“核心”的程序,我之前是想写个桌面,把这个桌面作为程序运行平台,现在觉得代码量大,费时长,就先写些基础程序,把桌面的放到后面,以后写。
如果不是在GUI的“核心”程序里调用程序,那么就无法运行,因为它是个动态库,
于是想让它们都可以成为可执行文件,可以单独运行,也可以在以后编写完成的桌面上能正常运行。
其实就是为了让多个程序在显示图形界面时,能正常显示,不被干扰。
#48
动态库是有这个功能的。至少在windows系统下是有的。
具体实现已经给你贴了代码了。
#pragma data_seg (".shared")
int sharedvar = 0;//共享数据
#pragma data_seg()
#pragma comment(linker,"/SECTION:.shared,RWS")
把系统级别的全局变量单独定义在一个数据段中。系统中的所有进程加载这个动态库之后所访问的sharevar都会是这一个。
注意这里的全局是相对整个系统中加载了这个模块的进程而言,而不单单是加载了这个模块的一个进程的进程空间
#49
你的需求要每一个独立的模块都能单独运行那就编译成exe然后在你的桌面里面创建进程吧。。然后就是IPC了。
#50
进程是独立的,进程A和进程B的内存空间都是独立存在的.他们之间是是不能互相访问的.
共享库可能在内存中只有一个拷贝.但是共享库里面的全局变量却在各个进程中独立存在.
共享库可能在内存中只有一个拷贝.但是共享库里面的全局变量却在各个进程中独立存在.
#1
不是很懂 帮顶
#2
#3
#4
理论是应该是同一个全局变量。
可以写两个程序验证一下!
可以写两个程序验证一下!
#5
当然可以 如果你编写的是c语言 你可以编写好一个.h文件的函数,把它放到c的.h目录下,然后用#include"yourself.h"进行引用
#6
#7
remote procedure call
#8
可是,这“ 某种方式”未知, dlopen函数和dlsym函数是用于打开动态链接库并获取指定函数指针的,不知道可不可以获取可执行文件中的main函数的函数指针。
#9
我觉得不可以,每个进程都有自己的代码段、数据段和栈吧,这个代码段或许会重合(这个我不确定),但数据段、栈是不可能共享的,要不然这进程间通讯的机制是不是太儿戏了。
#10
动态库里面的函数都是可以重定位的, 不知道main可不可以重定位, 如果可以, 理论上来说就和库里面的一样了
#11
看来不行,gcc -shared生成的动态库不能直接执行,但是不加-shared生成的执行文件用dlopen会失败。
不知道在Windows下可不可以。
#12
使用进程间通信(IPC),解决方案有很多种。
远程进程调用(remote procedure call)可以实现一个进程对另外一个进程数据读写,以下为远程进程调用需要用到的函数:
OpenProcess,VirtualAllocEx,WriteProcess,ReadProcessMemory,CreateRemoteThread
windows中有消息机制可以从一个程序通知另外一个程序信息。
但是所有的解决方案都需要对数据进行同步,CreateEvent,或者CreateMute可以实现多进程之间对同一数据同步。
以上。
远程进程调用(remote procedure call)可以实现一个进程对另外一个进程数据读写,以下为远程进程调用需要用到的函数:
OpenProcess,VirtualAllocEx,WriteProcess,ReadProcessMemory,CreateRemoteThread
windows中有消息机制可以从一个程序通知另外一个程序信息。
但是所有的解决方案都需要对数据进行同步,CreateEvent,或者CreateMute可以实现多进程之间对同一数据同步。
以上。
#13
那么,可不可以将 程序A 作为一个软件平台,而 程序B 就作为这个平台的一个软件,把 程序B 编译成动态库,没有main函数,但里面有个my_mian函数,供该平台在打开 程序B 时调用。
浏览器之类的软件的插件是不是这个原理?
#14
linux系统环境下该用什么函数呢?
#15
#16
把B封装成库当然可以了,A加载B后,同属一个进程空间。
不过IPC不是有很多办法吗
#17
肯定是不行的。
两个进程,其地址空间都是独立的,看变量名字相同,其内存地址可不一样的。
两个进程,其地址空间都是独立的,看变量名字相同,其内存地址可不一样的。
#18
开线程调用程序B中的函数,那么就是一个进程运行两个程序。
#19
IPC有很多办法???
请指教!!
#20
答复是很肯定的,不是同一个变量,只是同一套代码而已。正如你的一个程序运行两次,就相当于起了两个进程,这两个进程里的全局变量是没有关系的。进程之间通信还是需要使用IPC的。
IPC的方法很多,比如socket,命名管道,共享内存,消息队列,等等。
IPC的方法很多,比如socket,命名管道,共享内存,消息队列,等等。
#21
我说的是程序A的进程开一个子线程,把程序B当成动态库一样,调用里面的函数,而不是开子进程运行程序B。
#22
怎么都把我说的理解成了:程序A将程序B作为一个新的进程运行?
我表达的是:程序A 是一个进程,在程序A里调用程序B,程序A 会创建一个线程,在这个线程里,像调用动态库中的函数一样调用 程序B 中的main函数,由于全局变量可以在线程间共享,那么在线程中调用的函数应该也能使用 程序A 的进程中的全局变量。
如果不是在程序A里调用程序B,而是直接运行程序B的可执行文件,那么程序B就是一个新进程。
#23
请看1楼下半部分的内容:
但是,网上搜索到的相关资料,有的是说多进程间不能共享指针,因为指针指向的内存空间是属于一个进程的,其它进程不能使用这个指针访问其它进程中的数据。
#24
1、如你所说,这个问题就不是一个多进程的问题,仍然是一个进程。那么一个进程内部,所有线程的地址空间共享,全局变量自然能共用。
2、main函数估计不成,一个进程只能有一个main函数。
#25
网上的说法没有问题。进程和线程之间的区别,其实就是进程之间地址空间相互独立,而线程共用同一个地址空间。
也就是说进程A的一个指针(或地址),在进程B中没有任何意义。
还是不明白你究竟想干什么?
#26
可以改变程序B的main函数名称为my_main之类的,然后程序A在线程里使用my_main函数的函数指针来调用它。
#27
我想知道那些用qt、gtk等实现的图形界面系统是如何管理各个程序显示的窗口的,又如何获取它们的图形数据并绘制到屏幕上的?这个图形界面系统应该有个核心程序,主要是用于统一绘制多个程序的界面,并能进行管理。
#28
除非设置共享数据段,否则,所有的动态链接库中的全局变量,都会自己的进程空间拷贝一份副本
也就是说,这这种情况下每个进程看到的全局变量,是互相独立的
对于*nix平台,共享数据段只有偶尔几个平台支持,对于windows平台,可以设置seg_share来实现。
也就是说,这这种情况下每个进程看到的全局变量,是互相独立的
对于*nix平台,共享数据段只有偶尔几个平台支持,对于windows平台,可以设置seg_share来实现。
#29
不懂图形界面系统是怎么实现的。但我觉得肯定不是使用全局变量进行访问的。你想想看,数十个进程并发的访问同一个全局变量,来显示自己,这需要多强的一套冲突处理机制啊!
我觉得这样做简单一些。界面显示系统,提供绘制界面的服务,从一个固定的消息队列中接收消息,并根据消息的内容绘图;其他进程使用这种服务,把要绘制的内容组织成消息,放到消息队列中。
我觉得这样做简单一些。界面显示系统,提供绘制界面的服务,从一个固定的消息队列中接收消息,并根据消息的内容绘图;其他进程使用这种服务,把要绘制的内容组织成消息,放到消息队列中。
#30
嗯,实现消息队列,里面描述如何绘制界面,让界面显示系统来绘制。
#31
不过win32k子系统很多地方就是用的一个全局变量记录当前线程,所以进去就得加锁,包括user和gdi
#32
可是分析消息并做相应的工作有点困难,消息种类、以及相关的参数,统一用一个函数将消息添加至队列,统一用一个函数分析消息,并调用相关函数实现。
话说,可以用函数指针,用一个结构体存储“消息”,第一个成员变量是个函数指针,第二个表示该函数的参数个数,第三个就是指向该函数的不定参数列表的指针。
在主循环里处理“消息”时,直接调用函数指针指向的函数,并传递不定参数。
不知这样是否可行。
#33
那么为什么 B 不直接做成一个 .so 供动态调用?
#34
但是我又想让程序A和B都可以直接运行。
#35
不可行,你还是想用指针,进程A里的指针在进程B里是没有意义的。。。。。
你可以在程序B里,对绘图函数进行编号function_id;进程A给B发消息,把function_id给发过去,进程B根据编号,调用不同的绘图函数。
#36
B 的功能写成一个 .so,然后另外写一个进程包装在这个 .so 外面供单独调用。
#37
#38
《程序员的自我修养——链接、装载与库》
使用数据和代码分离技术
进程间共享数据的最简单方法是利用共享临时文本文件。
使用数据和代码分离技术
进程间共享数据的最简单方法是利用共享临时文本文件。
#39
可是想共享指针呢?这个指针经过malloc之类的函数分配过不定量的内存空间。
#40
函数指针也是指针,我把这个给忘了。。。
#41
表情选错了。
#42
两个进程共享二进制内存
复杂,共享临时文本文件
简单。
凡是能用二进制内存表示的信息,一定可以用文本文件表示。
查看一段二进制内存的值以及解释其意义 难,查看共享临时文本文件的内容以及解释其意义 易。
何去何从楼主自便。
凡是能用二进制内存表示的信息,一定可以用文本文件表示。
查看一段二进制内存的值以及解释其意义 难,查看共享临时文本文件的内容以及解释其意义 易。
何去何从楼主自便。
#43
提醒:共享临时文件还能跨机甚至越洋呢!
#44
你先确定你把一个exe的main函数作为一个线程函数来运行能不能陈功再问这个问题吧。
#45
那只有使用动态库了,把这些程序作为主程序的插件,运行主程序后,就可以在主程序里使用这些程序的功能。
#46
对啊。 那你何必还要把B写成exe然后在拐几个弯子去找main函数呢?
可以告诉你 你要是直接找exe函数,就算你找到了,也是不可能当作线程来运行的。
除非你自己在A中实现一个PE Loader负责把B.exe的相关段载入到内存的合适位置。
不过这还是不能保证B就是以一个线程来运行。。
不知道你为啥非要这样来做。
用动态库才是解决你这个问题的标准解决方案。
如果要保证所有加载此动态库的进程都共享这一个变量
请使用
#pragma data_seg (".shared")
int sharedbar = 0;//共享数据
#pragma data_seg()
#pragma comment(linker,"/SECTION:.shared,RWS")
#47
之前是想自己实现GUI系统,本以为使用同一动态库的多个程序,可以共享动态库中的全局变量。
于是就写代码。。。
直到最近才领悟到,动态库并没有这个功能,之前为实现GUI,是直接用全局变量(一个结构体)记录每个程序相关的数据(窗口排列顺序之类的),而每个程序在进入主循环后,只负责生成界面图形,显示图形的话,会有一个线程专门来处理图形显示,全局变量中通过指针来使用每个程序生成的界面图形,也就是通过使用相应的指针来将每个程序储存的图形数据绘制到屏幕上。
由于多个程序使用的同一动态库中的全局变量不是同一个,那么它们绘制的图形都会互相干扰,因为都是各做各的事,并不知道还有其它程序显示了界面。
为了让代码修改量尽量少,于是就有了1楼描述的想法,程序在调用库中的函数初始化,初始化时会将该程序记录到全局变量中,如果该程序是第一个初始化的,那么就设定它为本GUI的“核心”程序,并且,在该“核心”程序中调用其它程序,就会创建一个线程,并调用程序中的函数,由于线程是共享全局变量的,那么图形就会被正常绘制到屏幕上。
但是,还没有写出适合成为“核心”的程序,我之前是想写个桌面,把这个桌面作为程序运行平台,现在觉得代码量大,费时长,就先写些基础程序,把桌面的放到后面,以后写。
如果不是在GUI的“核心”程序里调用程序,那么就无法运行,因为它是个动态库,
于是想让它们都可以成为可执行文件,可以单独运行,也可以在以后编写完成的桌面上能正常运行。
其实就是为了让多个程序在显示图形界面时,能正常显示,不被干扰。
#48
动态库是有这个功能的。至少在windows系统下是有的。
具体实现已经给你贴了代码了。
#pragma data_seg (".shared")
int sharedvar = 0;//共享数据
#pragma data_seg()
#pragma comment(linker,"/SECTION:.shared,RWS")
把系统级别的全局变量单独定义在一个数据段中。系统中的所有进程加载这个动态库之后所访问的sharevar都会是这一个。
注意这里的全局是相对整个系统中加载了这个模块的进程而言,而不单单是加载了这个模块的一个进程的进程空间
#49
你的需求要每一个独立的模块都能单独运行那就编译成exe然后在你的桌面里面创建进程吧。。然后就是IPC了。
#50
进程是独立的,进程A和进程B的内存空间都是独立存在的.他们之间是是不能互相访问的.
共享库可能在内存中只有一个拷贝.但是共享库里面的全局变量却在各个进程中独立存在.
共享库可能在内存中只有一个拷贝.但是共享库里面的全局变量却在各个进程中独立存在.