Xenomai и real-time Linux

Вопросы программного кода и архитектуры Linux

Модератор: Olej

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 08 май 2018, 16:05

Olej писал(а): 2. скачиваем, собираем и устанавливаем дистрибутив Xenomai (библиотеки, include и т.д.);
Конфигурирование:

Код: Выделить всё

[olej@dell xenomai-3]$ ./configure --with-core=cobalt --enable-smp --enable-pshared --disable-tls
checking whether we build for Cobalt or Mercury core... cobalt
checking build system type... x86_64-unknown-linux-gnu
...
config.status: creating Makefile
config.status: creating config/Makefile
config.status: creating scripts/Makefile
config.status: creating scripts/xeno-config
config.status: creating scripts/xeno
...
config.status: executing depfiles commands
config.status: executing libtool commands
Параметры ./configure описаны в документации инсталляции, ссылка ввыше.
Компиляция:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/xenomai-3 $ time make
Making all in doc
...
make[1]: выход из каталога «/home/olej/2018_WORKS/Triol/xenomai-3»
  
real    9m27.099s
user    4m39.574s
sys     8m25.580s
Инсталляция:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/xenomai-3 $ time sudo make install
[sudo] пароль для olej:
Making install in doc
...
make[1]: выход из каталога «/home/olej/2018_WORKS/Triol/xenomai-3»

real    1m42.358s
user    0m37.631s
sys     1m41.791s

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 08 май 2018, 16:17

Olej писал(а): 1. пересобираем ядро Linux с патчем;
Теперь возвращаемся к пункту, который должен быть 1-м...

1.1. Смотрим, для каких версий ядра Linux существуют ipipe патчи для Xenomai (а они существуют для очень немногих версий ядра) Index of /downloads/ipipe/v4.x/x86:

Код: Выделить всё

[TXT] ipipe-core-4.1.18-x86-9.patch  25-May-2017 11:47  451K  
[TXT] ipipe-core-4.4.43-x86-8.patch  14-Jun-2017 11:47  486K  
[TXT] ipipe-core-4.4.71-x86-10.patch 03-Oct-2017 12:35  446K  
[TXT] ipipe-core-4.9.24-x86-2.patch  12-Jun-2017 11:06  491K  
[TXT] ipipe-core-4.9.38-x86-4.patch  03-Oct-2017 12:41  452K  
[TXT] ipipe-core-4.9.51-x86-5.patch  26-Mar-2018 09:17  456K  
[TXT] ipipe-core-4.9.90-x86-6.patch  26-Mar-2018 17:36  453K  
[DIR] older/                         26-Mar-2018 09:17    -   
1.2. Скачиваем патч:

Код: Выделить всё

[olej@xenix Triol]$ wget https://xenomai.org//downloads/ipipe/v4.x/x86/ipipe-core-4.9.90-x86-6.patch
--2018-04-20 15:40:15--  https://xenomai.org//downloads/ipipe/v4.x/x86/ipipe-core-4.9.90-x86-6.patch
Распознаётся xenomai.org (xenomai.org)… 62.210.215.82
Подключение к xenomai.org (xenomai.org)|62.210.215.82|:443... соединение установлено.
HTTP-запрос отправлен. Ожидание ответа… 200 OK
Длина: 464053 (453K) [text/x-diff]
Сохранение в: «ipipe-core-4.9.90-x86-6.patch»
...

[olej@xenix Triol]$ ls -l ipipe-core-4.9.90-x86-6.patch
-rw-rw-r-- 1 olej olej 464053 мар 26 18:36 ipipe-core-4.9.90-x86-6.patch
1.3. Скачиваем исходный код такого ядра Linux:

Код: Выделить всё

[olej@xenix Triol]$ wget https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.9.90.tar.gz
--2018-04-20 15:39:01--  https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.9.90.tar.gz
Распознаётся www.kernel.org (www.kernel.org)… 147.75.44.153, 2604:1380:4090:1700::1
Подключение к www.kernel.org (www.kernel.org)|147.75.44.153|:443... соединение установлено.
HTTP-запрос отправлен. Ожидание ответа… 301 Moved Permanently
Адрес: https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.9.90.tar.gz [переход]
--2018-04-20 15:39:02--  https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.9.90.tar.gz
Распознаётся mirrors.edge.kernel.org (mirrors.edge.kernel.org)… 147.75.101.1, 2604:1380:2001:3900::1
Подключение к mirrors.edge.kernel.org (mirrors.edge.kernel.org)|147.75.101.1|:443... соединение установлено.
HTTP-запрос отправлен. Ожидание ответа… 200 OK
Длина: 141860201 (135M) [application/x-gzip]
Сохранение в: «linux-4.9.90.tar.gz»
...

