LINUX.ORG.RU

Сообщения vbr

 

Postfix: принимать почту из интернета на домен, с локалхоста на всё

Сейчас у меня стоит

myhostname = myhost.mydomain.com
mydomain = mydomain.com

mydestination = $myhostname localhost.$mydomain localhost $mydomain

Соответственно postfix принимает из интернета почту на все эти домены. Я хочу, чтобы из интернета он принимал почту только на mydomain.com. Но при этом, когда на локалхосте программы отправляют почту на root или root@myhost.mydomain.com или root@localhost и тд, то эта почта приходила соответствующему пользователю.

Как это настроить?

Или это норма и не надо это настраивать? ChatGPT меня убеждает, что это норма и чтобы я не морочил ему голову, но я сомневаюсь.

 ,

vbr
()

Как бы я сделал идеальный дистрибутив

Захотелось потрындеть, решил описать свое видение идеального дистрибутива. Сразу скажу, что меня интересует лишь серверная специфика, про полноценный GUI писать не буду, там думать надо.

  1. Сборка. Не скажу, что видел всё, но обычно берут исходники софтины с её билд-системой, к ней сверху прикручивают какие-то скрипты, которые вызывают ./configure и тд. Я бы сделал по-другому: берём, собственно, исходники. Выкидываем все билд скрипты и переводим всё на bazel. Считаю его лучшей системой сборки в мире, если есть время на его изучение. Понятно, что надо будет исходные билд-скрипты на самом деле не выкинуть, а изучить, определять нужные дефайны и тд. Сделать процесс перевода не одноразовым, а чем-то вроде скрипта, чтобы следующие версии уже автоматом собирать, а не повторять весь процесс.

Отдельный вопрос с крупными пакетами вроде ядра. Там система сборки, наверное, в каком-то смысле уже часть исходников. Не уверен, что для ядра это вообще возможно. Но если возможно, то надо сделать, однозначно.

bazel даст повторяемые сборки. Это важно. Т.е. вася и петя берут одни исходники и получают идентичные бинарники.

  1. Пакетов, как таковых, нет. Весь дистрибутив это что-то вроде debian-minimal. Т.е. ядро + systemd + libc + coreutils + кучка необходимых программ. Всё это идёт единым образом (можно представлять как tar-архив). Образ ОС абсолютно иммутабельный, не просто 644, не просто mount -o ro, а хотелось бы прям на уровне иммутабельной ФС вроде ISO. Чтобы его поменять вообще было бы сложно. Ещё для безопасности было бы неплохо там всё обложить контрольными суммами и подписями, чтобы ядро сразу выпадало в осадок, если на диске что-то поменялось.

  2. Каждая следующая версия выпускается кроме того хорошо оптимизированным бинарным diff-ом, что позволит типовым обновлениям быть крохотными, в районе нескольких десятков килобайтов. Обновления постараться сделать не требующими перезагрузки, но в то же время корректными (перезапускать демоны, если поменялась библиотека, через kexec перезапускать ядро). Кроме того сделать возможность очень легко откатиться на предыдущую версию, тоже без перезагрузки. Понятно, что речь идёт об обновлениях безопасности, когда особо ничего не меняется.

  3. Используются современные продвинутые файловые системы наподобие bcachefs/zfs/btrfs. Смысл в том, чтобы во-первых использовать дедупликацию, и обновления из пункта 3 не занимали кучу места, во-вторых чтобы максимально упростить откаты на предыдущие версии.

  4. Использовать максимально современные и легковесные подходы. Ядро грузить с UEFI, для сервисов systemd, networkd, минимум выбора, максимум интегрированности. Также использовать хорошие подходы к безопасности, ну про иммутабельный root уже упоминал, кроме этого запускать все сервисы по возможности в chroot или вообще отдельных ns, написать хорошие selinux правила. Т.к. базовая система имеет относительно небольшой размер, это не должно быть очень уж сложным.

  5. Собственно остаётся главное, для чего нужен дистрибутив - запуск пользовательских программ. И вот это предлагается делать не через опакечивание каждой программы во вселенной, а через контейнеры. Сегодня видимо это podman. Т.е. максимум, что от дистрибутива надо - обеспечить работу этого самого podman-а. А дальше уже практически для всего софта имеются образы либо от самих разработчиков, либо от достаточно компетентных товарищей, которые достаточно часто обновляются.

  6. Есть уж говорить про GUI, тут можно применить похожую концепцию. Выбрать один DE, ну очевидно это гном, включить его в базовый образ, а весь софт ставить через контейнерные решения вроде flatpak. Хотя тут, конечно, базовый образ будет куда жирней.

 ,

vbr
()

Как работает UART over USB, если получатель тормозит?

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

У меня есть девайс, который на компьютере принимает ровнёхонько 20 000 байтов в секунду, вообще без видимых флюктуаций. А вот на смартфоне не успевает и выходит на процентов 10-20 меньше. Я в протоколах этих не разбираюсь и предполагал, что там как-то автоматически будет буферизоваться всё где-то (в разумных пределах), а я там уже буду вычитывать, к примеру 100 раз в секунду по 200 байтов за раз, ну или как получится.

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

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

 , ,

vbr
()

nginx.service: Can't open PID file /run/nginx.pid (yet?) after start: Bad file descriptor

Archlinux, после старта nginx появляется такая ошибка в логе.

May 08 15:10:55 alpine systemd[1]: Starting A high performance web server and a reverse proxy server...
May 08 15:10:56 alpine systemd[1]: nginx.service: Can't open PID file /run/nginx.pid (yet?) after start: Bad file descriptor
May 08 15:10:56 alpine systemd[1]: Started A high performance web server and a reverse proxy server.

systemd юнит:

# systemctl cat nginx
# /usr/lib/systemd/system/nginx.service
[Unit]
Description=A high performance web server and a reverse proxy server
After=network.target network-online.target nss-lookup.target

[Service]
Type=forking
PIDFile=/run/nginx.pid
PrivateDevices=yes
SyslogLevel=err

ExecStart=/usr/bin/nginx -g 'pid /run/nginx.pid; error_log stderr;'
ExecReload=/usr/bin/nginx -s reload
KillMode=mixed

[Install]
WantedBy=multi-user.target

В nginx.conf ничего, относящегося к делу нет.

Файл /run/nginx.pid создаётся, pid в нём присутствует.

Почитал man open, пишут, что

EBADF
(openat()) pathname is relative but dirfd is neither AT_FDCWD nor a valid file descriptor.

и совсем запутался. В исходниках systemd не осилил понять, что происходит, тут (github.com) и тут (github.com) если кому интересно.

Версия systemd 253.4-1-arch.

Так в принципе оно вроде работает, но это же неправильно.

/run это tmpfs, никаких симлинков вроде нигде не задействовано.

Перемещено hobbit из general

 ,

vbr
()

arch живой?

Разочаровавшись в дебиане решил попробовать сабж первый раз в жизни и приятно удивился. Сходу поставил его в не самой дефолтной конфигурации (шифрование рута, syslinux, systemd в initramfs). Всё прошло прям как по маслу, я приятно удивлён. Особенно порадовало наличие vi, а не этого новомодного vim.

Собственно интересует лишь - насколько он живой? Всё же такой подход, как у него, нынче не слишком популярен, все кажется сейчас угорают по убунте и подобному.

 ,

vbr
()

Cloudflare R2, в чём подвох?

Это сервис типа S3 но без оплаты egress. Не пойму, в чём подвох. Цена за хранение тоже божеская ($15/TB). Что мне мешает сделать клон ютуба и обанкротить клаудфляр?

 

vbr
()

Максимально повторяемая страница на разных браузерах

Я хочу сделать страницу, которая будет выглядеть максимально похоже на разных браузерах. Идеал - попиксельная идентичность. Понимаю, что идеала не достичь, но хочу достичь что могу.

Ширина и высота у страницы фиксированные.

Шрифты я использую свои.

На что ещё нужно обратить внимание, по крайней мере из очевидного?

Я так понимаю, применять что-то вроде font-size: xx-large не стоит, т.к. это не соответствует конкретному кеглю и лучше применять что-то вроде font-size: 30px.

 

vbr
()

Как правильно использовать C без стандартной библиотеки?

Хочу писать на C для МК, но так, чтобы ни единого байта не было в бинарнике, не от моего кода.

В целом я понимаю, как это всё собрать и слинковать. Вопрос больше в том, что компилятор C в моём понимании генерирует код, рассчитывая на определённый рантайм, который я у него хочу забрать. К примеру я слыхал, что компилятор может генерировать вызовы функций вроде memcpy, если посчитает нужным. Также я не очень хорошо представляю, что происходит до вызова main и насколько это важно.

Также развитие этого вопроса - тот же вопрос про C++.

 ,

vbr
()

Не могу собрать Qt для кросс-компиляции

Хочу написать приложение, которое будет работать на arm девайсе. Документации не нашёл, делаю по крохам информации, которую нашёл, но ничего не получилось.

Во-первых нужно собрать Qt для хоста.

Хост у меня дебиан. Ставлю пакеты cmake gcc g++ mesa-common-dev ninja-build perl. Собираю командами

../qt-everywhere-src-6.4.3/configure -prefix /mnt/data/qt-host -submodules qtbase
cmake --build . --parallel 4
cmake --install .

Это у меня получилось.

Далее нужно собрать Qt для таргета. Таргет у меня это какая-то китайская плата с i.MX8MM. Есть rootfs для неё.

Первая проблема в том, что не понятно, где брать компилятор. Я поставил таким образом:

dpkg --add-architecture arm64
apt-get update
apt-get install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi

Также пробовал вариации с --add-architecture arm и gnueabhf. Не знаю, чем они отличаются и как понять, какой мне надо.

Далее написал файл imx8mm.cmake со следующими строчками:

set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR aarch64)
set(CMAKE_C_COMPILER arm-linux-gnueabi-gcc)
set(CMAKE_CXX_COMPILER arm-linux-gnueabi-g++)
set(CMAKE_SYSROOT ${INPUT_sysroot})
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)

и пытаюсь сконфигурировать Qt командой

/mnt/data/qt-everywhere-src-6.4.3/configure \
  -prefix /opt/qt \
  -extprefix /mnt/data/qt-embedded \
  -qt-host-path /mnt/data/qt-host \
  -sysroot /mnt/data/rootfs-ok8mm \
  -submodules qtbase \
  -nomake examples -nomake tests \
  -- \
  -DCMAKE_TOOLCHAIN_FILE=/home/build/imx8mm.cmake

Это всё кончается ошибкой

ERROR: The OpenGL functionality tests failed! You might need to modify the OpenGL package search path by setting the OpenGL_DIR CMake variable to the OpenGL library's installation directory.

Я не знаю, где посмотреть точно какая ошибка ему помешала.

В файле CMakeError.log есть миллион ошибок, но в том числе одна, которая мне кажется важной и которую я не знаю, как решить:

: && /usr/bin/arm-linux-gnueabi-gcc --sysroot=/mnt/data/rootfs-ok8mm -DCHECK_FUNCTION_EXISTS=XOpenDisplay -fPIE -pie CMakeFiles/cmTC_d6b57.dir/CheckFunctionExists.c.o -o cmTC_d6b57  /mnt/data/rootfs-ok8mm/usr/lib/libX11.so  /mnt/data/rootfs-ok8mm/usr/lib/libXext.so  /mnt/data/rootfs-ok8mm/usr/lib/libGLESv2.so  /mnt/data/rootfs-ok8mm/usr/lib/libEGL.so && :
/mnt/data/rootfs-ok8mm/usr/lib/libX11.so: file not recognized: file format not recognized
collect2: error: ld returned 1 exit status

Как я понимаю, суть ошибки в том, что компилятор не соответствует плате.

Вот вывод readelf -a /mnt/data/rootfs-ok8mm/usr/lib/libX11.so.6.3.0, может быть он чем-то поможет: https://pastebin.com/raw/5t5dQ2qw

Также ещё вижу такие проблемы: в usr/include платы нет заголовков для EGL, но при этом сами библиотеки в usr/lib есть. Пока до ошибок с EGL не дошёл, планировал их решить установкой пакета EGL в хостовую систему и изменением set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) на BOTH, хотя не уверен, что это правильно.

Может быть я зря на Qt 6 это пытаюсь делать и лучше использовать Qt 5? На плате установлена Qt 5 и есть какие-то примеры на Qt 5. Но, как я понимаю, мне всё равно для своей разработки надо собирать локально версию для кросс-компиляции.

 ,

vbr
()

А как в виртуальной машине поддерживать актуальное время?

Я тут со своей доморощенной виртуализацией экспериментирую. И оказалось, что когда мой ноутбук уснул, в запущенной виртуальной машине время ушло назад на время сна (то бишь не двигалось вперёд). Перезагрузка виртуальной машины проблему решила, но хотелось бы понять, можно ли эту проблему решить другими способами. Я предполагаю, что в запущенном линуксе время отсчитывается средствами процессора, а нужно вероятно вместо этого использовать какие-то аппаратные источники времени (которые, предположительно, в виртуальной машине будут синхронизированы с хостом и будут правильные).

Перемещено hobbit из general

 ,

vbr
()

Docker linux/amd64 работает под M1 маком с розеттой

Давно хотел проверить, но никак не доходили руки. Вообще говорят, что и в докер десктопе это есть, я не проверял. В целом запустил федору через Virtualization.Framework на M1 макбуке, в ней поставил докер, а также розетту. И теперь:

% docker run --rm -it --platform linux/amd64 debian:11 uname -a
Linux 3ae5494cbd64 6.1.18-200.fc37.aarch64 #1 SMP PREEMPT_DYNAMIC Sat Mar 11 16:03:54 UTC 2023 x86_64 GNU/Linux

Для меня это важно, мне этого давно не хватало. На qemu эмуляция была, но там такая медленная скорость, что было не юзабельно. А тут ничего так, шустренько.

% time docker run --rm -it --platform linux/amd64 debian:11 bash -c "head -c $((1024 * 1024 * 1024)) /dev/zero | sha256sum"
0.02s user 0.02s system 0% cpu 5.759 total

% time docker run --rm -it --platform linux/arm64 debian:11 bash -c "head -c $((1024 * 1024 * 1024)) /dev/zero | sha256sum"
0.03s user 0.02s system 0% cpu 4.770 total

 , ,

vbr
()

За сколько может грузиться самый быстрый линукс?

Если он запускается в виртуалке. Загрузчика вообще нет, сразу ядро и initrd подаётся на вход. Скомпилировать ядро без всего кроме того что надо для виртуалки. Как-то юзерспейс максимально быстро стартануть. Systemd самый быстрый?

У меня сейчас в виртуалке федора с UEFI за несколько секунд грузится. Мне интересно, можно ли это ускорить. Чего она там делает эти несколько секунд - не понятно. dmesg если кому интересно.

 

vbr
()

Как на старом ядре запустить современный браузер?

Имеется китайская плата на i.mx6ull. Китайцы туда поставили китайский линукс на китайском ядре 4.1.15. Браузера там нет. Я хочу туда засунуть веб приложение. Свое ядро более актуальной версии скомпилять пока не вышло. Посоветуйте как быть.

 , ,

vbr
()

Как разобраться с китайским SoB?

Имеется такая плата: OKMX6ULL-C

К ней по шлейфу подключил маленький дисплей. При подаче питания грузится какой-то китайский линукс с демо-программами.

Теперь мне надо из этого сделать что-то своё. Я на raspberry собирал свой линукс, но как тут подступиться, пока не понимаю.

Во-первых я не могу подключиться к нему по UART-у, чтобы работать полноценно, а не на крохотном дисплейчике. На выходных пинах есть UART2, …, UART4. Я подключил USB UART к UART2, но дальше соединиться не смог. К распберри я так подключался.

Судя по схеме UART1 разведён на USB-C выход на этой плате через USB-UART микросхему. Не очень понимаю, для чего это сделано. Можно ли подключить этот выход к компьютеру напрямую? Я боюсь спалить что-нибудь.

Во-вторых я не понимаю, как там вообще устроена загрузка. В распберри просто сд-карта, с неё и грузишься. Тут внутри есть emmc память на 8 гигабайтов. Встроенный линукс грузится именно с неё. Там два раздела, один на 500 MB, там ядро и ещё какой-то файл dtb. На втором разделе корень. В принципе слот для сд-карты есть. Пока грузиться с него не пробовал, т.к. вообще не очень понимаю, что туда сувать.

