Ответы пользователя по тегу Операционные системы
  • Как ос генерируют виртуальные адреса, по которым будет поиск, не физические? Почему программы с одних адресов начинаются?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Почему программы с одних адресов начинаются?

    Потому что часть программ просто линкуется в одни и те же адреса. Это т.н. position-dependent executable, их в принципе невозможно загрузить для исполнения по другому адресу, и до недавнего времени (по крайней мере в linux) это было поведением по умолчанию. Но вот уже лет 10 во многих дистрибутивах по умолчанию используются PIE -- position-independent executables, и если не выключен ASLR, то при каждой загрузке часть адреса выбирается случайно. Но это сделано не для улучшения поведения TLB а для безопасности, поскольку это затрудняет атаки использующие известные адреса загрузки кода.

    Вот есть Tlb, представим это как линейный массив, или c , если все адреса будут одинаковы. То Очевидно что tlb будет работать в 1% своего множества

    Нет, не очевидно. Потому что никто не делает процессоры с пропорциональным отображением всего адресного пространства на все записи TLB. Обычно индексом записи TLB являются младшие биты номера страницы. Т.е. две соседние страницы могут использовать два соседних индекса в TLB, а канал TLB на 256 записей может быть полностью использован всего-то непрерывным мегабайтом памяти в 4-КБайтных страницах.
    Ответ написан
    Комментировать
  • Что планирует ОС - потоки или процессы?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Из всего изученного стало понятно, что процессы - это некие "контейнеры", содержащие id, статус, instruction pointer, значение регистров, открытые файлы и другие данные контекста.

    Вот уже по этому предложению видно, что понятно не стало. instruction pointer и значения регистров -- свои у каждого потока.

    какую роль в планировании играют процессы?

    Никакой.

    Для чего они нужны?

    Для учёта ресурсов и создания изолированных адресных пространств.

    Как планировщик ОС работает с процессами?

    Никак.

    Моя единственная догадка в том, что планировщик как бы "заглядывает" в каждый процесс и уже там работает с потоками.

    Не нужно ему никуда заглядывать. У него есть списки потоков находящихся в разных состояниях, а планирование заключается в перемещении потоков по этим спискам.
    Ответ написан
    9 комментариев
  • Почему не работает загрузчик?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    я так понял, происходит прыжок в никуда?

    Расскажи, как ты это понял?

    почему может не работать?

    Первая ошибка здесь: твой код собран под 0:7c00, но ты загрузил в ds 7c00 вместо нуля.
    Ответ написан
  • Как в архитектурах risc одинаковые виртуальные адреса разных контекстов задач различаются?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В risc вроде там куча csr регистров

    Вот на этом месте остановись. RISC -- это не конкретный набор инструкций и регистров, это принцип организации набора инструкций. RISC-процессоры все разные, возьми крнкретный и разбирайся с ним, не вали их все в одну кучу, не ставь на вопрос теги процессоров которые не имеют к нему отношения.

    на разных компиляторах одна си операция ассемблируется то в комбинацию lui + addi, то в комбинацию auipc +addi

    Ты указал ARM в тегах, но у ARM нет инструкций lui и auipc. Такие инструкции есть у RISC-V.
    Если ты посмотришь в The RISC-V Instruction Set Manual, раздел 2.4 Integer Computational Instructions, то увидишь, что опкод lui загружает константу собранную из 20 битов непосредственного значения из инструкции и 12 нулевых младших битов в целевой регистр, а auipc прибавляет такую же точно константу к PC и загружает в целевой регистр результат сложения, и в этом вся разница между ними.

    где какая используется не совсем понимаю.

    lui используется для генерации констант, которые не зависят от того, где расположен код, а auipc для генерации констант, которые двигаются вместе с кодом. Т.е. Если ты хочешь вызвать функцию, которая находится дальше чем ±2К от точки вызова, ты можешь сгенерировать её адрес инструкцией auipc, и полученный код будет работать одинаково, независимо от того, по какому адресу он будет размещён. А если тебе надо поместить в регистр константу, например 0x12345678, то ты можешь это сделать парой инструкций lui rd, 0x12345 ; addi rd, rd, 0x678 и значение константы будет всегда одинаковым, вне зависимости от того, где будет этот код.

    Каким образом одинаковые адреса различаются. Или они просто не могут быть одинаковыми(типа ос позаботиться)?

    Если есть MMU и он используется ОС, то есть и виртуальные адреса и они могут быть одинаковыми у разных процессов. Если MMU нет или он не используется, то ОС размещает все процессы в одном адресном пространстве, нет смысла говорить отдельно о виртуальных адресах, поскольку они равны физическим, адреса выделяемые ОС разным процессам могут быть как одинаковыми (например несколько процессов запущенных из одного исполняемого образа могут использовать один и тот же код и константные данные), так и разными (например изменяемые данные разные у всех процессов, а стеки разные у всех потоков).

    Как они в tlb обрабатываются, если вдруг они реально могут быть одинаковыми, и там нету ни каких дополнительных индексов процесса)

    Выбери конкретную процессорную архитектуру -- обсудим. у многих RISC-архитектур есть ASID, который идентифицирует адресное пространство и записывается вместе с виртуальным адресом в TLB. Но в любом случае ASID -- это просто оптимизация для повышения производительности, когда он отсутствует или переполняется ОС должна сбрасывать содержимое TLB при переключении адресного пространства.

    У ARM есть регистры TTBR с примерно той же функцией, что и cr3 в x86.
    У RISC-V есть CSR satp, содержащий ASID и базовый адрес корневого каталога страничных таблиц. Об этом можно прочитать в разделе 4.1.12 Supervisor Address Translation and Protection (satp) Register спецификации The RISC-V Instruction Set Manual Volume II: Privi....
    Ответ написан
    Комментировать
  • Может ли прерывание прервать выполнение конструктора / деструктора в С++?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Может ли прерывание прервать выполнение конструктора / деструктора в С++?

    Да, конечно может, как и любой другой код, явно не защищённый от прерываний.

    нужно ли в конструкторах / деструкторах защищать код критическими секциями?

    Нужно защищать любое состояние, к которому может обращаться код из разных контекстов выполнения -- например из разных потоков или из потока и обработчика прерывания. В ядре linux (где разных типов контекста много и разных способов синхронизации тоже много) есть руководство, что и когда использовать.
    Ответ написан
    Комментировать
  • Как увеличить FPS в системе?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как увеличить FPS в системе?

    Ты уже задавал этот вопрос в комментариях к предыдущему вопросу, там есть ответ:

    Основной способ стандартный -- не перерисовывать всё, если можно этого избежать.

    Нет нужды перерисовывать весь интерфейс в бэк-буфере, если ничего не изменилось кроме положения мыши. Указатель мыши вообще можно рисовать прямо во фрейм-буфере, когда он перемещается копировать маленький квадратик из бэк-буфера и рисовать стрелку в новом месте.
    Ответ написан
  • Как исправить движение мыши?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    mov al, [bp+12]
      mov bl, al
      mov cl, 3
      shl al, cl
    
      sbb dh, dh
      cbw
      mov dl, [bp+8]
      mov al, [bp+10]

    Этот кусок кода из обработчика перемещений мыши должен делать знаковое расширение 9-битных координат, но я вижу, что в существующем коде в обработчик перемещений всегда приходят нули в координатах x и y, а из-за этого знакового расширения отрицательные dx и dy всегда становятся равными -256. Если добавить вызов функции initialize (0xc205) прерывания 0x15 в mouse.init с 3-байтными пакетами:
    kernel.routine.mouse.init:
      push es bx
      int 0x11
      test ax, 4
      jz kernel.routine.mouse.init.error
      mov ax, 0xC205
      mov bh, 3
      int 0x15
      jc kernel.routine.mouse.init.error
      mov ax, 0xC203
      mov bh, MOUSE_RESOLUTION
      int 0x15
      jc kernel.routine.mouse.init.error

    то у меня всё начинает работать как ожидалось.
    Кстати в ответе на SO по твоей ссылке вызов этой функции есть, непонятно зачем ты его выкинул.
    Ответ написан
    2 комментария
  • Как узнать, откуда прерывание?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    проблема заключается в том, что я не знаю, как получить состояние машины в момент прерывания, чтобы его сохранить.

    Возможно тебе следует выяснить, что это конкретно за "состояние машины" которое ты собираешься сохранить, возможно это поможет тебе его найти.
    Ответ написан
    4 комментария
  • Как лучше это сделать?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    в скрипте линкера есть такая строка . = 0x100000;. Знаю, что grub загружает по этому адресу ядро

    нужно чтобы grub по прежнему загружал ядро по адрсесу 0x100000. А адресация внутри ядра происходила по виртуальному адресу, допустим 0x60000000

    Для начала нужно понять откуда grub берёт адрес для загрузки. Если из образа ядра, то я вижу один возможный вариант решения, если нет -- то два.
    Универсальное решение -- разбить ядро на две части: выполняющуюся сразу после загрузки и до включения виртуальной адресации и выполняющуюся с виртуальной адресацией. Линковать их двумя отдельными командами с разными скриптами линковщика, образ второй части встраивать в первую через какой-нибудь .incbin. Так делает ядро linux. Отсюда можно проследить как это делается.
    Не универсальное решение на случай, когда grub берёт адрес загрузки не из образа ядра, а часть кода работающая до переключения на виртуальную адресацию сравнительно проста -- сделать код этой части независимым от адреса загрузки, а образ ядра линковать для конечного виртуального адреса.
    Ответ написан
    2 комментария
  • Как создать массив хендлов на MASM?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Для полноты картины не хватает определений hBmp, hbtm и hInstance.
    Косяк бросающийся в глаза сразу -- ты создаёшь таймер в обработчике WM_INITDIALOG, но нигде его не удаляешь и он продолжает тикать и после закрытия диалога.
    Ответ написан
    Комментировать
  • Что происходит во время прерывания в многопоточной среде? Или прерывания посреди прерывания?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    откуда прерывания знают адрес, куда им вернуть результат.

    Прерывания не знают. Это работа ОС -- организовать информацию так, чтобы при получении прерывания разобраться, откуда оно, зачем, и что с ним делать.

    Прерывание в коде int 21h и прочие Это какое?

    Любое прерывание инициируемое инструкцией int -- программное. В отличие от прерывания, инициируемого уровнем или фронтом сигнала подключённого к контроллеру прерываний.

    Вообще, кажется, если понять, что программные прерывания на x86 используются просто как удобный способ вызывать функции ядра, т.е. делать системные вызовы, то путаницы должно стать меньше. Не думай о них как о прерываниях, думай о них просто как о вызовах функций ядра. Ядро делает всё для того, чтобы для приложения это именно так и выглядело.

    выполнение прерывания std::cin>>line; Может и сутки длиться.

    Системного вызова. std::cin >>line в конце концов превращается в системный вызов read.

    Вот как по пунктам для этой команды. (С условием что есть еще 1 поток жаждущий ЦП).

    Можно запустить такую программу, узнать её PID, выполнить где-нибудь cat /proc/<PID>/stack и увидеть следующую картину:
    [<0>] wait_woken+0x67/0x80
    [<0>] n_tty_read+0x426/0x5a0
    [<0>] tty_read+0x135/0x240
    [<0>] new_sync_read+0x115/0x1a0
    [<0>] vfs_read+0xf4/0x180
    [<0>] ksys_read+0x5f/0xe0
    [<0>] do_syscall_64+0x33/0x80
    [<0>] entry_SYSCALL_64_after_hwframe+0x44/0xa9

    Т.е. поток выполнил системный вызов (ksys_read), зашёл в VFS, добрался до функции чтения в драйвере терминала (tty_read) и перешёл в состояние ожидания в глубине этой функции (wait_woken). Когда драйвер терминала получит данные для программы, он разбудит её поток и системный вызов завершится. До тех пор этот поток будет не готов к выполнению и скедулер ОС просто не будет выделять ему время.

    Мне кажется, что тебе было бы полезно прочитать вторую и третью книжки (Understanding the Linux Kernel и Linux Kernel Developmen) из моего списка.
    Ответ написан
    Комментировать
  • Как происходит доступ к эл. массива на уровне ядра? Malloc выделяет непрерывную физическую память?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как происходит доступ к эл. массива на уровне ядра?

    Так же как и на уровне приложения -- через трансляцию виртуального адреса в физический.

    Например массив Int* arr = new int[1024*1024*1024] он как храниться?

    Если мы для определённости возьмём linux, то у ядра есть несколько разных способов выделения памяти, в зависимости от того, для чего эта память выделяется. Есть наиболее простой и стандартный kmalloc который выделяет память непрерывную как виртуально так и физически. Обычно этим механизмом нельзя выделить большой непрерывный кусок. Есть vmalloc, который выделяет непрерывную виртуально, но возможно прерывную физически память. Есть get_free_pages который выделяет непрерывные страницы физической памяти, возможно, не отображаемые ни в какие виртуальные адреса. Есть Contiguous Memory Allocator который при старте системы резервирует кусок непрерывной физической памяти и может аллоцировать оттуда куски по запросу.
    Важный момент состоит в том, что аллокации делаемые ядром linux через упомянутые интерфейсы всегда обеспечиваются физической памятью, у памяти ядра нет пейджинга.

    А физическая, для массива то же? Ведь, так будет доступ намного быстрее?

    Почему быстрее? С точки зрения процессора всё равно будет трансляция виртуального адреса в физический, если повезёт -- попадание в TLB, если не повезёт -- ходить по каталогам и таблицам страниц в памяти.

    получается эмулятор каждый адрес вычислять что ли?

    Простой эмулятор -- да, наверно. Умный эмулятор может кешировать эту информацию, например именно это свойство даёт QEMU большую часть его Q.
    Ответ написан
    Комментировать
  • Почему не работает клавиатура?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    почему-то не работает прерывание 0х20 для клавиатуры

    я не буду отлаживать твой код, но предложу тебе несколько вопросов, которые помогут тебе посмотреть в нужные места:
    - посылает ли клавиатура вообще IRQ?
    - настроен ли контроллер прерываний на приём IRQ от клавиатуры?
    - размаскирована ли линия IRQ от клавиатуры в контроллере прерываний?
    - настроен ли контроллер прерываний на то чтобы вызывать int 0x20 в ответ на IRQ от клавиатуры? [1]
    - получает ли процессор прерывание от контроллера прерываний?
    - настроена ли запись в IDT для int 0x20 на вызов твоего обработчика?
    - разрешены ли прерывания в процессоре?

    [1] Коль скоро здесь ты установил базовый вектор первого PIC в 0x20, то клавиатура, посылая IRQ1, должна вызывать int 0x21.
    Ответ написан
    Комментировать
  • Почему Qemu вылетает?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Я потратил несколько дней на то, чтобы понять в чем дело. Ничего не вышло.

    Эта часть вопроса не даёт нам никакой полезной информации. Рассказывай что делал, а мы попробуем понять, что пошло не так в твоём расследовании.
    Ответ написан
  • Почему не работает печать?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    я на винде только лог qemu могу просматривать

    Иван Четчасов, этого более чем достаточно, чтобы понять, что происходит. По шагам:
    - надо узнать адрес метки printsz
    - найти в логе qemu выполнение кода по этому адресу
    - проследить за тем, какой код выполняется и что оказывается в регистрах
    - понять что не так.
    Ответ написан
    Комментировать
  • Почему ВМ перезагружается?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Я пишу ос и у меня возникла проблема

    Возникла проблема -- отлаживай.
    Разберись, что за адрес у тебя загружается здесь в GDT.

    Вот так это можно пофиксить.
    Ответ написан
  • Почему для драйвера мыши используется тот же порт, что и в драйвере клавиатуры?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Такие же порты используются при нахождении нажатой клавиши на клавиатуре, так как они могут быть и там и тут?

    Это называется мультиплексирование. В конце концов PS/2 -- довольно сложный интерфейс, работающий с командами, а не то чтобы клавиатура была напрямую подсоединена к одному из портов PC. См. https://wiki.osdev.org/Mouse_Input#Keyboard.2FAux_...
    Ответ написан
    Комментировать
  • Ядра операционной системы под OpenSourse лицензией, но не BSD и GPL?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Среди "больших" ОС есть Haiku (MIT).
    Cреди rtos/embedded -- FreeRTOS (MIT), nuttx (apache).
    Ответ написан
    Комментировать
  • Ошибка компиляции, как исправить?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Делаю Binutils вот итог:

    configure: error: source directory already configured; run "make distclean" there first

    как исправить?

    прочитать сообщение об ошибке и сделать как оно говорит. А в будущем никогда не запускать configure в каталоге с исходниками, всегда создавать отдельный каталог для сборки и запускать configure и make там.
    Ответ написан
    Комментировать
  • Как установить на ARM-компьютер big-endian OS?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Какая из свободных OS/дистрибутивов Linux/BSD предоставляет такую возможность?

    buildroot позволяет собрать образ ядра linux/юзерспейс для big-endian ARM.
    Ответ написан
    2 комментария