[olej@xenix Triol]$ ls -l linux-4.9.90.tar.gz
-rw-rw-r-- 1 olej olej 141860201 мар 25 10:53 linux-4.9.90.tar.gz

olej@Cobalt ~/2018_WORKS/Triol $ tar -zxf linux-4.9.90.tar.gz
Тут есть вопрос: брать ванильное ядро или использовать .src из репозитория своего дистрибутива Linux?
Авторы Xenomai используют 1-е, но 2-е - правильнее ... но здесь сложность выбрать именно то ядро, что нужно (по версии).

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 08 май 2018, 16:37

Olej писал(а): 1. пересобираем ядро Linux с патчем;
1.4. Накладываем патч:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol $ time xenomai-3/scripts/prepare-kernel.sh --arch=x86_64 --linux=./linux-4.9.90 --ipipe=ipipe-core-4.9.90-x86-6.patch
checking file arch/x86/Kconfig
checking file arch/x86/entry/common.c
...
checking file mm/vmalloc.c

real	1m5.128s
user	0m24.778s
sys	1m4.100s
1.5. Готовимся к сборке ядра...
- используем .config от текущего дистрибутива:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol $ cd linux-4.9.90/

olej@Cobalt ~/2018_WORKS/Triol/linux-4.9.90 $ cp /boot/config-`uname -r` .config

- конфигурируем параметры ядра ...

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/linux-4.9.90 $ make menuconfig
...
scripts/kconfig/mconf  Kconfig
configuration written to .config

*** End of the configuration.
*** Execute 'make' to start the build or try 'make help'.
Здесь может нужно доустановить:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/Xen_doc_own $ sudo apt install ncurses-dev
...
Здесь появятся новые конфиг-параметры, из рекомендаций Xenomai:

Код: Выделить всё

Recommended options:

* General setup
  --> Local version - append to kernel release: -xenomai-3.0.5
  --> Timers subsystem
      --> High Resolution Timer Support (Enable)
* Xenomai/cobalt
  --> Sizes and static limits
    --> Number of registry slots (512 --> 4096)
    --> Size of system heap (Kb) (512 --> 4096)
    --> Size of private heap (Kb) (64 --> 256)
    --> Size of shared heap (Kb) (64 --> 256)
    --> Maximum number of POSIX timers per process (128 --> 512)
  --> Drivers
    --> RTnet
        --> RTnet, TCP/IP socket interface (Enable)
            --> Drivers
                --> New intel(R) PRO/1000 PCIe (Enable)
                --> Realtek 8169 (Enable)
                --> Loopback (Enable)
        --> Add-Ons
            --> Real-Time Capturing Support (Enable)
* Power management and ACPI options
  --> CPU Frequency scaling
      --> CPU Frequency scaling (Disable)
  --> ACPI (Advanced Configuration and Power Interface) Support
      --> Processor (Disable)
  --> CPU Idle
      --> CPU idle PM support (Disable)
* Pocessor type and features
  --> Enable maximum number of SMP processors and NUMA nodes (Disable)
  // Ref : http://xenomai.org/pipermail/xenomai/2017-September/037718.html
  --> Processor family
      --> Core 2/newer Xeon (if "cat /proc/cpuinfo | grep family" returns 6, set as Generic otherwise)
  // Xenomai will issue a warning about CONFIG_MIGRATION, disable those in this order
  --> Transparent Hugepage Support (Disable)
  --> Allow for memory compaction (Disable)
  --> Contiguous Memory Allocation (Disable)
  --> Allow for memory compaction
    --> Page Migration (Disable)
* Device Drivers
  --> Staging drivers
      --> Unisys SPAR driver support
         --> Unisys visorbus driver (Disable)

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 08 май 2018, 16:50

Olej писал(а): 1. пересобираем ядро Linux с патчем;
1.6. ... и сборка и установка ... довольно обычные операции, но это часы компьютерного времени:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/linux-4.9.90 $ time make
...
  IHEX    firmware/yam/1200.bin
  IHEX    firmware/yam/9600.bin

real	535m1.524s
user	326m52.028s
sys	258m29.378s
(это в VirtualBox, но и в реальном железе это очень скучно)
Здесь может быть ошибка если не установлено:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/Xen_doc_own $ apt install libssl-dev
...

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/linux-4.9.90 $ time make modules
  CHK     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CHK     include/generated/bounds.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/asm-offsets.h
  CALL    scripts/checksyscalls.sh
  Building modules, stage 2.
  MODPOST 4749 modules

real	17m23.788s
user	7m46.865s
sys	8m54.727s

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/linux-4.9.90 $ time make bzImage 
...
Kernel: arch/x86/boot/bzImage is ready  (#2)

real	18m10.596s
user	7m52.628s
sys	10m30.910s
Установка:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/linux-4.9.90 $ time sudo make install
...

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/linux-4.9.90 $ time sudo make modules_install
[sudo] пароль для olej: 
  INSTALL arch/x86/crypto/aes-x86_64.ko
...
real	19m23.686s
user	6m58.163s
sys	11m11.815s

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time Linux

Непрочитанное сообщение Olej » 08 май 2018, 16:52

1.7. Конфигурирование умолчаний GRUB 2
/etc/default/grub :

Код: Выделить всё

#GRUB_HIDDEN_TIMEOUT=0
GRUB_HIDDEN_TIMEOUT=
#GRUB_HIDDEN_TIMEOUT_QUIET=true
GRUB_HIDDEN_TIMEOUT_QUIET=false

Код: Выделить всё

olej@Cobalt ~ $ sudo grub-mkconfig -o /boot/grub/grub.cfg
[sudo] пароль для olej: 
Создание конфигурационного файла grub...
Найден образ linux: /boot/vmlinuz-4.13.0-38-generic
Найден образ initrd: /boot/initrd.img-4.13.0-38-generic
Найден образ linux: /boot/vmlinuz-4.10.0-38-generic
Найден образ initrd: /boot/initrd.img-4.10.0-38-generic
Найден образ linux: /boot/vmlinuz-4.9.90-xenomai-3.0.5
Найден образ initrd: /boot/initrd.img-4.9.90-xenomai-3.0.5
Found memtest86+ image: /boot/memtest86+.elf
Found memtest86+ image: /boot/memtest86+.bin
завершено
1.8. После перезагрузки (ручным выбором из меню GRUB):

Код: Выделить всё

olej@Cobalt ~ $ uname -a
Linux Cobalt 4.9.90-xenomai-3.0.5 #2 SMP Sat Apr 21 11:57:39 EEST 2018 x86_64 x86_64 x86_64 GNU/Linux
Теперь мы имеем готовой RT-окружение Xenomai, они называют его Cobalt, и можно писать пользовательские RT-приложения.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 08 май 2018, 18:54

Olej писал(а): 3. можем писать свои пользовательские приложения в нативном API Xenomai (это ранние наработки Xenomai);
Внешний вид realtime task в нативном API Xenomai (что и как здесь происходит - абсолютно не имеет значения, это пример внешнего вида):

Код: Выделить всё

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/mman.h>
#include <alchemy/task.h>
#include <alchemy/timer.h>
#include <math.h>

#define CLOCK_RES 1e-9     //Clock resolution is 1 ns by default
#define MKS 1000           //Expressed in ticks
#define LOOP_PERIOD 30*MKS //Expressed in ticks
RT_TASK loop_task;
int err;

void loop_task_proc( void *arg ) {
   RT_TASK *curtask;
   RT_TASK_INFO curtaskinfo;
   RTIME tstart, now; //, tend, abstime;
   curtask = rt_task_self();
   rt_task_inquire( curtask, &curtaskinfo );
   int ctr = 0;
   //Print the info
   printf( "Starting task %s with period of 10 ms ....\n", curtaskinfo.name );
   //Make the task periodic with a specified loop period
   rt_task_set_periodic( NULL, TM_NOW, LOOP_PERIOD );
   tstart = rt_timer_read();
   //Start the task loop
   while( 1 ) {
      now = rt_timer_read();
/*    abstime = now - tstart;
      printf( "Loop count: %d, Loop time: %.5f s  mks time: %.5f mks ns time: %.d ns \n", 
              ctr, abstime/1000000.0, abstime/1000.0, abstime);
      printf( "Loop count: %d, Loop diff time: %.5f mks\n", ctr, ( now - tend ) / 1000.0 ); 
      tend = now;*/
      ctr++;
      rt_task_wait_period( NULL );
//    printf("Loop count: %d, Loop time: %.5f ms\n", ctr, (rt_timer_read() - now)/10000.0);
  }
}

static void handler( int signo ) { }

void get_result( void ) {
   printf( "завершение с обсчётом ==================\n" );
}

int main( int argc, char **argv ) {
   // Lock the memory to avoid memory swapping for this program
   // int on_exit(void (*function)(int , void *), void *arg);
   signal( SIGINT, handler );
   atexit( get_result );          // выполнить при завершении
   mlockall( MCL_CURRENT | MCL_FUTURE );
   printf( "Starting cyclic task...\n" );
   // Create the real time task
   rt_task_create( &loop_task, "cyclic_task", 0, 50, 0);
   //Since task starts in suspended mode, start task
   rt_task_start( &loop_task, &loop_task_proc, 0 );
   //Wait for Ctrl-C
   pause();
   rt_task_delete( &loop_task );
   printf( "\n-------------------\n" );
}
И самая важная здесь часть - Makefile сборки такого нативного приложения:

Код: Выделить всё

XENO_CONFIG := $(XENO_DIR)/bin/xeno-config
CFLAGS  := `$(XENO_CONFIG) --posix --alchemy --cflags`
LDFLAGS := `$(XENO_CONFIG) --posix --alchemy --ldflags`
CC := `$(XENO_CONFIG) --cc`
...
periodic_rdtsc: periodic_rdtsc.c Makefile
        $(CC) -Wall $(CFLAGS) $< $(LDFLAGS) -lanalogy -ltrank -o $@
...
Сборка:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/periodic $ make periodic_rdtsc
`/usr/xenomai/bin/xeno-config --cc` -Wall `/usr/xenomai/bin/xeno-config --posix --alchemy --cflags` periodic_rdtsc.c `/usr/xenomai/bin/xeno-config --posix --alchemy --ldflags` -lanalogy -ltrank -Bstatic -L./ -ltest -o periodic_rdtsc 
Выполнение:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/periodic $ export LD_LIBRARY_PATH=/usr/xenomai/lib; ./periodic_rdtsc 
Starting cyclic task...
Starting task cyclic_task with period of 10 ms ....
^C^C
-------------------
завершение с обсчётом ==================

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 08 май 2018, 19:27

Olej писал(а): 3. можем писать свои пользовательские приложения в нативном API Xenomai (это ранние наработки Xenomai);
Ещё один пример в нативном API, ещё проще:

Код: Выделить всё

#include <stdio.h>
#include <signal.h>
#include <unistd.h>

#include <alchemy/task.h>

RT_TASK hello_task;

void helloWorld( void *arg ) {
   RT_TASK_INFO curtaskinfo;
   printf( "Hello World!\n" );
   // inquire current task
   rt_task_inquire( NULL, &curtaskinfo );
   // print task name
   printf( "Task name : %s \n", curtaskinfo.name );
}

int main( int argc, char* argv[] ) {
   char str[ 10 ];
   printf( "start task\n" );
   sprintf(str,"hello");
  /* Create task
   * Arguments: &task,
   *            name,
   *            stack size (0=default),
   *            priority,
   *            mode (FPU, start suspended, ...)
   */
   rt_task_create( &hello_task, str, 0, 50, 0 );
  /*  Start task
   * Arguments: &task,
   *            task function,
   *            function argument
   */
   rt_task_start( &hello_task, &helloWorld, 0 );
}
Makefile:

Код: Выделить всё

XENO_CONFIG := /usr/xenomai/bin/xeno-config
CFLAGS  := `$(XENO_CONFIG) --posix --alchemy --cflags`
LDFLAGS := `$(XENO_CONFIG) --posix --alchemy --ldflags`
CC := `$(XENO_CONFIG) --cc`
EXECUTABLE := ex01a

all: $(EXECUTABLE)

%: %.c
        $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS)

clean:
        rm -f $(EXECUTABLE)
Сборка:

Код: Выделить всё

Cobalt ex1 # make
`/usr/xenomai/bin/xeno-config --cc` -o ex01a ex01a.c -I/usr/xenomai/include/cobalt -I/usr/xenomai/include -D_GNU_SOURCE -D_REENTRANT -fasynchronous-unwind-tables -D__COBALT__ -D__COBALT_WRAP__ -I/usr/xenomai/include/alchemy -Wl,--no-as-needed -Wl,@/usr/xenomai/lib/cobalt.wrappers -Wl,@/usr/xenomai/lib/modechk.wrappers -lalchemy -lcopperplate /usr/xenomai/lib/xenomai/bootstrap.o -Wl,--wrap=main -Wl,--dynamic-list=/usr/xenomai/lib/dynlist.ld -L/usr/xenomai/lib -lcobalt -lmodechk -lpthread -lrt   
Выполнение:

Код: Выделить всё

Cobalt ex1 # export LD_LIBRARY_PATH=/usr/xenomai/lib/

Cobalt ex1 # ./ex01a
start task
Hello World!
Task name : hello
Здесь важно и наглядно то, что функцией main() запускается realtime задача, системные вызовы которой будут идти не в kernel Linux, а в другое микроядро Xenomai, сосуществующее параллельно с Linux.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 08 май 2018, 19:58

