我有一个基本的疑问。 我有一个使用共享库的进程。如果我在库 中分配了一些内存,那么它是哪个地址空间。 (Library or Process) 在我看来,它是进程地址空间,因为一旦连接了库,它都在进程地址空间中。地址空间库或进程
如果我错了,请纠正我。
感谢 Arpit
我有一个基本的疑问。 我有一个使用共享库的进程。如果我在库 中分配了一些内存,那么它是哪个地址空间。 (Library or Process) 在我看来,它是进程地址空间,因为一旦连接了库,它都在进程地址空间中。地址空间库或进程
如果我错了,请纠正我。
感谢 Arpit
库没有自己的地址空间。它映射到某个进程并在其中执行。所以你是对的。共享库的内存分配在正在使用它的进程内完成。
这听起来像你可能会在地址空间和堆之间感到困惑。
进程只有一个地址空间,一个进程中的所有内容(主可执行文件,任何共享库和任何静态库)都共享单个地址空间。尽管可能在单个地址空间中存在多个堆,但glibc的实现方式是只有一个标准堆(标准堆,我指的是通过malloc/free访问的堆)。这不同于Windows,可执行文件和dll可能都有自己的堆(尽管同样是共享一个地址空间)。
库本身没有内存空间,因为它不是正在运行的进程。共享库的概念是共享代码指令的副本,但不包含该代码使用或生成的任何数据。
因此,例如,如果你的库是用来管理一个动态分配的结构:
object.h
struct object_struct {
char *name;
int foo;
int bar;
};
typedef struct object_struct * object_t; /* opaque pointer */
object_t new_object (char *name, int foo, int bar);
void delete_object(object_t);
int dump_object(object_t);
object.c
#include <stdio.h>
#include "object.h"
object_t new_object (char *_name, int foo, int bar) {
object_t _p = malloc(sizeof(object_t);
if (!_p)
return NULL;
_p->foo = foo; _p->bar = bar;
_p->name = strdup(_name);
return _p;
}
void delete_object(object_t p) {
if(_p->name)
free(_p->name);
if(_p)
free(_p);
}
int dump_object(object_t p) {
FILE * fp = fopen(p->name, "w");
if (!fp)
return -1;
fprintf(fp, "foo: %d\nbar: %d\n", p->foo, p->bar);
fclose(fp);
return 0;
}
而且你两个程序consumer1.c和consumer2.c使用该库对象,如下所示:
consumer1.c
#include "object.h"
int main() {
object_t o = new_object("consumer1.txt", 1, 2);
dump_object(o);
delete_object(o);
return 0;
}
consumer2.c
#include "object.h"
int main() {
object_t o = new_object("consumer2.txt", 1, 2);
dump_object(o);
delete_object(o);
return 0;
}
对所有意图和目的,对象库的这两个节目不会有任何共同的数据或共同记忆或公共空间。
P.S .:假设gcc和gnu make,这里有一个make文件供你测试一切。
的Makefile
default: libobject.a consumer1 consumer2
.c.o: %.c
$(CC) -c -o [email protected] $<
libobject.a: object.o
$(AR) r [email protected] object.o
object.o: object.c object.h
consumer1 consumer2: [email protected] libobject.a
$(CC) -o [email protected] [email protected] -L. -lobject
P.P.S:这是作为仅作为参考!我还没有在这里测试过代码,希望它一切顺利,但是,如果我犯了语法错误,请适当修复。
共享库可以链接许多进程,并在这些进程的上下文中运行。
假设你有一个共享库来发送http请求。浏览器进程和桌面应用程序都可以与该库链接,但是进程上下文将使它们能够发送独立请求,尽管它们都加载了相同的库。
因此,进程上下文决定内存分配,无论它在哪里写入(进程或库)。