Ещё есть два раздела mmcblk1boot1 4MiB, mmcblk1boot0 4MiB. Они не монтируются, не знаю, что там на них.

В /etc/issue написано Freescale i.MX Release Distro 4.1.15-2.0.1 \n \l

Моя цель: для начала подключить это всё дело через серийный порт, чтобы можно было с компьютера с ним работать по-человечески. Потом скомпилировать минимальный линукс и загрузиться с него. А потом я уже сам разберусь.

Насколько я понимаю, производитель процессора это NXP, компания нормальная, но саму плату сделали китайцы.

У меня есть два гигабайта какой-то мусорной документации, которую они выслали, но я там ничего не понял. Собственно там толком ничего и нет, самое полезное это распиновка самой платы, остальное - тупо несколько десятков даташитов по всем микросхемам, использованным на плате и какой-то «мануал» с putty.exe и ссылками на китайские форумы, откуда предлагается скачать виртуалбокс. В общем такие мануалы мне не нужны.

Я на распи собирал свой линукс через buildroot. Но там был готовый конфиг и человеческие гайды. Как действовать тут - я пока в затруднении.

 , ,

vbr
()

Будут ли языки программирования супер высокого уровня?

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

На мой взгляд за последние лет 30 языки программирования не стали выше уровнем. Если взять тот же Haskell, который в каком-то виде в первый раз появился в 1990 году, то я бы не сказал, что Rust последней версии чем-то категорично его превосходит. В целом примерно одни и те же идеи тусуют в разных пропорциях. Я тут говорю исключительно про то, насколько язык помогает программисту писать код.

Мне интересно, как вообще можно совершить качественный скачок в языках программирования, оставаясь в той же парадигме, т.е. мы не будем рассматривать фантастику вроде того, что ты пытаешься там в чате чего-то объяснять роботу. А мы так же пишем формальный строгий текст латинницей, который преобразуется в машинный код. Но при этом то, что сейчас требует месяца работы, будет требовать трёх дней. Там, где сейчас 10 багов, будет 1 баг.

Предполагать, что что-то придёт взамен тексту, я тоже не буду. Текст доказал свою пользу на протяжении тысячелетий. Думаю, что ничего лучше текста не придумать.

Или же программирование в текущем виде достигло своего апогея и никаких принципиально новых идей уже не стоит ожидать?

 ,

vbr
()

Не могу поморгать диодом из C

Хочу поморгать диодом без библиотек. В целом сетап описан тут (linux.org.ru). Процессор STM32F030F4P6. Диод подключен, насколько я могу судить, к ноге PA4.

На текущий момент конфигурация такая:

Makefile:

CC = arm-none-eabi-gcc
AS = arm-none-eabi-as
LD = arm-none-eabi-ld
CFLAGS = -mthumb -mcpu=cortex-m0 -O0

.PHONY: all flash

all: app.bin

crt.o: crt.s

app.elf: linker.ld crt.o blink.o
	$(LD) -T linker.ld -o app.elf crt.o blink.o

app.bin: app.elf
	arm-none-eabi-objcopy -O binary $< $@

flash: app.bin
	st-flash --reset write $< 0x8000000

crt.s:

.cpu cortex-m3
.thumb

.word 0x20005000
.word _reset
.thumb_func
_reset:
  bl blink
  b .

linker.ld:

MEMORY {
  FLASH(rx): ORIGIN = 0x08000000, LENGTH = 16K
  RAM (xrw): ORIGIN = 0x20000000, LENGTH = 4K
}

blink.c:

#include <stdint.h>

const uint32_t RCC_BASE = 0x40021000;
const uint32_t GPIOA_BASE = 0x48000000;
const uint32_t RCC_AHBENR_OFFSET = 0x14;
const uint8_t RCC_AHBENR_IOPAEN_BIT = 17;
const uint32_t GPIOx_MODER_OFFSET = 0x00;
const uint8_t GPIOx_MODER_MODE4_BIT_OFFSET = 8;
const uint32_t GPIOx_ODR_OFFSET = 0x14;
const uint8_t GPIOx_ODR_OD4_BIT = 4;

void bit_clear(uint32_t address, uint8_t bit);
void bit_set(uint32_t address, uint8_t bit);
void bit_toggle(uint32_t address, uint8_t bit);

void blink(void) {
  bit_set(RCC_BASE + RCC_AHBENR_OFFSET, RCC_AHBENR_IOPAEN_BIT);
  bit_set(GPIOA_BASE + GPIOx_MODER_OFFSET, GPIOx_MODER_MODE4_BIT_OFFSET);
  bit_set(GPIOA_BASE + GPIOx_ODR_OFFSET, GPIOx_ODR_OD4_BIT);
  volatile uint32_t counter = 0;
  while (1) {
    if (counter % 0x10000 == 0) {
      bit_toggle(GPIOA_BASE + GPIOx_ODR_OFFSET, GPIOx_ODR_OD4_BIT);
    }
    counter++;
  }
}

void bit_clear(uint32_t address, uint8_t bit) {
  uint32_t mask = 1 << bit;
  volatile uint32_t *ptr = (uint32_t *) address;
  *ptr &= ~mask;
}

void bit_set(uint32_t address, uint8_t bit) {
  uint32_t mask = 1 << bit;
  volatile uint32_t *ptr = (uint32_t *) address;
  *ptr |= mask;
}

void bit_toggle(uint32_t address, uint8_t bit) {
  uint32_t mask = 1 << bit;
  volatile uint32_t *ptr = (uint32_t *) address;
  *ptr ^= mask;
}

Адреса брал из RM0360:

2.2.2 Memory map and register boundary addresses

AHB2 0x4800 0000 - 0x4800 03FF GPIOA
AHB1 0x4002 1000 - 0x4002 13FF RCC

7.4.6
Reset and clock control (RCC)
AHB peripheral clock enable register (RCC_AHBENR)
Address offset: 0x14
Bit 17: IOPAEN: I/O port A clock enable

8.4.1
GPIO port mode register (GPIOx_MODER)
Address offset:0x00
Bits 9:8 Port configuration bits
01: General purpose output mode

8.4.6
GPIO port output data register (GPIOx_ODR)
Address offset: 0x14
Bit 4: Port output databit

Насколько я понял из чтения документации:

  1. Нужно настроить регистр RCC_AHBENR и включить I/O port A.
  2. Нужно настроить регистр GPIOx_MODER и включить output mode для PA4.
  3. Для включения/выключения диода нужно менять бит GPIOx_ODR.

Возможно код на C неправильный, я его знаю плохо, пытался писать максимально просто.

На CubeMX пример с HAL копипастил, он работает, диод моргает. Ниже приведу на всякий случай:

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2023 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_4);
	HAL_Delay(100);
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOA_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);

  /*Configure GPIO pin : PA4 */
  GPIO_InitStruct.Pin = GPIO_PIN_4;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

Но я в нём ничего не понимаю, хотелось бы попроще.

 , ,

vbr
()

Правильно ли я подключил МК?

Хочу поэкспериментировать с МК. Для этого собрал следующую конструкцию:

Плата Baite STM32F030F4

Модуль зарядки TP4056

Далее у меня есть плата Nucleo L073RZ мануал (стр. 16). Я от этой платы отрезал верхний кусок по линии разреза, как я понимаю, там находится программатор. У этого программатора я вытащил два джампера CN2 чтобы переключить его на работу с внешним МК.

Подключил я это всё следующим образом:

1 провод от модуля зарядки TP4056 с пометкой «OUT +» к плате Baite, пину «header 1 pin 5 VIN»

1 провод от модуля зарядки TP4056 с пометкой «OUT -» к плате Baite, пину «header 1 pin 6 GND»

4 провода от Nucleo L073RZ коннектор CN4 пины VDD_TARGET, SWCLK, GND, SWDIO к Baite пинам SWD header pins 3V3, SWCLK, GND, SWDIO

2 провода от Nucleo L073RZ пины TX RX к Baite пинам Serial header pins RX TX

Вообще вчера я подключал всё почти так же, только питание у модуля зарядки брал похоже не с тех разъёмов. В итоге на Baite шло нефильтрованное питание из USB (примерно 4.5В показывал мультиметр). В целом всё заработало, программу я смог залить, но периодически программатор показывал, что соединения с контролером нет.

