Преимущество различных разделов данных в c [duplicate]

Вы можете попытаться сделать это с помощью выражения Func .

from django.db.models import Func, Sum

AModel.objects.annotate(cumsum=Func(Sum('a_number'), template='%(expressions)s OVER (PARTITION BY %(partition_by)s)', partition_by='id')).values('id', 'cumsum').order_by('id')

13
задан Angus 16 May 2013 в 06:02
поделиться

2 ответа

Секция .bss гарантируется, что все нули при загрузке программы в память. Поэтому любые глобальные данные, которые не инициализируются или инициализируются нулем, помещаются в раздел .bss. Например:

static int g_myGlobal = 0;     // <--- in .bss section

Приятная часть этого вопроса состоит в том, что данные раздела .bss не обязательно должны быть включены в файл ELF на диске (т. Е. Нет целого региона нули в файле для раздела .bss). Вместо этого загрузчик знает из заголовков секций, сколько выделяется для секции .bss, и просто обнуляет его, прежде чем передавать управление вашей программе.

Обратите внимание на вывод readelf:

[ 3] .data PROGBITS 00000000 000110 000000 00 WA 0 0 4
[ 4] .bss NOBITS 00000000 000110 000000 00 WA 0 0 4

.data отмечен как PROGBITS. Это означает, что в файле ELF есть «бит» программных данных, которые загрузчик должен прочитать в памяти для вас. .bss, с другой стороны, отмечено NOBITS, что означает, что в файле нет ничего, что должно быть прочитано в память как часть нагрузки.


Пример:

// bss.c
static int g_myGlobal = 0;

int main(int argc, char** argv)
{
   return 0;
}

Скомпилируйте его с помощью $ gcc -m32 -Xlinker -Map=bss.map -o bss bss.c

Посмотрите на заголовки разделов с $ readelf -S bss

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
   :
  [13] .text             PROGBITS        080482d0 0002d0 000174 00  AX  0   0 16
   :
  [24] .data             PROGBITS        0804964c 00064c 000004 00  WA  0   0  4
  [25] .bss              NOBITS          08049650 000650 000008 00  WA  0   0  4
   :

Теперь мы ищем нашу переменную в таблице символов: $ readelf -s bss | grep g_myGlobal

37: 08049654     4 OBJECT  LOCAL  DEFAULT   25 g_myGlobal

Обратите внимание, что g_myGlobal показано как часть раздела 25. Если мы оглянемся назад в заголовках раздела, мы увидим, что 25 .bss.


Чтобы ответить на ваш реальный вопрос:

Здесь, в приведенной выше программе, я не имею никаких неинсталлированных данных, но BSS занял 8 байтов. Почему он занимает 8 байтов?

Продолжая мой пример, мы ищем любой символ в разделе 25:

$ readelf -s bss | grep 25
     9: 0804825c     0 SECTION LOCAL  DEFAULT    9 
    25: 08049650     0 SECTION LOCAL  DEFAULT   25 
    32: 08049650     1 OBJECT  LOCAL  DEFAULT   25 completed.5745
    37: 08049654     4 OBJECT  LOCAL  DEFAULT   25 g_myGlobal

Третий столбец - это размер. Мы видим наш ожидаемый 4-байтовый g_myGlobal, и этот 1-байтовый completed.5745. Это, вероятно, функция-статическая переменная где-то в инициализации времени выполнения C - помните, что много «вещей» происходит до того, как main() когда-либо называется.

4 + 1 = 5 байт. Однако, если мы оглянемся на заголовок секции .bss, мы увидим, что последний столбец Al равен 4. Это выравнивание раздела, то есть этот раздел при загрузке всегда будет кратным 4 байтам. Следующий множественный из 5 - 8, поэтому раздел .bss - 8 байтов.


Дополнительно Мы можем посмотреть файл карты, сгенерированный компоновщиком, чтобы увидеть, какие объектные файлы были размещены где в конечном выходе.

.bss            0x0000000008049650        0x8
 *(.dynbss)
 .dynbss        0x0000000000000000        0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crt1.o
 *(.bss .bss.* .gnu.linkonce.b.*)
 .bss           0x0000000008049650        0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crt1.o
 .bss           0x0000000008049650        0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crti.o
 .bss           0x0000000008049650        0x1 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/32/crtbegin.o
 .bss           0x0000000008049654        0x4 /tmp/ccKF6q1g.o
 .bss           0x0000000008049658        0x0 /usr/lib/libc_nonshared.a(elf-init.oS)
 .bss           0x0000000008049658        0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/32/crtend.o
 .bss           0x0000000008049658        0x0 /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../lib/crtn.o

Опять же, третий столбец является размером.

Мы видим, что 4 байта .bss взяты из /tmp/ccKF6q1g.o. В этом тривиальном примере мы знаем, что это временный объектный файл из компиляции нашего файла bss.c. Другой 1 байт пришел из crtbegin.o, который является частью среды выполнения C.


Наконец, поскольку мы знаем, что эта 1 байтовая тайна bss-переменной равна crtbegin.o, и она называется completed.xxxx, это настоящее имя completed, и это, вероятно, статичность внутри некоторой функции. Глядя на crtstuff.c , мы находим виновника: a static _Bool completed внутри __do_global_dtors_aux().

33
ответ дан Jonathon Reinhart 22 August 2018 в 21:30
поделиться
  • 1
    Я бы не инициализировал пример static int g_myGlobal; - чтобы он дошел до .bss - и он должен использоваться в коде, иначе компилятор мог бы оптимизировать, полностью удалив его. – Basile Starynkevitch 15 May 2013 в 06:51
  • 2
    @BasileStarynkevitch Увольнение моего Linux VM прямо сейчас .... – Jonathon Reinhart 15 May 2013 в 06:52
  • 3
    Скорее всего, .bss исходит из некоторой внутренней переменной в включенных стандартных библиотеках, возможно, из printf. Именно поэтому printf и др. Не являются потокобезопасными. – Lundin 15 May 2013 в 07:25
  • 4
    @Lundin printf будет частью libc, который динамически связан, поэтому его bss не будет отображаться в этом исполняемом файле. Кроме того, я не могу думать ни о какой причине printf, в частности, будет поддерживать любое состояние. – Jonathon Reinhart 15 May 2013 в 07:26
  • 5
    @Lundin Кроме того, я явно показал, что другой 1 байт был из crtbegin.o. Некоторый минимальный код запуска CRT всегда будет статически связан. – Jonathon Reinhart 15 May 2013 в 07:28

По определению сегмент bss занимает какое-то место в памяти (когда программа запускается), но не требует никакого дискового пространства. Вам нужно определить некоторую переменную, чтобы заполнить ее, поэтому попробуйте

int bigvar_in_bss[16300];
int var_in_data[5] = {1,2,3,4,5};

. Ваша простая программа может не иметь никаких данных в .bss, а общие библиотеки (например, libc.so) могут иметь свои собственные .bss "

Смещение файлов и адреса памяти нелегко связаны.

Подробнее о спецификации ELF , также используйте /proc/ (например, cat /proc/self/maps будет отображать адресное пространство процесса cat, выполняющего эту команду). Читайте также proc (5)

2
ответ дан Basile Starynkevitch 22 August 2018 в 21:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: