源于systemd的例子
先看bus-error.h中的一个宏:
#define BUS_ERROR_MAP_ELF_REGISTER \ __attribute__ ((__section__("BUS_ERROR_MAP"))) \ __attribute__ ((__used__)) \ __attribute__ ((aligned(8)))
意思是将数据定义在BUS_ERROR_MAP段,8字节对齐,标记为已使用的
bus-error.c中定义了一个数组:
BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map bus_standard_errors[] = { SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.Failed", EACCES), SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.NoMemory", ENOMEM), ...... SD_BUS_ERROR_MAP("org.freedesktop.DBus.Error.ObjectPathInUse", EBUSY), SD_BUS_ERROR_MAP_END };
test-bus-error.c中定义了两个数组:
BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors[] = { SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error", 5), SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-2", 52), SD_BUS_ERROR_MAP_END }; BUS_ERROR_MAP_ELF_REGISTER const sd_bus_error_map test_errors2[] = { SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-3", 33), SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-4", 44), SD_BUS_ERROR_MAP("org.freedesktop.custom-dbus-error-33", 333), SD_BUS_ERROR_MAP_END };
如果将bus-error.c编译到动态库,然后test-bus-error.c去连接该动态库,bus-error.c在.so中,有一个BUS_ERROR_MAP段;test-bus-error.c在.exe中,有另一个BUS_ERROR_MAP段,里面只有两个数组。
当使用如下代码打印数组时,就会发现动态连接的输出会少很多(只打印了test-bus-error.c中的两个数组):
extern const sd_bus_error_map __start_BUS_ERROR_MAP[]; extern const sd_bus_error_map __stop_BUS_ERROR_MAP[]; static void dump_mapping_table(void) { const sd_bus_error_map *m; printf("----- errno mappings ------\n"); m = __start_BUS_ERROR_MAP; while (m < __stop_BUS_ERROR_MAP) { if (m->code == BUS_ERROR_MAP_END_MARKER) { m = ALIGN8_PTR(m+1); continue; } printf("%s -> %i/%s\n", strna(m->name), m->code, strna(errno_to_name(m->code))); m ++; } printf("---------------------------\n"); }
__start_BUS_ERROR_MAP和__stop_BUS_ERROR_MAP分别是段BUS_ERROR_MAP的起始和结尾地址,由GCC负责处理。