Linux Kernel Library: ядро Linux в форм-факторе so или dll

    Когда-то читал статью о выборе файловых систем «чтоб везде-везде работало». В ней в очередной раз увидел жалобы, что Ext4 замечательная файловая система, но на Windows есть только кривые неточные проприетарные драйверы. Но отмотаем ленту ещё на пару лет назад: тогда на Хабре (а в те времена — Гиктаймсе) пролетала новость про LibOS — попытку превратить Linux kernel в обычную библиотеку пользовательского режима. Упор там делался на вынос сетевого стека в user space. Как-то раз я решил поглядеть, а жив ли вообще проект, и в их блоге увидел ссылку на своего рода конкурента — проект Linux Kernel Library (LKL). По сути, это порт ядра, так сказать, на аппаратную архитектуру «библиотека пользовательского режима POSIX / Win32».


    Чем интересна LKL? Во-первых тем, что она живёт и здравствует, пусть и не в основной кодовой базе ядра. Во-вторых, это более-менее честная поддержка «архитектуры», автоматически делающая доступной бОльшую часть ядра. Более того, прямо в комплекте идут утилиты-примеры: cptofs/cpfromfs, fs2tar, lklfuse. В этой статье мы протестируем LKL на хостовом Linux, заглянем в файл с образом Ext4 (Btrfs, XFS...) без рута и виртуалок и коротко обсудим, как её можно попробовать на Windows.


    DISCLAIMER 1: Захотите попробовать — делайте бекапы. Если вы захотите проделать такое с разделом с важными данными — на свой страх и риск. Впрочем, здесь хотя бы драйверы будут реально родные.


    DISCLAIMER 2: Уважайте лицензии. Вероятно, линковка с LKL делает вашу программу GPL'ной.


    Первичное знакомство


    Репозиторий LKL (lkl/linux на GitHub) представляет из себя форк обычного Linux kernel, в котором добавлена поддержка ещё одной архитектуры, в основном мы будет видеть это в каталогах arch/lkl и tools/lkl. Сделаем клон репозитория и попробуем собрать по инструкции. Для экспериментов я буду использовать shallow clone, который содержит не всю историю репозитория, а лишь указанное количество последних коммитов:


    $ git clone https://github.com/lkl/linux.git lkl-linux --depth 10
    $ cd lkl-linux
    $ patch -p 1 <<EOF
    diff --git a/tools/lkl/lib/hijack/xlate.c b/tools/lkl/lib/hijack/xlate.c
    index 03ccc6294..75368dcc2 100644
    --- a/tools/lkl/lib/hijack/xlate.c
    +++ b/tools/lkl/lib/hijack/xlate.c
    @@ -3,6 +3,7 @@
     #include <fcntl.h>
     #include <sys/ioctl.h>
     #include <sys/socket.h>
    +#include <linux/sockios.h>
     #undef st_atime
     #undef st_mtime
     #undef st_ctime
    EOF
    $ make -C tools/lkl -j4

    Пришлось чуточку поправить исходник, но в итоге получилась библиотека tools/lkl/lib/liblkl.so (а ещё — статическая tools/lkl/liblkl.a):


    nm -D tools/lkl/lib/liblkl.so
                     U __assert_fail
                     U bind
                     U calloc
                     U clock_gettime
                     U close
                     w __cxa_finalize
    0000000000063b30 T dbg_entrance
    0000000000063f30 T dbg_handler
                     U __errno_location
                     U fcntl
                     U fdatasync
    0000000000639580 D fd_net_ops
                     U fgets
                     U __fprintf_chk
                     U free
                     U fwrite
                     U getc
                     U getenv
                     w __gmon_start__
                     U if_nametoindex
                     U inet_pton
                     U ioctl
                     U __isoc99_scanf
                     w _ITM_deregisterTMCloneTable
                     w _ITM_registerTMCloneTable
    0000000000061750 T jmp_buf_longjmp
    0000000000061720 T jmp_buf_set
    0000000000065470 T jsmn_init
    0000000000065060 T jsmn_parse
    0000000000065490 T jsmn_strerror
    00000000000614c0 T lkl_add_gateway
    0000000000061290 T lkl_add_neighbor
    00000000000621a0 T lkl_bug
    000000000005f070 T lkl_closedir
    0000000000639520 D lkl_dev_blk_ops
    000000000005fa10 T lkl_dirfd
    0000000000062640 T lkl_disk_add
    0000000000062780 T lkl_disk_remove
    000000000005ec50 T lkl_encode_dev_from_sysfs
    000000000005f9f0 T lkl_errdir
    000000000005ef80 T lkl_fdopendir
    0000000000067f10 T lkl_get_free_irq
    000000000005f2c0 T lkl_get_virtio_blkdev
    00000000006395c0 D lkl_host_ops
    00000000000614b0 T lkl_if_add_gateway
    00000000000613e0 T lkl_if_add_ip
    00000000000614a0 T lkl_if_add_linklocal
    0000000000061520 T lkl_if_add_rule_from_saddr
    0000000000061480 T lkl_if_del_ip
    0000000000060d70 T lkl_if_down
    0000000000060b10 T lkl_ifname_to_ifindex
    0000000000061400 T lkl_if_set_ipv4
    0000000000061530 T lkl_if_set_ipv4_gateway
    0000000000061430 T lkl_if_set_ipv6
    00000000000615b0 T lkl_if_set_ipv6_gateway
    0000000000060ef0 T lkl_if_set_mtu
    0000000000060bf0 T lkl_if_up
    0000000000061160 T lkl_if_wait_ipv6_dad
    000000000005fba0 T lkl_iomem_access
    000000000005fb50 T lkl_ioremap
    0000000000067730 T lkl_is_running
    0000000000066150 T lkl_load_config_env
    0000000000065950 T lkl_load_config_json
    0000000000066880 T lkl_load_config_post
    0000000000066510 T lkl_load_config_pre
    000000000005f470 T lkl_mount_dev
    000000000005eae0 T lkl_mount_fs
    00000000000642a0 T lkl_netdev_add
    00000000000645c0 T lkl_netdev_free
    0000000000061030 T lkl_netdev_get_ifindex
    0000000000064e70 T lkl_netdev_macvtap_create
    0000000000064ed0 T lkl_netdev_pipe_create
    0000000000064ce0 T lkl_netdev_raw_create
    00000000000644c0 T lkl_netdev_remove
    0000000000064c60 T lkl_netdev_tap_create
    0000000000064a10 T lkl_netdev_tap_init
    000000000005eea0 T lkl_opendir
    0000000000062170 T lkl_perror
    00000000000620b0 T lkl_printf
    0000000000067f90 T lkl_put_irq
    0000000000061620 T lkl_qdisc_add
    0000000000061630 T lkl_qdisc_parse_add
    000000000005f0f0 T lkl_readdir
    0000000000063f80 T lkl_register_dbg_handler
    0000000000064930 T lkl_register_netdev_fd
    000000000005efe0 T lkl_rewinddir
    000000000005fa20 T lkl_set_fd_limit
    00000000000614e0 T lkl_set_ipv4_gateway
    0000000000061500 T lkl_set_ipv6_gateway
    0000000000065f60 T lkl_show_config
    00000000004f51ad T lkl_start_kernel
    0000000000062080 T lkl_strerror
    00000000000685f0 T lkl_syscall
    0000000000062270 T lkl_sysctl
    0000000000062410 T lkl_sysctl_parse_write
    0000000000067770 T lkl_sys_halt
    00000000000680e0 T lkl_trigger_irq
    000000000005f870 T lkl_umount_dev
    000000000005edc0 T lkl_umount_timeout
    0000000000066ed0 T lkl_unload_config
    00000000008186a0 B lkl_virtio_devs
                     U __longjmp_chk
                     U lseek64
                     U malloc
                     U memchr
                     U memcpy
                     U memset
                     U open
                     U perror
                     U pipe
                     U poll
    0000000000064070 T poll_thread
                     U pread64
                     U __printf_chk
                     U pthread_create
                     U pthread_detach
                     U pthread_exit
                     U pthread_getspecific
                     U pthread_join
                     U pthread_key_create
                     U pthread_key_delete
                     U pthread_mutexattr_init
                     U pthread_mutexattr_settype
                     U pthread_mutex_destroy
                     U pthread_mutex_init
                     U pthread_mutex_lock
                     U pthread_mutex_unlock
                     U pthread_self
                     U pthread_setspecific
                     U puts
                     U pwrite64
                     U read
                     U readv
    00000000008196a0 B registered_devs
    000000000005fa90 T register_iomem
                     U sem_destroy
                     U sem_init
                     U sem_post
                     U sem_wait
                     U _setjmp
                     U setsockopt
                     U sigaction
                     U sigemptyset
                     U __snprintf_chk
                     U socket
                     U __stack_chk_fail
                     U stderr
                     U stdin
                     U stpcpy
                     U strchr
                     U strcpy
                     U __strcpy_chk
                     U strdup
                     U strerror
                     U strlen
                     U strncat
                     U __strncat_chk
                     U strncmp
                     U strncpy
                     U strrchr
                     U strtok
                     U strtok_r
                     U strtol
                     U strtoul
                     U syscall
                     U timer_create
                     U timer_delete
                     U timer_settime
    000000000005fb00 T unregister_iomem
                     U usleep
    0000000000063110 T virtio_dev_cleanup
    0000000000062ee0 T virtio_dev_setup
    0000000000063100 T virtio_get_num_bootdevs
    0000000000062c10 T virtio_process_queue
    0000000000062af0 T virtio_req_complete
    0000000000062ec0 T virtio_set_queue_max_merge_len
                     U __vsnprintf_chk
                     U write
                     U writev

    А где же системные вызовы, спросите вы. Без паники, они спрятаны за общей точкой входа lkl_syscall. Это такой аналог функции syscall для LKL. В реальной же ситуации в большинстве случаев вы будете использовать типизированные обёртки lkl_sys_<name>. Также мы видим всякие функции для настройки «ядра», добавления в него виртуальных устройств, а также обёртки над «сложными» системными вызовами, в обычной системе предоставляемые libc. Например, есть такой системный вызов getdents, но… «These are not the interfaces you are interested in.» — с порога говорит нам man-страница. В обычных же случаях предполагается использовать стандартную библиотечную функцию readdir (3), но не путайте её с readdir (2) — древним системным вызовом, который на x86_64 даже не реализован. В случае же работы с LKL вам потребуются обёртки lkl_opendir / lkl_readdir / lkl_closedir.


    Попробуем что-нибудь написать


    Напоминаю, уважайте лицензии. Сам Linux kernel распространяется под GPL2, будет ли программа, дёргающая за относительно публичные интерфейсы LKL считаться производной работой — я не знаю.


    Что же, давайте попробуем слинковаться с библиотекой. Предполагается, что переменной $LKL присвоен путь до репозитория со скомпилированной LKL.


    #include <stdio.h>
    
    #include "lkl_host.h"
    #include "lkl.h"
    
    int main()
    {
        // lkl_host_ops содержит указатели на функции для различных
        //     "платформенно-зависимых" операций: `printk`, `panic`, ...
        // Строка, передаваемая вторым аргументом -- полноценная командная строка ядра
        lkl_start_kernel(&lkl_host_ops, "mem=128M");
    
        return 0;
    }

    Скомпилируем:


    $ gcc test.c -o test -I$LKL/tools/lkl/include -L$LKL/tools/lkl/lib -llkl

    И оно работает!


    $ ./test
    ./test: error while loading shared libraries: liblkl.so: cannot open shared object file: No such file or directory
    $ LD_LIBRARY_PATH=$LKL/tools/lkl/lib ./test
    [    0.000000] Linux version 5.3.0+ (trosinenko@trosinenko-pc) (gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)) #1 Tue Dec 3 14:37:02 MSK 2019
    [    0.000000] memblock address range: 0x7fba8c000000 - 0x7fba93fff000
    [    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 32319
    [    0.000000] Kernel command line: mem=128M
    [    0.000000] Dentry cache hash table entries: 16384 (order: 5, 131072 bytes, linear)
    [    0.000000] Inode-cache hash table entries: 8192 (order: 4, 65536 bytes, linear)
    [    0.000000] mem auto-init: stack:off, heap alloc:off, heap free:off
    [    0.000000] Memory available: 129044k/131068k RAM
    [    0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
    [    0.000000] NR_IRQS: 4096
    [    0.000000] lkl: irqs initialized
    [    0.000000] clocksource: lkl: mask: 0xffffffffffffffff max_cycles: 0x1cd42e4dffb, max_idle_ns: 881590591483 ns
    [    0.000000] lkl: time and timers initialized (irq1)
    [    0.000003] pid_max: default: 4096 minimum: 301
    [    0.000019] Mount-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
    [    0.000022] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes, linear)
    [    0.003622] random: get_random_bytes called from _etext+0xbcdb/0x14b05 with crng_init=0
    [    0.003692] printk: console [lkl_console0] enabled
    [    0.003707] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
    [    0.003714] xor: automatically using best checksumming function   8regs
    [    0.003783] NET: Registered protocol family 16
    [    0.171647] raid6: int64x8  gen()  4489 MB/s
    [    0.343119] raid6: int64x8  xor()  3165 MB/s
    [    0.514836] raid6: int64x4  gen()  4668 MB/s
    [    0.689529] raid6: int64x4  xor()  3256 MB/s
    [    0.861155] raid6: int64x2  gen()  6283 MB/s
    [    1.032668] raid6: int64x2  xor()  3793 MB/s
    [    1.206752] raid6: int64x1  gen()  5185 MB/s
    [    1.378219] raid6: int64x1  xor()  2901 MB/s
    [    1.378225] raid6: using algorithm int64x2 gen() 6283 MB/s
    [    1.378227] raid6: .... xor() 3793 MB/s, rmw enabled
    [    1.378229] raid6: using intx1 recovery algorithm
    [    1.378333] clocksource: Switched to clocksource lkl
    [    1.378427] NET: Registered protocol family 2
    [    1.378516] tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes, linear)
    [    1.378521] TCP established hash table entries: 1024 (order: 1, 8192 bytes, linear)
    [    1.378527] TCP bind hash table entries: 1024 (order: 1, 8192 bytes, linear)
    [    1.378532] TCP: Hash tables configured (established 1024 bind 1024)
    [    1.378596] UDP hash table entries: 128 (order: 0, 4096 bytes, linear)
    [    1.378618] UDP-Lite hash table entries: 128 (order: 0, 4096 bytes, linear)
    [    1.379286] workingset: timestamp_bits=62 max_order=16 bucket_order=0
    [    1.380271] SGI XFS with ACLs, security attributes, no debug enabled
    [    1.380864] io scheduler mq-deadline registered
    [    1.380872] io scheduler kyber registered
    [    1.383396] NET: Registered protocol family 10
    [    1.383763] Segment Routing with IPv6
    [    1.383779] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
    [    1.384091] Btrfs loaded, crc32c=crc32c-generic
    [    1.384223] Warning: unable to open an initial console.
    [    1.384237] This architecture does not have kernel memory protection.
    [    1.384239] Run /init as init process

    Можно даже видеть по timestamp'ам, что ядро не просто «выплюнуло» в консоль этот текст, а красиво постепенно грузилось как настоящее.


    Усложняем эксперимент


    Давайте теперь попробуем как-то по-настоящему использовать эту библиотеку — всё-таки целое ядро ОС! Попробуем чисто в user space прочитать файл с Ext4-раздела. Причём «родным» драйвером! За основу возьмём tools/lkl/cptofs.c и реализуем только самое необходимое (для наглядности):


    #undef NDEBUG
    
    #include <stdio.h>
    #include <stdint.h>
    #include <string.h>
    #include <assert.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <stdlib.h>
    
    #include "lkl_host.h"
    #include "lkl.h"
    
    // Обработка ошибок показана не везде и кое как,
    // чтобы не загромождать исходник -- не повторяйте этого дома :)
    
    int main(int argc, const char *argv[])
    {
      const char * const fsimage = argv[1];
      const char * const fstype = argv[2];
      const char * const file_to_dump = argv[3];
    
      struct lkl_disk disk;
      int disk_id, ret;
      char mpoint[128];
    
      // Открываем файл с образом диска
      memset(&disk, 0, sizeof(disk));
      disk.fd = open(fsimage, O_RDONLY);
      assert(disk.fd >= 0);
    
      // Подцепляем его как блочное устройство
      disk_id = lkl_disk_add(&disk);
      assert(disk_id >= 0);
    
      // Запускаем ядро
      lkl_start_kernel(&lkl_host_ops, "mem=128M");
    
      // Монтируем раздел на блочном устройстве
      ret = lkl_mount_dev(disk_id, 0 /* part */, fstype,
                          LKL_MS_RDONLY, NULL,
                          mpoint, sizeof(mpoint));
    
      if (ret < 0) {
        fprintf(stderr, "lkl_mount_dev failed: %s\n", lkl_strerror(ret));
        close(disk.fd);
        exit(1);
      }
    
      // Так, что тут у нас...
      // (воспользуемся псевдо-libc обёртками)
      struct lkl_dir *dir = lkl_opendir(mpoint, &ret);
      struct lkl_linux_dirent64 *dent;
      while ((dent = lkl_readdir(dir)) != NULL) {
        fprintf(stderr, "Directory entry: %s\n", dent->d_name);
      }
      // тут нужно было бы понять: NULL -- это ошибка или конец каталога...
      lkl_closedir(dir);
    
      // Попробуем прочитать что-нибудь
      // Здесь используем обёртки над непосредственными системными вызовами
      char tmp[256];
      uint8_t buffer[65536];
      snprintf(tmp, sizeof(tmp), "%s/%s", mpoint, file_to_dump);
      int fd = lkl_sys_open(tmp, LKL_O_RDONLY, 0);
      fprintf(stderr, "fd = %d\n", fd);
      assert(fd >= 0);
      int count = lkl_sys_read(fd, buffer, sizeof(buffer));
      /* хостовый */ write(STDERR_FILENO, buffer, count);
      lkl_sys_close(fd);
    
      return 0;
    }
    

    Обратите внимание на переименованные define'ы с префиксами LKL_ (например, LKL_O_RDONLY): на Linux-хосте они, скорее всего, совпадают с теми, что без префиксов, а вот на других системах — не факт.


    $ mke2fs ext4.img -t ext4 32M
    $ sudo mount ext4.img /mnt
    $ echo -e "Hello world\!\nTEST" | sudo tee /mnt/test.txt
    $ sudo umount /mnt
    $ LD_LIBRARY_PATH=$LKL/tools/lkl/lib ./read-file ext4.img ext4 test.txt
    [    0.000000] Linux version 5.3.0+ (trosinenko@trosinenko-pc) (gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)) #1 Tue Dec 3 14:37:02 MSK 2019
    // ... //
    [    1.378960] Warning: unable to open an initial console.
    [    1.378975] This architecture does not have kernel memory protection.
    [    1.378977] Run /init as init process
    [    1.379852] EXT4-fs (vda): mounted filesystem with ordered data mode. Opts:
    Directory entry: test.txt
    Directory entry: ..
    Directory entry: lost+found
    Directory entry: .
    fd = 0
    Hello world\!
    TEST

    Ух ты, работает! А что-нибудь более экзотическое?


    $ mksquashfs test.c read-file.c squashfs.img
    $ LD_LIBRARY_PATH=$LKL/tools/lkl/lib ./read-file squashfs.img squashfs test.c
    [    0.000000] Linux version 5.3.0+ (trosinenko@trosinenko-pc) (gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)) #1 Tue Dec 3 14:37:02 MSK 2019
    // ... //
    [    1.378472] This architecture does not have kernel memory protection.
    [    1.378474] Run /init as init process
    lkl_mount_dev failed: No such device

    Ой! Хотя, постойте, мы же, наверное, просто не включили в наше ядро-библиотеку поддержку SquashFS!


    Настраиваем параметры сборки LKL


    Для себя я выработал такую последовательность команд, которая работает для LKL — возможно, её можно сократить вплоть до традиционного make defconfig, make menuconfig, make.


    $ make defconfig ARCH=lkl
    $ make menuconfig ARCH=lkl
    //// тут включаем SquashFS и выходим с сохранением конфигурации
    $ cp .config arch/lkl/configs/defconfig
    $ make mrproper
    $ make -C tools/lkl -j4 # Это мы уже видели

    И вуаля!


    $ gcc read-file.c -o read-file -I$LKL/tools/lkl/include -L$LKL/tools/lkl/lib -llkl
    $ LD_LIBRARY_PATH=$LKL/tools/lkl/lib ./read-file squashfs.img squashfs test.c
    [    0.000000] Linux version 5.3.0+ (trosinenko@trosinenko-pc) (gcc version 9.2.1 20191008 (Ubuntu 9.2.1-9ubuntu2)) #1 Wed Dec 4 12:07:50 MSK 2019
    // ... //
    [    1.378346] This architecture does not have kernel memory protection.
    [    1.378348] Run /init as init process
    Directory entry: .
    Directory entry: ..
    Directory entry: read-file.c
    Directory entry: test.c
    fd = 0
    #include <stdio.h>
    
    #include "lkl_host.h"
    #include "lkl.h"
    
    int main()
    {
        lkl_start_kernel(&lkl_host_ops, "mem=128M");
    
        return 0;
    }

    В данном случае, правда, даже перекомпилировать read-file.c едва ли было нужно — библиотека-то динамическая.


    Позвольте, а где обещанные готовые программки?


    И действительно, в каталоге tools/lkl лежат cptofs.c, fs2tar.c и ещё много интересного, но оно не собирается! Порывшись в Makefile'ах я обнаружил, что есть некий Makefile.autoconf, который ищет требуемые заголовочные файлы, и Makefile.conf, куда это всё записывается.


    Так-с, кто-то хочет libarchive, кто-то libfuse — ну что же, поставим libarchive-dev, libfuse-dev (в случае Ubuntu) и пересоберём. Всё равно не получается… А если удалить Makefile.conf… Опа, собралось!


    Итак, что же теперь у нас есть? Теперь в каталоге tools/lkl у нас есть cptofs, fs2tar и lklfuse.


    Для начала скопируем cptofs под именем cpfromfs:


    $ $LKL/tools/lkl/cptofs --help
    Usage: cptofs [OPTION...] -t fstype -i fsimage path... fs_path
    Copy files to a filesystem image
    
      -i, --filesystem-image=string   path to the filesystem image - mandatory
      -p, --enable-printk        show Linux printks
      -P, --partition=int        partition number
      -s, --selinux=string       selinux attributes for destination
      -t, --filesystem-type=string   select filesystem type - mandatory
      -?, --help                 Give this help list
          --usage                Give a short usage message
    
    Mandatory or optional arguments to long options are also mandatory or optional
    for any corresponding short options.
    $ cp $LKL/tools/lkl/cp{to,from}fs
    $ $LKL/tools/lkl/cpfromfs --help
    Usage: cpfromfs [OPTION...] -t fstype -i fsimage fs_path... path
    Copy files from a filesystem image
    
      -i, --filesystem-image=string   path to the filesystem image - mandatory
      -p, --enable-printk        show Linux printks
      -P, --partition=int        partition number
      -s, --selinux=string       selinux attributes for destination
      -t, --filesystem-type=string   select filesystem type - mandatory
      -?, --help                 Give this help list
          --usage                Give a short usage message
    
    Mandatory or optional arguments to long options are also mandatory or optional
    for any corresponding short options.

    Как говорится, «Как вы яхту назовёте...». Запускаем...


    $ $LKL/tools/lkl/cpfromfs -t ext4 -i ext4.img test.txt .
    error processing entry /mnt/0000fe00/test.txt, aborting

    Хмм… Надо посмотреть… Впрочем, для интерактивного использования оно всё равно неудобно, поскольку каждый раз приходится ждать около секунды, пока ядро загрузится. Зато fs2tar работает без проблем:


    $ $LKL/tools/lkl/fs2tar -t ext4 ext4.img ext4.tar
    $ tar -tf ext4.tar
    tar: Удаляется начальный `/' из имен объектов
    /test.txt
    /lost+found/

    Но самая интересная программа здесь на мой взгляд — это lklfuse:


    $ mkdir mountpoint
    $ $LKL/tools/lkl/lklfuse -o type=ext4 ext4.img mountpoint/
    $ ls mountpoint/
    lost+found  test.txt
    $ mount
    sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
    proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
    ... ещё много всего, потому что это таблица монтирования хоста
    /dev/fuse on /run/user/1000/doc type fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
    lklfuse on /path/to/mountpoint type fuse.lklfuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000)
    $ echo ABC > mountpoint/ABC.XYZ
    $ umount mountpoint
    $ sudo mount ext4.img /mnt
    $ ls /mnt
    $ cat /mnt/ABC.XYZ
    ABC

    По-моему, впечатляет: можно без рута (но тут зависит от настроек системы) подмонтировать файловую систему через FUSE, поработать с ней, отмонтировать — а потом подключить к хостовому ядру (уже с рутом) и продолжить, как ни в чём не бывало.


    Мало того, что lklfuse позволяет обычному пользователю подмонтировать раздел с помощью штатного драйвера ядра. Хостовое ядро вообще не обязано быть собрано с поддержкой этой ФС. Да что уж там, не удивлюсь, если это всё точно так же заведётся на OS X.


    Немного про кросс-платформенность


    А что же с доступом к линуксовым ФС из других операционных систем? На OS X, думаю, будет попроще: всё-таки она полноценный UNIX, да и поддержка FUSE, вроде, есть. Так что есть надежда, что оно заведётся с ходу. Если нет, я бы посмотрел в сторону проверки того, везде ли в системные вызовы LKL передаются константы с префиксами LKL_, а не их хостовые аналоги.


    С Windows несколько сложнее: во-первых, там банально может не быть некоторых привычных в мире UNIX библиотек (например, для разбора аргументов командной строки). Во-вторых, нужно понять, как подмонтироваться к хостовому дереву файловых систем. Самое простое было бы — так же через FUSE. Говорят, когда-то был некий Dokan, сейчас тоже что-то есть, но нужно гуглить. Главное, что сама LKL на Windows собирается, нужно только учесть, что ей требуется 64-битный тип long для работы в 64-битном режиме, поэтому не каждый компилятор подойдёт (по крайней мере, так написано в текущем readme проекта).

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

    Комментарии 5

      0
      Не собирается на OS X(
      ну по крайней мере сходу
      make -C tools/lkl -j4
      AUTOCONF /Users/stavinsky/temp/linux-master/tools/lkl/Makefile.conf
      ld: unknown option: -print-output-format
      ld: unknown option: -print-output-format
      ld: unknown option: -print-output-format
      ld: unknown option: -print-output-format
      arch/lkl/Makefile:18: *** Unrecognized platform: . Stop.
      make[1]: *** [sub-make] Error 2
        +1

        Возможно, LKL рассчитывает на GNU ld, а вас, может, lld или GNU ld древней версии… Это, конечно, может вызвать проблемы и далее, но конкретно в этом случае есть ощущение, что оно просто проверяет: на Винде мы или на Юниксе — можно просто закомментировать пока лишнюю ветвь, и если вдруг остальное заработает — можно им issue написать.


        PS: не знаю, как с lld, а clang'ом свежее ядро вполне собирается.

        0

        Смотрела на этот проект 2 года назад, создалось ощущение что проект практически запущен ( не поддерживантся), не говоря уже о том как часто обновляется ядро, учитывая все обнаруженные уязвимости. Сама идея замечательная!

          +1

          Не путаете ли вы его с LibOS? Тот уже пару лет назад выглядел запущенным, а LKL более-менее обновляется: сейчас в него вмержена версия 5.3+, если верить логам против актуальной 5.4.2 — тоже, конечно, не идеально, но и совсем запущенным не назовёшь. Хотя, в какие-то периоды, действительно, создавалось ощущение застоя. А уязвимости — это, конечно, грустно.

          0

          -

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

          Самое читаемое