• Как в io_uring отправить sqe, чтобы sqe выполнилось через 3 секунды после io_uring_submit?

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

    Для организации таймаута в liburing есть io_uring_prep_timeout, но кроме этого нужно сериализовать таймаут и все предыдущие команды (чтобы таймаут начинался после их окончания) и следующую после таймаута команду и сам таймаут (чтобы последующие команды не стартовали вместе с таймаутом). Сериализация делается установкой флага IOSQE_IO_DRAIN для sqe, почитать об этом можно например здесь. У меня нарисовался следующий пример, который записывает в файл (stderr), делает паузу в одну секунду, а потом записывает ещё:
    #include <fcntl.h>
    #include <liburing.h>
    #include <stdio.h>
    #include <sys/mman.h>
    
    #define QUEUE_DEPTH 16
    
    int main(int argc, char **argv)
    {
            int i;
            struct io_uring ring;
            struct io_uring_cqe *pcqe;
            static const char msg0[] = "before timeout\n";
            static const char msg1[] = "after timeout\n";
            struct io_uring_sqe *sqe;
    
            io_uring_queue_init(QUEUE_DEPTH, &ring, 0);
            io_uring_prep_write(io_uring_get_sqe(&ring), 2, msg0, sizeof(msg0), 0);
    
            sqe = io_uring_get_sqe(&ring);
            io_uring_prep_timeout(sqe, (struct __kernel_timespec[]){{.tv_sec = 1}},
                                  -1, IORING_TIMEOUT_ETIME_SUCCESS);
            io_uring_sqe_set_flags(sqe, IOSQE_IO_DRAIN);
    
            sqe = io_uring_get_sqe(&ring);
            io_uring_prep_write(sqe, 2, msg1, sizeof(msg1), 0);
            io_uring_sqe_set_flags(sqe, IOSQE_IO_DRAIN);
            io_uring_submit(&ring);
            for (i = 0; i < 3; ++i) {
                    int rv = io_uring_wait_cqe(&ring, &pcqe);
                    if (rv < 0) {
                            errno = -rv;
                            perror("io_uring_wait_cqe");
                    } else {
                            io_uring_cqe_seen(&ring, pcqe);
                    }
            }
    }
    Ответ написан
    Комментировать
  • Возможно ли реализовать виртуальный uart на stm32?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Первая проблема что нужно при скорости 9600 бит/c передача одного бита должна происходить прмерно 1/9600 = 104 микорсекунды. HAL_Delay поддерживает минимальный период 1 милисекунда.

    Это говорит о том, что нужно использовать другой метод для организации задержки. Например основанный на таймере со счётчиком.

    какой надо выставлять уровень напряжения на пине в простое

    Стандартно -- высокий логический. Сколько вольт этому должно соответствовать конкретно -- зависит от того, что вы подключите снаружи. Явно там будет какой-нибудь конвертор или другой микроконтроллер.
    Ответ написан
  • Как можно разделить данный код (см. ниже) по header'ам и cpp'ам, учитывая зависимости в нём?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    как я могу это сделать?

    Разносишь определения классов по файлам *.h. Разносишь определения методов классов по одноимённым файлам *.cc, инклудишь в них одноимённые *.h Потом смотришь на свою картинку. Стрелки наследования и агрегации добавляют include <файл в конце стрелки> в h файл в начале стрелки. Стрелки использования добавляют include <файл в конце стрелки> в cc файл в начале стрелки.
    Ответ написан
    1 комментарий
  • Как исправить ошибку буфера с UART?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    ONESTOPBIT ломало передачу блока

    Передачу откуда куда?

    DWORD ComIface::write(byte* data, int count)

    Что конкретно эта функция должна делать? Если это просто запись count байтов, то зачем так сложно?

    DWORD ComIface::read_block(byte* buffer, int size)

    Что конкретно эта функция должна делать?


    hpet rt;
        while (get_stats().cbInQue < size) {
            if (!SetCommMask(port_handle, EV_RXCHAR)) {
                printf("SetCommMask failed with error %d.\n", GetLastError());
                return NumberOfBytesRead;
            }
            WaitCommEvent(port_handle, &status, &overlap);
            WaitForSingleObject(overlap.hEvent, read_delay);
            if (rt.get_ms_dt_weak().count() > read_delay * size) {
                return NumberOfBytesRead;
            }
        }


    Что здесь происходит?

    Какие проблемы приводят к такому и как это чинить?

    Чтобы что-то чинить нужно это сначала понять.
    Ответ написан
  • Как из массива байтов HEX сделать сделать DEC?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    как вернуть как было в новый массив

    byte summ[N];
    word s = x * y;
    
    for (i = 0; i < N; ++i) {
        summ[i] = s % 256;
        s /= 256;
    }
    Ответ написан
    2 комментария
  • Как устранить ошибку конверсии при использовании битовых полей?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Как устранить ошибку конверсии при использовании битовых полей?

    Не использовать битовые поля. Серьёзно. Удобств на копейку а мороки на рубль.
    Ответ написан
    4 комментария
  • Почему передается некорректный адрес указателя в функцию?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Потому что переменная со спецификатором static локальна для единицы трансляции. Ты написал static button s1; в заголовочном файле, а это значит, что каждая единица трансляции в которую ты подключил этот файл получит свой собственный, независимый экземпляр переменной s1. Функция ModesInit инициализирует s1 из ModeDriver.o, а s1 из main.o останется неинициализированным.

    Исправить это можно заменив static на extern в заголовочном файле, а в одном из исходников добавив определение для переменной -- button s1;.
    Ответ написан
    1 комментарий
  • Как написать ассембли код x86 nasm для Linux?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Твой traverse_loop держит указатель на текущую запись в eax, но первый же вызов PrintName портит почти все регистры и не восстанавливает их, поэтому первый же movzx esi, byte [eax + 10h] после этого вызова обращается мимо памяти и вызывает segfault. Проще всего это исправить каким-нибудь pusha / popa вокруг тела PrintName. После этого ты доберёшься до вызова PrintMark, где увидишь, что эта функция ожидает в eax + 10h текстового представления оценки, а у тебя пока есть только двоичное.
    Ответ написан
    Комментировать
  • Является ли мой алгоритм криптостойким? Если нет, то где его уязвимость?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Шифрование происходит следующим образом:

    Создается хеш ключа с помощью SHA512(его размер = 16 байт).
    Для каждого из 16 блоков хеша создается случайное число с помощью Random, используя значение блока в качестве начального числа.
    Создается массив байтов того же размера, что и ввод, и заполняется случайными числами.
    Каждый байт ввода XOR-суммируется с соответствующим байтом массива байтов.

    У этого алгоритма есть как минимум следующая уязвимость: если кто-то может получить пару "фрагмент открытого текста" - "соответствующий шифртекст" хотя бы для какого-нибудь открытого текста и заданного пароля, то он сможет расшифровать соответствующий фрагмент из любого текста зашифрованного с тем же паролем. Просто поксорив результат с известным фрагментом открытого текста и с соотвтетсвующим ему шифртекстом.
    Ответ написан
    4 комментария
  • Функция не работает, не понимаю почему, как можно исправить?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    что я сделал не так, подскажите пожалуйста
    if (b[i] >= x || b[i] <= y) {
      a[j] = b[i];
      j++;
    }
    ...
    if (b[i] < x || b[i] > y) {
      a[j] = b[i];
      j++;
    }

    Условия в операторах if не являются взаимоисключающими, а значит j может стать больше чем n и запись в a[j] вылезет за границу массива.
    Я не уверен в правильности первого условия, но особо не задумываясь можно второе условие переписать как прямое отрицание первого: if (!(b[i] >= x || b[i] <= y)) и это гарантирует, что индекс не выйдет за пределы массива, вне зависимости от правильности первого условия.
    Ответ написан
    Комментировать
  • Компилятор выдаёт ошибку при попытке вызвать sizeof() относительно моего массива. Как исправить ошибку?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В C параметр функции не может быть массивом, только указателем. Синтаксис "имя с квадратными скобками" несёт тот же смысл, что и "имя со звёздочкой" когда речь идёт о параметрах функции. Если внутри функции взять sizeof от такого параметра результат будет равен sizeof от указателя. Это очень распространённая ошибка и компилятор говорит тебе об этом. Если тебе нужен размер массива переданного в функцию -- передавай его отдельно, например отдельным параметром.

    sizeof(dict)/sizeof(const char)

    Здесь ещё одна ошибка: dict -- это массив указателей (на самом деле указатель на такой массив, но по крайней мере, ты ожидал массив указателей), но ты делишь размер массива на размер const char а не на размер const char *. Во избежание таких ошибок для вычисления размера массива обычно пишут sizeof(dict)/sizeof(dict[0]).
    Ответ написан
    Комментировать
  • Контринтуитивный синтаксис объявления нескольких переменных одного типа?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    можно подумать, что при объявлении указателя, символ * относится к имени(не как часть, а как что-то зависящее от него), а не к типу.

    Если взять стандарт языка (например C99) и почитать главы Declarations, Type Specifiers и Declarators, то можно увидеть, что он разделяет declaration-specifiers, в который входят только слова и declarators, в который входят скобочки и звёздочки. Т.е. твой вывод по сути верный.

    Там же можно увидеть, что часть называемую declarator всегда можно обернуть в скобки, из чего можно извлечь следующий вывод: часть объявления вокруг которой можно поставить скобки самым широким образом относится к конкретному идентификатору, оставшаяся часть -- ко всему списку. Т.е. const char *a, b; можно превратить в const char (*a), b, но нельзя превратить в const (char *a), b или в char (const *a), b.

    Ну и напоследок стоит добавить, что такая интерпретация объявления не следует ни из чего с необходимостью, это просто решение которое было принято разработчиками языка. Они могли принять это решение по-другому и тогда уже другие конструкции вызывали бы наше удивление.
    Ответ написан
    2 комментария
  • Можете объяснить код на STM32?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    uint8_t led_state = 0x03; Данной командой мы завели переменную, которая равна 3

    В коде написано 2.

    что под этим подразумевается?

    2 -- это вот такое 8-битное двоичное число: 00000010. А если 2 заменить на 3, то число станет таким: 00000011. Улавливаешь связь с количеством и номерами включенных светодиодов?

    HAL_GPIO_WritePin(GPIOE, led_state << 8, GPIO_PIN_SET); Это я так понимаю мы сначала устанавливаем самый первый светодиод, т.е. 8, но на практике ни так.

    Нет, светодиоды на схеме подключены к битам 8..15, а led_state ты выше видел какое. Этой командой мы сдвигаем биты 0..7 led_state в биты 8..15.

    led_state = led_state >> 1 | led_state << 7;Эту строку совсем не понимаю.

    Это циклический сдвиг вправо на 1. Т.е. биты "выдвигаемые" вправо за пределы led_state появляются слева.
    т.е. двоичное число abcdefgh превращается в 0abcdefg | h0000000 = habcdefg.
    Ответ написан
    6 комментариев
  • Как исправить "неопределённая ссылка на «http::server::server::run()"?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Взял первый пример HTTP сервера на официальном сайте Boost
    add_executable(main main.cpp)

    В "первом примере HTTP сервера" по твоей ссылочке файлов-то существенно больше, не один только main.cpp. Ты бы их добавил как-нибудь в список исходников, а то немного странно получается, ты не находишь? Глядишь среди них где-то найдётся и исходник определяющий http::server::server::server.
    Ответ написан
    3 комментария
  • Как ос генерируют виртуальные адреса, по которым будет поиск, не физические? Почему программы с одних адресов начинаются?

    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-КБайтных страницах.
    Ответ написан
    Комментировать
  • Ошибка С2360, initialization of 'hInstanse' is skipped by 'case' label, почему?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    initialization of 'hInstanse' is skipped by 'case' label, почему?
    switch (uMsg)
    {
    ...
    case WM_CREATE:
    //получаем дескриптор приложения
    HINSTANCE hInstance = GetModuleHandle(0);
    ...
    break;
    
    case WM_MOUSEMOVE:
    //устанавливаем тот или иной курсор в зависимости от местонахождения мыши
    ...

    Потому что -- посмотри в этот код -- это фактически так: перейдя на метку WM_MOUSEMOVE код попадёт в область где hInstance определён, но минует его инициализацию. Компилятор туповат, чтобы понять, что hInstance дальше не используется. Простейший фикс -- обернуть код обработчиков в блоки:
    switch (uMsg)
    {
    ...
    case WM_CREATE:
    {
      //получаем дескриптор приложения
      HINSTANCE hInstance = GetModuleHandle(0);
      ...
    }
    break;
    
    case WM_MOUSEMOVE:
    {
      //устанавливаем тот или иной курсор в зависимости от местонахождения мыши
      ...
    }
    ...
    Ответ написан
    1 комментарий
  • Почему в git нет последовательного номера редакции по аналогии с svn?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    В svn было довольно удобно ориентироваться на последовательные номера редакций.

    В git точно так же можно ориентироваться на вывод git describe, в котором присутствует ближайшая метка (или выбранная метка, если делать git describe --match 'mask'), количество коммитов после этой метки и хеш последнего коммита. Например, в одном и том же дереве linux я вижу:
    $ git describe
    xtensa-6.8-rc2-esp32-spi-8-gb25ff15921c2
    $ git describe --match 'v*'
    v6.8-rc2-52-gb25ff15921c2
    $ git describe --match 'v?.?'
    v6.7-13495-gb25ff15921c2

    голова отстоит на 8 коммитов от последней метки xtensa-6.8-rc2-esp32-spi, или на 52 коммита от последней официальной метки v6.8-rc2 или на 13495 коммитов от последнего релиза v6.7.
    Ответ написан
    Комментировать
  • Ошибка в подсчете символов, что делать?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    считать количество русских букв, однако он не правильно это делает, что не так?

    считать русские буквы сложно, твой код зависит от кодировки и в любой не-однобайтной кодировке этот код не будет работать правильно. Проще всего, мне кажется, выкинуть charVector и весь код связанный с ним, а оставшееся переписать следующим образом:
    setlocale(LC_ALL, "");
    
    const char *str = input.c_str();
    
    while (*str) {
        wchar_t c;
        int n = mbtowc(&c, str, MB_CUR_MAX);
    
        if (n < 0)
            break;
        if (wcschr(L"абвгд...юя", c))
            ++count;
        str += n;
    }
    Ответ написан
    1 комментарий
  • Есть ли способ быстро выравнивать адреса?

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

    Можно, если выравнивание по степени двойки. addr = (addr + alignment - 1) & -alignment
    Ответ написан
  • Почему нет инфы о библиотеках в procfc файле maps, которые в сишном коде подключены и используются?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Компилирую gcc -o outfile source.c -lpthread. То есть собираю без всяких статиков, чтобы были зависимости к подключенным библиотекам. Далее запускаю процесс, чекаю /proc/pid/maps. Там нет ни единого упоминания к libpthread.

    100500 лет назад libpthread объединилась с glibc и теперь хоть и существует отдельно, чтобы программы использующие -lpthread продолжали собираться, внутри пустая. Короче, ты выбрал неудачного кандидата для экспериментов.
    Ответ написан
    Комментировать