Как узнать, что происходит до перехода компьютера в спящий режим и во время него?

Я считаю, что на самом деле краткий ответ заключается в том, что компиляторы Linux разбивают код на части, по крайней мере одна из которых представляет собой чистый код, и поэтому может быть отображена в памяти в адресное пространство более чем одного процесса. Любые глобальные объекты отображаются таким образом, что каждый процесс получает свою собственную копию.

Вы можете увидеть это, используя readelf или objdump , но readelf , я думаю, дает более ясную картину.

Вот фрагмент вывода readelf -e /usr/lib/libc.so.6. Это библиотека C, которая, вероятно, отображается почти во всех процессах. Соответствующая часть вывода readelf (хотя все это интересно) - это заголовки программ:

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x00000034 0x00000034 0x00140 0x00140 R E 0x4
  INTERP         0x164668 0x00164668 0x00164668 0x00017 0x00017 R   0x4
      [Requesting program interpreter: /usr/lib/ld-linux.so.2]
  LOAD           0x000000 0x00000000 0x00000000 0x1adfc4 0x1adfc4 R E 0x1000
  LOAD           0x1ae220 0x001af220 0x001af220 0x02c94 0x057c4 RW  0x1000
  DYNAMIC        0x1afd90 0x001b0d90 0x001b0d90 0x000f8 0x000f8 RW  0x4
  NOTE           0x000174 0x00000174 0x00000174 0x00044 0x00044 R   0x4
  TLS            0x1ae220 0x001af220 0x001af220 0x00008 0x00048 R   0x4
  GNU_EH_FRAME   0x164680 0x00164680 0x00164680 0x06124 0x06124 R   0x4
  GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RW  0x10
  GNU_RELRO      0x1ae220 0x001af220 0x001af220 0x01de0 0x01de0 R   0x1

Две строки LOAD - единственные части файла, которые отображаются непосредственно в память. Первый заголовок LOAD отображает часть /usr/lib/libc.so.6 в память с разрешениями R и E: чтение и выполнение. Это код.Аппаратные функции предотвращают запись программы в этот фрагмент памяти, поэтому все программы могут совместно использовать одни и те же страницы реальной физической памяти. Ядро может настроить оборудование для отображения одной и той же физической памяти во все процессы.

Второй заголовок LOAD помечен как RW - чтение и запись. Это часть с глобальными переменными, которую использует библиотека C. Каждый процесс получает свою собственную копию в физической памяти, отображаемую в адресное пространство этого процесса с аппаратными разрешениями, установленными для чтения и записи. Этот раздел не является общим.

Вы можете увидеть эти сопоставления памяти в запущенном процессе, используя файловую систему / proc . Хорошая команда для иллюстрации: cat / proc / self / maps . Здесь перечислены все отображения памяти, которые имеет процесс cat , и из каких файлов они были получены ядром.

Что касается того, сколько вам нужно сделать для того, чтобы ваша функция была выделена в память, которая отображается в разные процессы, это в значительной степени зависит от флагов, которые вы передаете компилятору. Код, предназначенный для разделяемых библиотек ".so", компилируется "независимо от позиции". Позиционно-независимый код делает такие вещи, как обращение к ячейкам памяти переменных со смещениями относительно текущей инструкции, а также переходы или переходы к местоположениям относительно текущей инструкции, а не загрузка или запись по абсолютным адресам и переход к абсолютным адресам. Это означает, что часть «RE» ЗАГРУЗКИ /usr/lib/libc.so и часть «RW» должны загружаться только по адресам, которые находятся на одинаковом расстоянии друг от друга в каждом процессе.В вашем примере кода переменная static всегда будет по крайней мере кратной размеру страницы, за исключением кода, который на нее ссылается, и она всегда будет загружаться на этом расстоянии друг от друга в адресном пространстве процесса из-за как даны заголовки LOAD ELF.

Замечание о термине «разделяемая память»: существует система разделяемой памяти пользовательского уровня, связанная с «системой межпроцессного взаимодействия System V». Это способ для нескольких процессов явным образом совместно использовать часть памяти. Это довольно сложно и непонятно настроить и исправить. Общая память, о которой мы здесь говорим, более или менее полностью невидима для любого пользовательского процесса. Ваш примерный код не будет знать разницы, работает ли он как независимый от позиции код, совместно используемый несколькими процессами, или если это единственная копия.

2
04.04.2019, 15:09
1 ответ

Откройте эмулятор терминала и введите sudo dmesgперед приостановкой работы в ОЗУ и запишите самую последнюю отметку времени. Затем приостановите работу в ОЗУ. Если ваш компьютер не просыпается сам по себе, возобновите работу и начните сначала, пока он не проснется сам по себе. Проверьте вывод sudo dmesgеще раз, затем используйте функцию поиска вашего эмулятора терминала(Ctrl + Shift + F ), чтобы найти отметку времени из более раннего. Начните читать оттуда.

1
27.01.2020, 22:17

Теги

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