Olej писал(а): 3. можем писать свои пользовательские приложения в нативном API Xenomai (это ранние наработки Xenomai);
Но куда интереснее у них возможность:
Olej писал(а): 4. можем писать realtime приложения в стандартном API POSIX, когда Xenomai маскирует многие системные вызовы Linux;
Она у них появилась, похоже, только в последние годы ... из 15 лет развития Xenomai...

Идея состоит в том, что основные системные (man -s2 ...) вызовы поступают не в Linux kernel, а для них написаны оболочки (wrappers) и они перенапраяляются в микроядро Xenomai, там модифицируются, после чего отправляются в ядро Linux.
Всё это в исходниках Xenomai (которые мы собирали при установке) находится здесь:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/xenomai-3/include/cobalt $ pwd
/home/olej/2018_WORKS/Triol/xenomai-3/include/cobalt

olej@Cobalt ~/2018_WORKS/Triol/xenomai-3/include/cobalt $ ls
arith.h      kernel       Makefile.in  sched.h      stdio.h   syslog.h  trace.h     unistd.h
boilerplate  Makefile     mqueue.h     semaphore.h  stdlib.h  ticks.h   tunables.h  wrappers.h
fcntl.h      Makefile.am  pthread.h    signal.h     sys       time.h    uapi

olej@Cobalt ~/2018_WORKS/Triol/xenomai-3/include/cobalt $ cat *.h | grep COBALT_DECL
COBALT_DECL(int, open(const char *path, int oflag, ...));
COBALT_DECL(int, open64(const char *path, int oflag, ...));
COBALT_DECL(int, fcntl(int fd, int cmd, ...));
COBALT_DECL(mqd_t, mq_open(const char *name,
COBALT_DECL(int, mq_close(mqd_t qd));
COBALT_DECL(int, mq_unlink(const char *name));
COBALT_DECL(int, mq_getattr(mqd_t qd,
COBALT_DECL(int, mq_setattr(mqd_t qd,
COBALT_DECL(int, mq_send(mqd_t qd,
COBALT_DECL(int, mq_timedsend(mqd_t q,
COBALT_DECL(ssize_t, mq_receive(mqd_t q,
COBALT_DECL(ssize_t, mq_timedreceive(mqd_t q,
COBALT_DECL(int, mq_notify(mqd_t q,
COBALT_DECL(int, pthread_attr_init(pthread_attr_t *attr));
COBALT_DECL(int, pthread_create(pthread_t *ptid_r,
COBALT_DECL(int, pthread_getschedparam(pthread_t thread,
COBALT_DECL(int, pthread_setschedparam(pthread_t thread,
COBALT_DECL(int, pthread_mutex_init(pthread_mutex_t *mutex,
COBALT_DECL(int, pthread_mutex_destroy(pthread_mutex_t *mutex));
COBALT_DECL(int, pthread_mutex_lock(pthread_mutex_t *mutex));
COBALT_DECL(int, pthread_mutex_timedlock(pthread_mutex_t *mutex,
COBALT_DECL(int, pthread_mutex_trylock(pthread_mutex_t *mutex));
COBALT_DECL(int, pthread_mutex_unlock(pthread_mutex_t *mutex));
COBALT_DECL(int, pthread_cond_init (pthread_cond_t *cond,
COBALT_DECL(int, pthread_cond_destroy(pthread_cond_t *cond));
COBALT_DECL(int, pthread_cond_wait(pthread_cond_t *cond,
COBALT_DECL(int, pthread_cond_timedwait(pthread_cond_t *cond,
COBALT_DECL(int, pthread_cond_signal(pthread_cond_t *cond));
COBALT_DECL(int, pthread_cond_broadcast(pthread_cond_t *cond));
COBALT_DECL(int, pthread_kill(pthread_t ptid, int sig));
COBALT_DECL(int, pthread_join(pthread_t ptid, void **retval));
 * COBALT_DECL(). Since Cobalt also routes pthread_yield() to its own
COBALT_DECL(int, pthread_yield(void));
COBALT_DECL(int, pthread_setname_np(pthread_t thread, const char *name));
COBALT_DECL(int, sched_yield(void));
COBALT_DECL(int, sched_get_priority_min(int policy));
COBALT_DECL(int, sched_get_priority_max(int policy));
COBALT_DECL(int, sched_setscheduler(pid_t pid, int policy,
COBALT_DECL(int, sched_getscheduler(pid_t pid));
COBALT_DECL(int, sem_init(sem_t *sem,
COBALT_DECL(int, sem_destroy(sem_t *sem));
COBALT_DECL(int, sem_post(sem_t *sem));
COBALT_DECL(int, sem_wait(sem_t *sem));
COBALT_DECL(int, sem_timedwait(sem_t *sem,
COBALT_DECL(int, sem_trywait(sem_t *sem));
COBALT_DECL(int, sem_getvalue(sem_t *sem, int *value));
COBALT_DECL(sem_t *, sem_open(const char *name, int oflags, ...));
COBALT_DECL(int, sem_close(sem_t *sem));
COBALT_DECL(int, sem_unlink(const char *name));
COBALT_DECL(int, sigpending(sigset_t *set));
COBALT_DECL(int, sigwait(const sigset_t *set, int *sig));
COBALT_DECL(int, sigwaitinfo(const sigset_t *set, siginfo_t *si));
COBALT_DECL(int, sigtimedwait(const sigset_t *set, siginfo_t *si,
COBALT_DECL(int, kill(pid_t pid, int sig));
COBALT_DECL(int, sigqueue(pid_t pid, int sig,
COBALT_DECL(int, vfprintf(FILE *stream, const char *fmt, va_list args));
COBALT_DECL(int, __vfprintf_chk(FILE *stream, int level,
COBALT_DECL(int, __vprintf_chk(int flag,
COBALT_DECL(int, __printf_chk(int flag, const char *fmt, ...));
COBALT_DECL(int, __fprintf_chk(FILE *fp, int flag, const char *fmt, ...));
COBALT_DECL(int, vprintf(const char *fmt, va_list args));
COBALT_DECL(int, fprintf(FILE *stream, const char *fmt, ...));
COBALT_DECL(int, printf(const char *fmt, ...));
COBALT_DECL(int, puts(const char *s));
COBALT_DECL(int, fputs(const char *s, FILE *stream));
COBALT_DECL(int, putchar(int c));
COBALT_DECL(int, fputc(int c, FILE *stream));
COBALT_DECL(size_t,
COBALT_DECL(int, fclose(FILE *stream));
COBALT_DECL(void, free(void *ptr));
COBALT_DECL(void *, malloc(size_t size));
COBALT_DECL(void, syslog(int priority, const char *fmt, ...));
COBALT_DECL(void, vsyslog(int priority,
COBALT_DECL(void, __vsyslog_chk(int priority, int level,
COBALT_DECL(void, __syslog_chk(int pri, int flag,
COBALT_DECL(int, clock_getres(clockid_t clock_id,
COBALT_DECL(int, clock_gettime(clockid_t clock_id,
COBALT_DECL(int, clock_settime(clockid_t clock_id,
COBALT_DECL(int, clock_nanosleep(clockid_t clock_id,
COBALT_DECL(time_t, time(time_t *t));
COBALT_DECL(int, nanosleep(const struct timespec *rqtp,
COBALT_DECL(int, timer_create(clockid_t clockid,
COBALT_DECL(int, timer_delete(timer_t timerid));
COBALT_DECL(int, timer_settime(timer_t timerid,
COBALT_DECL(int, timer_gettime(timer_t timerid,
COBALT_DECL(int, timer_getoverrun(timer_t timerid));
COBALT_DECL(ssize_t, read(int fd, void *buf, size_t nbyte));
COBALT_DECL(ssize_t, write(int fd, const void *buf, size_t nbyte));
COBALT_DECL(int, close(int fildes));
COBALT_DECL(unsigned int, sleep(unsigned int seconds));
#define COBALT_DECL(T, P)	\

olej@Cobalt ~/2018_WORKS/Triol/xenomai-3/include/cobalt $ cat *.h | grep COBALT_DECL | wc -l
91
Вот эти 90 системных вызовов.

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 08 май 2018, 20:08

Olej писал(а): 4. можем писать realtime приложения в стандартном API POSIX, когда Xenomai маскирует многие системные вызовы Linux;
При этом мы пишем приложение совершенно в POSIX API ... всё зависит от того как мы его собираем (Makefile): с Xenomai - это буде realtime приложение, без - обычное Linux приложение, полностью эквивалентное.

Пример кода (совершенно draft - не смотрим что там делается + как это написано):

Код: Выделить всё

#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <time.h>
#include <pthread.h>
#include <sys/syscall.h>

#include <stdio.h>
#include <sys/mman.h>   /* for MCL_CURRENT and MCL_FUTURE */
#include <fcntl.h>

#define DEVICE_NAME     "udooGpio-0"
void* print_time (void*);

char buf[1024];
ssize_t size;
int device;
int ret;
int gpio_value=0;
long long freq_mks;
timer_t timer1;
pthread_t thread;

int main( int argc, char *argv[] ) {
    if( argc != 2 ) {
        fprintf( stderr, "Использование: %s <freq_mks> <nsecs>\n", argv[ 0 ] );
        exit( EXIT_FAILURE );
    }
    freq_mks = atoll( argv[ 1 ] );
    if( freq_mks < 100 ) {
        fprintf( stderr, "Error parametr enter >100  exit: %s <freq_mks> <nsecs>\n", argv[0] );
        exit( EXIT_FAILURE );
    }
    pthread_create(&thread, NULL, print_time, NULL);
   /* no memory-swapping for this programm */
   ret = mlockall(MCL_CURRENT | MCL_FUTURE);
   if( ret ) {
      perror( "ERROR : mlockall has failled" );
      exit( 1 );
   }
   /* open the device */
   device = open( DEVICE_NAME, O_RDWR );
   if( device < 0 ) {
      ret = close( device );
      printf( "ERROR : can't open device %s (%s)\n",
              DEVICE_NAME, strerror( -device ) );
      exit( 1 );
   }
   pthread_join( thread, NULL );
   ret = close( device );
   if( ret < 0 ) {
      printf( "ERROR : can't close device %s (%s)\n",
              DEVICE_NAME, strerror(-ret));
      exit( 1 );
   }
   exit( EXIT_SUCCESS );
}

void* print_time( void* args ) {
     struct timespec tp;
     char buffer [80];
     struct itimerspec new_value, old_value;
     struct sigaction action;
     struct sigevent sevent;
     sigset_t set;
     int signum = SIGALRM;

     sevent.sigev_notify = SIGEV_THREAD_ID;
     sevent.sigev_notify_thread_id = syscall( __NR_gettid );
     sevent.sigev_signo = signum;

     sigemptyset( &set );
     sigaddset( &set, signum );
     sigprocmask( SIG_BLOCK, &set, NULL );

     if( timer_create (CLOCK_MONOTONIC, &sevent, &timer1 ) == -1 )
         perror ("timer_create");

     new_value.it_interval.tv_sec = 0;
     new_value.it_interval.tv_nsec = freq_mks*1000;  // 100_000_000 = 100 ms
     new_value.it_value.tv_sec = 1;
     new_value.it_value.tv_nsec = 0;

     if( timer_settime( timer1, 0, &new_value, &old_value ) == -1 )
         perror( "timer_settime" );

     while(1){
         ///* wait for signal (1 s) */
         if( sigwait( &set, &signum) == -1 )
             perror( "sigwait" );

         if( clock_gettime( CLOCK_MONOTONIC, &tp ) == -1 )
             perror ( "clock_gettime" );

         buf[ 0 ] = gpio_value;
         size = write( device, (const void *)buf, 1024 + 1 );
	 gpio_value = !gpio_value;
         
     }
}
Обращаем внимание, что среди #include - только POSIX заголовочные файлы, никаких Xenomai!
А вот как это должно собираться для realtime - Makefile:

Код: Выделить всё

XENO_CONFIG := /usr/xenomai/bin/xeno-config
CFLAGS := $(shell $(XENO_CONFIG)   --skin=posix --cflags)
LDFLAGS := $(shell $(XENO_CONFIG)  --skin=posix --ldflags)
EXTRA_CFLAGS:=-I/usr/xenomai/include  -I/usr/xenomai/include/trank/posix -I/usr/xenomai/include/cobalt
CC := $(shell $(XENO_CONFIG) --cc)  
EXECUTABLE := posix_timer

all: $(EXECUTABLE)

%: %.c
	$(CC) -o $@ $< $(CFLAGS) $(LDFLAGS)

clean: 
	rm -f $(EXECUTABLE)
Обратите внимание, что опции сборки радикально поменялись по сравнению с нативной сборкой!
И всё это готово для исполнения ... хотя в показанном draft-е нет соответствующего драйвера и устройства:

Код: Выделить всё

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/posix_timer $ export LD_LIBRARY_PATH=/usr/xenomai/lib

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/posix_timer $ echo $LD_LIBRARY_PATH=/usr/xenomai/lib

olej@Cobalt ~/2018_WORKS/Triol/Xen_works/posix_timer $ ./posix_timer 2000
ERROR : can't open device udooGpio-0 (Operation not permitted)
Эта ошибка - неважно ... но при этом начинает выполняться realtime Linux приложение!

Аватара пользователя
Olej
Писатель
Сообщения: 21338
Зарегистрирован: 24 сен 2011, 14:22
Откуда: Харьков
Контактная информация:

Re: Xenomai и real-time

Непрочитанное сообщение Olej » 08 май 2018, 20:11

Olej писал(а): Идея состоит в том, что основные системные (man -s2 ...) вызовы поступают не в Linux kernel, а для них написаны оболочки (wrappers) и они перенапраяляются в микроядро Xenomai, там модифицируются, после чего отправляются в ядро Linux.
Документация по POSIX-интерфейсу Xenomai здесь: Xenomai 3.0.6. POSIX interface.

Там же пример того, как условной трансляцией в коде, собираемом даже под Xenomai обёртки системных вызовов, можно делать вызовы к изначальным Linux/POSIX API:

Код: Выделить всё

 /* Open a plain Linux UDP socket. */
 #ifndef __XENO__
       fd = socket(PF_INET, SOCK_DGRAM, 0);
 #else /* __XENO__ */
       fd = __real_socket(PF_INET, SOCK_DGRAM, 0);
 #endif /* __XENO__ */
P.S. т.е. это не совсем там же, но рядом - Use of Linux original services.

Покопаться с конкретными примерами пользовательских приложений realtime под Xenomai здесь:
Xenomai (но текст сопутствующий там на нидерландском/голландском языке).
И здесь Xenomai 3 Exercises + краткие сопроводительные комментарии к этим примерам: Real-time Linux (Xenomai), Background.

Ответить

Вернуться в «Linux изнутри»

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 5 гостей