Сегодня я питание подключил как выше написал, теперь там 4.2В, как я понимаю, более стабильное. Также запитал USB-порт отдельным блоком питания. Пока вроде не отваливается. Вообще допускаю, что я плохо что-то припаял, т.к. паять я не умею, модуль питания и контролер шли без гребёнок, я эту гребёнку к ним припаял и соединил всё на проводках с квадратными разъёмами.

Вопрос 1 - вообще всё правильно?

Вопрос 2 - для чего нужен пин VDD_TARGET? Я сначала подумал, что от него можно запитать контролер, но потом почитав понял, что он питание не даёт а наоборот проверяет.

Вопрос 3 - для чего я подключил TX/RX? Я сам не знаю. Как-то через ST Link можно получить к нему доступ?

Вопрос 4. Можно ли куда-то подключить пин с программатора NRST? Я так понимаю, это удобная штука для перезагрузки контролера, но куда его подключить я не нашёл. Или он не нужен?

 

vbr
()

Контроль своего домена

Предположим, мне не нравится, что гугл в любой момент может забанить мой username@gmail.com, на который завязана вся моя цифровая жизнь.

Ну как линуксоид я иду и покупаю домен. Настраиваю на этот домен почтовый ящик и вот уже я me@username.com, счастье.

Но есть одно «но». Чтобы купить домен, мне надо зарегистрироваться на каком-нибудь namecheap-е. И для регистрации мне нужна… Правильно, почта.

Если я потеряю доступ к своей исходной почте, любая проблема с аккаунтом и доступ к домену я теряю.

Что же делать?

Пока для себя решил остановиться на варианте - использовать регистратора из своей страны. Есть надежда, что в случае проблем я смогу к ним позвонить, скинуть фото документов и получить возможность, к примеру, сменить забаненную почту.

Альтернативно: можно после покупки домена и настройки почтового сервера у регистратора сменить почту. Рекурсивненько получается. Но опять же это рецепт для проблем. Забыл домен оплатить вовремя, побежал его продлевать - а зайти не можешь и почта не ходит уже.

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

 

vbr
()

Постгрес в контейнере и ограничение по памяти?

Имеется постгрес в контейнере в кубе. За несколько дней у него растёт потребление по памяти постепенно. Пока не дорастает до лимита, процесс-коннект не прибивает ООМ-ом и всё заново не происходит. Кажется, что это не совсем хорошо. Хочется навести порядок. Начинал с 60M, уже 300M ему выделил, он сегодня до 200 дорос, как чайный гриб, растёт и всё, при том, что он и на 60M работал - ему 200M явно не надо.

Причём судя по тому, что, скажем, он 3 дня работает нормально, это явно не какие-то там пики и тд, просто память утекает в какие-то кеши или хз куда.

В идеале хочется задать постгресу Xmx60m как жаве и он за пределы этих 60m не вылазил и сам рассчитал там размеры для своих кешей и прочего. А не ронял процессы по ООМ.

Как тут правильно поступить?

 , ,

vbr
()

Как грамотно запустить контейнер, чтобы работал Ctrl+C

Нужно указать в докерфайле какую-нибудь команду, которая ничего не делает. Но чтобы работало завершение по сигналам.

Первое, что пробовал это ENTRYPOINT ["sleep", "infinity"]. Не сработало. sleep игнорирует сигналы. Всякие вариации вроде bash -c "sleep infinity" или bash -c "exec sleep infinity" тоже не работают.

Лучшее, что придумал - ENTRYPOINT ["sh", "-c", "while sleep 1; do true; done"]. Но немного некрасиво - секунду всё равно ждать и крутится там туда-сюда, запускает sleep всё время. И кажись для SIGSTOP не работает, только для SIGINT.

Какой самый классный и короткой способ сделать так, чтобы и по сигналу (SIGINT и SIGSTOP) завершало выполнение, и чтобы в рамках sh работало, и выглядело не монструозно. Через всякие trap-ы и kill-ы и я смогу, но там строк на 10 будет в лучшем случае.

 , , ,

vbr
()

RSS подписка на новые темы