【发布时间】:2010-06-29 05:31:16
【问题描述】:
我有一个基本的疑问。 我有一个使用共享库的进程。如果我在库中分配一些内存 那么它是哪个地址空间。 (库或进程) 在我看来,它是进程地址空间,因为一旦附加了库,它就全部在进程地址空间中。
如果我错了,请纠正我。
谢谢 阿皮特
【问题讨论】:
标签: c linux memory shared-libraries
我有一个基本的疑问。 我有一个使用共享库的进程。如果我在库中分配一些内存 那么它是哪个地址空间。 (库或进程) 在我看来,它是进程地址空间,因为一旦附加了库,它就全部在进程地址空间中。
如果我错了,请纠正我。
谢谢 阿皮特
【问题讨论】:
标签: c linux memory shared-libraries
库没有自己的地址空间。它被映射到某个进程中并在其中执行。所以你是对的。共享库的内存分配是在使用它的进程内部完成的。
【讨论】:
听起来您可能对地址空间和堆感到困惑。
一个进程有一个地址空间,进程内的所有东西(主可执行文件、任何共享库和任何静态库)都共享一个地址空间。
虽然在单个地址空间中可能存在多个堆,但 glibc 的实现方式是只有一个标准堆(标准堆,我指的是您通过 malloc/free 访问的堆)。这与 Windows 不同,在 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 文件供你测试。
生成文件
default: libobject.a consumer1 consumer2
.c.o: %.c
$(CC) -c -o $@ $<
libobject.a: object.o
$(AR) r $@ object.o
object.o: object.c object.h
consumer1 consumer2: $@.o libobject.a
$(CC) -o $@ $@.o -L. -lobject
P.P.S:这只是一个指南!我还没有在这里测试过代码,希望它一切顺利,但是,带着一粒盐,如果我犯了语法错误,请适当地修复。
【讨论】:
共享库可以与许多进程链接,并在这些进程的上下文中运行。
假设您有一个共享库来发送 http 请求。浏览器进程和桌面应用程序都可以与该库链接,但进程上下文将使它们能够发送独立的请求,尽管它们都加载了相同的库。
因此进程上下文决定了内存的分配,无论它是写在哪里(进程或库)。
【讨论】: