Продолжаем развивать тему использования компьютера с ubuntu server в качестве устройства для связи мира микроконтроллеров с миром персональных компьютеров.
Ссылка на часть 1

Напомню, что статья описывает практику применения описанной техники и не ставит целью охватить все глубины и возможности современной аппаратуры. Это один из вариантов решения поставленной задачи.
В этой части я покажу, как проходить следующие моменты:
Друзья, жду Ваших интересных комментариев и ценных советов. Если где соврал — сильно не гневайтесь, просто указывайте, что можно сделать лучше. Надеюсь, появится 3 часть про большой скрипт, автоустановку… может ещё что.
Ссылка на часть 1

Напомню, что статья описывает практику применения описанной техники и не ставит целью охватить все глубины и возможности современной аппаратуры. Это один из вариантов решения поставленной задачи.
В этой части я покажу, как проходить следующие моменты:
Статический IP + DHCP сервер
В локальной сети на данный момент предполагается всего два устройства. Сам сервер и управляющая машина. Исходя из данной простоты настроим Ubuntu server.
Статический IP
Опорная информация
1. Чтобы узнать логическое имя (logical name) сетевого интерфейса делаем:
Вариант использования функции ifconfig (как аналог ipconfig в windows) иногда может дать только loop 127.0.0.1. Название интерфейса зависит от аппаратуры. На двух разных машинах ставил ubuntu с одной флэшки и были разные имена сетевых интерфейсов. enp3s0 — это классификация по шине и номеру устройства, как я понимаю. Бывают ещё из такой серии eth0 и такой ens35. Не пугайтесь.
2. Изменение файла конфигурации сети
Должно быть так:
Нажимаем cntrl-x — для выхода из редактора
Нажимаем y — для сохранения изменений
3. Перезагружаем сетевой сервис:
DHCP сервер
Опорная информация
1. Редактируем файлы для работы DHCP сервера
В файле
2. Если будете использовать функцию gethostbyname(), то в файле
В файле /etc/hostname хранится имя пк (ubuntu). Можно посмотреть через
3. Перезагружаем сетевой сервис:
SSH доступ
По идее, подключив теперь стационарный компьютер, мы получи для него IP и сможем иметь доступ по SSH. Для доступа из Windows я использовал утилиту PuTTY. Там же, в программных файлах PuTTY, есть утилита для передачи данных по сети.
Вот состав батника для передачи файлов с Ubuntu на Windows.
И для закачки на сервер
Статический IP
Опорная информация
1. Чтобы узнать логическое имя (logical name) сетевого интерфейса делаем:
и ищем строчкуsudo lshw -C network
logical name: enp3s0
Вариант использования функции ifconfig (как аналог ipconfig в windows) иногда может дать только loop 127.0.0.1. Название интерфейса зависит от аппаратуры. На двух разных машинах ставил ubuntu с одной флэшки и были разные имена сетевых интерфейсов. enp3s0 — это классификация по шине и номеру устройства, как я понимаю. Бывают ещё из такой серии eth0 и такой ens35. Не пугайтесь.
2. Изменение файла конфигурации сети
(nano — эта маленький текстовый редактор)sudo nano /etc/network/interfaces
Должно быть так:
# This file describes the network interfaces available on your system # and how to activate them. For more information, see interfaces(5). source /etc/network/interfaces.d/* # The loopback network interface auto lo iface lo inet loopback # My local network. allow-hotplug enp3s0 iface enp3s0 inet static address 172.16.55.1 netmask 255.255.255.0 gateway 172.16.55.1
Нажимаем cntrl-x — для выхода из редактора
Нажимаем y — для сохранения изменений
3. Перезагружаем сетевой сервис:
service networking restart
DHCP сервер
Опорная информация
1. Редактируем файлы для работы DHCP сервера
найдите строчкуsudo nano /etc/default/isc-dhcp-server
— это название интерфейса для DHCP сервера. В нашем случае должно быть так:INTERFACES=""
INTERFACES="enp3s0"
В файле
нужно добавитьsudo nano /etc/dhcp/dhcpd.conf
В рамках этой подсети DHCP сервер будет выдавать адреса в диапазоне от 2 до 100.subnet 172.16.55.0 netmask 255.255.255.0{ range 172.16.55.2 172.16.55.100; }
2. Если будете использовать функцию gethostbyname(), то в файле
должно быть прописано имя пк и IP. Возможно есть более удобный способ получить свой собственный IP, но мне он не поддался.sudo nano /etc/hosts
127.0.0.1 localhost 172.16.55.1 ubuntu
В файле /etc/hostname хранится имя пк (ubuntu). Можно посмотреть через
и ещё миллионом способов.sudo cat /etc/hostname
3. Перезагружаем сетевой сервис:
service networking restart
SSH доступ
По идее, подключив теперь стационарный компьютер, мы получи для него IP и сможем иметь доступ по SSH. Для доступа из Windows я использовал утилиту PuTTY. Там же, в программных файлах PuTTY, есть утилита для передачи данных по сети.
Вот состав батника для передачи файлов с Ubuntu на Windows.
d:\"Program Files"\PuTTY\pscp.exe ubuntu@172.16.55.1:/home/ubuntu/tool/* "F:/WORK/SERVER/tool/"
И для закачки на сервер
d:\"Program Files"\PuTTY\pscp.exe "F:/WORK/SERVER/tool/*" ubuntu@172.16.55.1:/home/ubuntu/tool/
Ставим драйвер от FTDI
Драйвера от FTDI поставляются в сжатом виде. Содержатся в пакете сами драйвера, библиотеки, примеры использования и README.pdf файл, который больше всего был интересен. Из файла D3XX Programmers Guide ни разу не ясно, как использовать драйвер для Linux. Пришлось даже написать в тех поддержку FTDI, благо они своевременно и по делу отвечают. Можно было бы и не писать, если бы я сразу раскрыл этот архив. Но полезными оказались ссылки, которые они прислали, примеры разводки и схемотехники.
Как показано выше, с помощью утилиты pscp из комплекта PuTTY, копируем на сервер драйвер. У меня был d3xx-linux-i686-0.5.0.tar.bz2. Заходим в эту папку на сервере и делаем
Далее, по инструкции FTDI исполняем:
Как показано выше, с помощью утилиты pscp из комплекта PuTTY, копируем на сервер драйвер. У меня был d3xx-linux-i686-0.5.0.tar.bz2. Заходим в эту папку на сервере и делаем
tar -xvf d3xx-linux-i686-0.5.0.tar.bz2
Далее, по инструкции FTDI исполняем:
cd linux-i686 sudo rm -f /usr/lib/libftd3xx.so sudo cp -f libftd3xx.so /usr/lib sudo cp -f libftd3xx.so.0.5.0 /usr/lib sudo cp -f 51-ftd3xx.rules /etc/udev/rules.d sudo udevadm control --reload-rules
Компилируем программу
Программу я писал в codeBlocks и она, за исключением некоторых моментов, в том числе и из-за FTDI, совместима с Windows. Перестала она компилироваться для Windows, когда я поставил туда h файл из драйвера для linux D3XX (c D2XX и FT232RL чипом не было проблем).
Теперь makefile. Программисты и так знают зачем он нужен, просто укажу особенности:
STATLIB=libftd3xx.a — указываем название библиотеки для Linux
CFLAGS=$(DEPENDENCIES) -Wall -Wextra -std=c++11 — разрешаем c++11
Таким образом, в папке проекта лежат файлы main.c ftd3xx.h makefile libftd3xx.a и прочие файлы проекта. И для компиляции проекта теперь нужно зайти в эту папку и сделать
Теперь makefile. Программисты и так знают зачем он нужен, просто укажу особенности:
STATLIB=libftd3xx.a — указываем название библиотеки для Linux
CFLAGS=$(DEPENDENCIES) -Wall -Wextra -std=c++11 — разрешаем c++11
пример makefile для одного файла проекта main.cpp
CC=g++ UNAME := $(shell uname) ifeq ($(UNAME), Darwin) DEPENDENCIES := -lpthread -ldl -lobjc -framework IOKit -framework CoreFoundation else DEPENDENCIES := -lpthread -ldl -lrt endif CFLAGS=$(DEPENDENCIES) -Wall -Wextra -std=c++11 STATLIB=libftd3xx.a APP = prgr all: $(APP) $(APP): main.o $(CC) -o $(APP) main.o $(STATLIB) $(CFLAGS) main.o: main.cpp $(CC) -c -o main.o main.cpp $(CFLAGS) clean: rm -f *.o ; rm $(APP)
Таким образом, в папке проекта лежат файлы main.c ftd3xx.h makefile libftd3xx.a и прочие файлы проекта. И для компиляции проекта теперь нужно зайти в эту папку и сделать
make
daemon
Роль демонов в Linux похожа на роль служб в Windows. Это программы, которые живут в фоновом режиме и делают всякую периферическую работу. Всё начинается с systemd — программы, которая запускается первой, имеет соответственно PID=1, и запускает все другие фоновые задачи через скрипты. Поковырявшись в Ubuntu, я удивился насколько много всего внутри построено на скриптах. Вы уже видели, как меняется статический IP, настраиваются программы, простой коррекцией файлов в текстовом редакторе.
Выполнив
Так вот, при запуске демона исполняется скрипт, в котором указано когда и как программу нужно запустить, как её остановить или перезапустить. Чтобы демон работал нормально, программа при запуске должна сохранить в файл, путь к которому указан в скрипте, свой PID и перейти в другой поток (в фоновый режим).
Пособие по демону меня ввело в грусть и тоску. Сильно упростив демона, я его превратил в утилиту для запуска любой программы. Но обязательная часть не поменялась. Помимо этого, он ведет лог, чтобы проверить, если вдруг что.
Компилируем демона.
На данный момент в нашем рабочем каталоге, допустим /home/ubuntu/daemon/, имеем:
daemon — программа демона
prgr — программа
prgr.strt — скрипт, который нужно выполнить до запуска программы (если надо)
prgr.stop — скрипт, который нужно выполнить для остановки программы (если надо)
Нужно разрешить программам работать:
Теперь нужен скрипт для systemd
Делаем
В скрипте кратко:
Description — краткое название-описание
After — что требуется для запуска
Type=forking — systemd предполагает, что служба запускается однократно и процесс разветвляется с завершением родительского процесса.
PIDFile — файл с PID программы из демона
ExecStartPre — до запуска программы
ExecStart — программа с параметрами
ExecStop — как остановить
WantedBy — уровень, на котором запускать
Теперь можно попробовать всё запустить.
Пишем
Если всё без ошибок, то запускаем:
После этого смотрите лог демона, всё должно поехать.
Чтобы работала автозагрузка
Выполнив
Вы увидите список запущенных программ с их PID. PID — это обязательный идентификатор запущенной программы, по которому за этой программой следит ОС. В крайней ситуации, можно грохнуть программу по этому PID из терминала — пишите kill и PID (может пригодиться для отладки).ps -el
Так вот, при запуске демона исполняется скрипт, в котором указано когда и как программу нужно запустить, как её остановить или перезапустить. Чтобы демон работал нормально, программа при запуске должна сохранить в файл, путь к которому указан в скрипте, свой PID и перейти в другой поток (в фоновый режим).
Пособие по демону меня ввело в грусть и тоску. Сильно упростив демона, я его превратил в утилиту для запуска любой программы. Но обязательная часть не поменялась. Помимо этого, он ведет лог, чтобы проверить, если вдруг что.
код daemon
void SetPidFile(char* Filename) { FILE* f; f = fopen(Filename, "w+"); if (f) { fprintf(f, "%u", getpid()); fclose(f); } } int main( int argc, char** argv ) { char toolfile[32]; char folder[32]; intptr_t ret; FILE* logfile; if( argc!=3 ) { printf( "Write address of the program and name: /home/ubuntu/tool/ tool\n"); return -1; } pid_t pid, sid; pid = fork(); if (pid < 0) { sleep(1); return -1; } //We got a good pid, Close the Parent Process if (pid > 0) { return 0; } //Create a new Signature Id for our child sid = setsid(); if (sid < 0) { return -1; } //Change File Mask umask(0); //Save PID memcpy( toolfile, argv[0], strlen(argv[0]) ); memcpy( toolfile + strlen(argv[0]), ".log", 4 ); memset( toolfile + strlen(argv[0]) + 4, 0, 1 ); printf( "Daemon:: log to:%s\n", toolfile ); logfile = fopen( toolfile, "w" ); fprintf( logfile, "Daemon:: started with 0=%s 1=%s 2=%s\n", argv[0], argv[1], argv[2] ); memset( toolfile, 0, 32 ); memcpy( toolfile, argv[0], strlen(argv[0]) ); memcpy( toolfile + strlen(argv[0]), ".pid", 4 ); memset( toolfile + strlen(argv[0]) + 4, 0, 1 ); SetPidFile( toolfile ); fprintf( logfile, "Daemon:: PID=%u saved in the %s\n", getpid(), toolfile ); memset( folder, 0, 32 ); memcpy( folder, argv[1], strlen(argv[1]) ); fflush ( logfile ); memset( toolfile, 0, 32 ); memcpy( toolfile, folder, strlen(argv[1]) ); memset( toolfile + strlen(argv[1]), '/', 1 ); memcpy( toolfile + strlen(argv[1]) + 1, argv[2], strlen(argv[2]) ); //Change Directory //If we cant find the directory we exit with failure. if ((chdir(folder)) < 0) { fprintf( logfile, "Daemon:: Program folder was not found:%s\n", folder ); fclose( logfile ); return -1; } //Close Standard File Descriptors close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); fprintf( logfile, "Daemon:: Program started\n" ); fflush ( logfile ); ret = execl( toolfile, folder, NULL ); if( ret==-1 ) { fprintf( logfile, "Daemon:: execl error: %s. File=%s Folder=%s\n", strerror(errno), toolfile, folder ); fclose( logfile ); return -1; } fprintf( logfile, "Daemon:: closed\n" ); fclose( logfile ); return 0; }
Компилируем демона.
На данный момент в нашем рабочем каталоге, допустим /home/ubuntu/daemon/, имеем:
daemon — программа демона
prgr — программа
prgr.strt — скрипт, который нужно выполнить до запуска программы (если надо)
prgr.stop — скрипт, который нужно выполнить для остановки программы (если надо)
Нужно разрешить программам работать:
sudo chmod 755 ./tool sudo chmod 755 ./daemon
Теперь нужен скрипт для systemd
Делаем
и записываем туда наш скрипт.sudo nano /etc/systemd/system/mydaemon.service
mydaemon.service
[Unit] Description=my service After=network.target After=isc-dhcp-server.service [Service] Type=forking PIDFile=/home/ubuntu/daemon/daemon.pid ExecStartPre=/bin/sh /home/ubuntu/daemon/prgr.strt ExecStart=/home/ubuntu/daemon/daemon /home/ubuntu/daemon/prgr prgr ExecStop=/bin/sh /home/ubuntu/daemon/prgr.stop Restart=always TimeoutSec=5 [Install] WantedBy=multi-user.target
В скрипте кратко:
Description — краткое название-описание
After — что требуется для запуска
Type=forking — systemd предполагает, что служба запускается однократно и процесс разветвляется с завершением родительского процесса.
PIDFile — файл с PID программы из демона
ExecStartPre — до запуска программы
ExecStart — программа с параметрами
ExecStop — как остановить
WantedBy — уровень, на котором запускать
Теперь можно попробовать всё запустить.
Пишем
systemctl daemon-reload systemctl status mydaemon
Если всё без ошибок, то запускаем:
systemctl start mydaemon
После этого смотрите лог демона, всё должно поехать.
Чтобы работала автозагрузка
systemctl enable mydaemon
Друзья, жду Ваших интересных комментариев и ценных советов. Если где соврал — сильно не гневайтесь, просто указывайте, что можно сделать лучше. Надеюсь, появится 3 часть про большой скрипт, автоустановку… может ещё что.