Ինչպես սկսել Linux-ում օգտագործողի ռեժիմի օգտագործումը

Ներածություն թարգմանչից. Տարբեր տեսակի բեռնարկղերի մեր կյանք զանգվածային մուտքի ֆոնին կարող է բավականին հետաքրքիր և օգտակար լինել պարզել, թե ինչ տեխնոլոգիաներով է ամեն ինչ սկսվել մեկ անգամ: Նրանցից ոմանք կարող են օգտակար օգտագործվել մինչ օրս, բայց ոչ բոլորն են հիշում նման մեթոդները (կամ գիտեն, թե արդյոք դրանք չեն բռնվել դրանց արագ զարգացման ընթացքում): Այդպիսի տեխնոլոգիաներից մեկը User Mode Linux-ն է: Բնօրինակի հեղինակը շատ է փորել՝ պարզելով, թե հին մշակումներից որն է դեռ աշխատում, որը՝ ոչ, և հավաքել է քայլ առ քայլ հրահանգի նման մի բան, թե ինչպես ինքներդ ձեզ ձեռք բերել homebrew UML 2k19-ում: Եվ այո, սկզբնական գրառման հեղինակին հրավիրել ենք Հաբր Քեյդի, այնպես որ, եթե հարցեր ունեք, մեկնաբանություններում հարցրեք անգլերենով։

Ինչպես սկսել Linux-ում օգտագործողի ռեժիմի օգտագործումը

Օգտագործողի ռեժիմը Linux-ում, փաստորեն, Linux միջուկի մի նավահանգիստ է իր համար: Այս ռեժիմը թույլ է տալիս գործարկել Linux-ի ամբողջական միջուկը որպես օգտագործողի գործընթաց և սովորաբար օգտագործվում է մշակողների կողմից՝ վարորդների փորձարկման համար: Բայց այս ռեժիմը նաև օգտակար է որպես ընդհանուր մեկուսացման գործիք, որի սկզբունքը նման է վիրտուալ մեքենաների աշխատանքին։ Այս ռեժիմը ապահովում է ավելի շատ մեկուսացում, քան Docker-ը, բայց ավելի քիչ, քան լիարժեք վիրտուալ մեքենան, ինչպիսին է KVM-ը կամ Virtual Box-ը:

Ընդհանուր առմամբ, Օգտվողի ռեժիմը կարող է թվալ տարօրինակ և դժվար օգտագործման գործիք, բայց այն դեռ ունի իր կիրառությունները: Ի վերջո, սա լիարժեք Linux միջուկ է, որն աշխատում է ոչ արտոնյալ օգտվողից: Այս հատկությունը թույլ է տալիս պոտենցիալ անվստահելի կոդը գործարկել առանց հոսթ մեքենայի համար որևէ սպառնալիքի: Եվ քանի որ սա լիարժեք միջուկ է, դրա գործընթացները մեկուսացված են հյուրընկալող մեքենայից, այսինքն. Օգտատիրոջ ռեժիմում աշխատող գործընթացները տեսանելի չեն լինի հոսթին. Սա սովորական Docker կոնտեյների նման չէ, որի դեպքում հյուրընկալող մեքենան միշտ տեսնում է պահեստի ներսում գտնվող գործընթացները: Նայեք այս pstree-ի հատվածին իմ սերվերներից մեկից.

containerd─┬─containerd-shim─┬─tini─┬─dnsd───19*[{dnsd}]
           │                 │      └─s6-svscan───s6-supervise
           │                 └─10*[{containerd-shim}]
           ├─containerd-shim─┬─tini─┬─aerial───21*[{aerial}]
           │                 │      └─s6-svscan───s6-supervise
           │                 └─10*[{containerd-shim}]
           ├─containerd-shim─┬─tini─┬─s6-svscan───s6-supervise
           │                 │      └─surl
           │                 └─9*[{containerd-shim}]
           ├─containerd-shim─┬─tini─┬─h───13*[{h}]
           │                 │      └─s6-svscan───s6-supervise
           │                 └─10*[{containerd-shim}]
           ├─containerd-shim─┬─goproxy───14*[{goproxy}]
           │                 └─9*[{containerd-shim}]
           └─32*[{containerd}]

Եվ համեմատեք սա Linux միջուկի pstree-ի հետ Օգտվողի ռեժիմում.

linux─┬─5*[linux]
      └─slirp

Docker կոնտեյներների հետ աշխատելիս ես կարող եմ հյուրընկալողից տեսնել այն պրոցեսների անունները, որոնք աշխատում են հյուրում: Linux Օգտվողի ռեժիմով դա հնարավոր չէ: Ինչ է դա նշանակում? Սա նշանակում է, որ մոնիտորինգի գործիքները գործում են Linux-ի աուդիտի ենթահամակարգի միջոցով չտեսնել Հյուրերի համակարգում գործող գործընթացները: Բայց որոշ իրավիճակներում այս հատկանիշը կարող է դառնալ երկսայրի սուր:

Ընդհանուր առմամբ, ստորև ներկայացված ամբողջ գրառումը հետազոտությունների և ցանկալի արդյունքի հասնելու կոպիտ փորձերի հավաքածու է: Դա անելու համար ես պետք է օգտագործեի տարբեր հնագույն գործիքներ, կարդայի միջուկի աղբյուրները, կատարեի կոդի ինտենսիվ վրիպազերծում, որը գրված էր դեռ տարրական դպրոցում սովորելու տարիներին, ինչպես նաև հատուկ երկուական տարբերակի միջոցով հղկել Heroku-ի կառուցվածքները՝ գտնելու ինձ անհրաժեշտ գործիքները: . Այս ամբողջ աշխատանքը ստիպեց իմ IRC-ի տղաներին կոչել ինձ մոգ: Հուսով եմ, որ այս գրառումը ծառայում է որպես հուսալի փաստաթուղթ ինչ-որ մեկի համար, ով փորձի նույն բանը նոր միջուկների և ՕՀ տարբերակների հետ:

հարմարեցում

Linux User Mode-ի կարգավորումը կատարվում է մի քանի քայլով.

  • հոսթից կախվածությունների տեղադրում;
  • Linux միջուկի ներբեռնում;
  • միջուկի կառուցման կոնֆիգուրացիա;
  • միջուկի հավաքում;
  • երկուական տեղադրում;
  • հյուրի ֆայլային համակարգի կազմաձևում;
  • միջուկի գործարկման պարամետրերի ընտրություն;
  • հյուրերի ցանցի ստեղծում;
  • սկսելով հյուրի միջուկը:

Ենթադրում եմ, որ եթե դուք որոշեք դա անել ինքներդ, ամենայն հավանականությամբ կանեք այն ամենը, ինչ նկարագրված է Ubuntu-ի կամ Debian-ի նման համակարգում: Ես փորձեցի իրականացնել վերը նշված բոլորը իմ սիրելի բաշխման մեջ՝ Alpine-ում, բայց ոչինչ չստացվեց, ըստ երևույթին, այն պատճառով, որ Linux միջուկն ունի կոշտ կապող glibc-իզմեր վարորդների համար Օգտատիրոջ ռեժիմում: Ես նախատեսում եմ այս մասին զեկուցել հոսանքին հակառակ այն բանից հետո, երբ վերջնականապես հասկանամ խնդիրը:

Կախվածության տեղադրում հյուրընկալողից

Ubuntu-ն պահանջում է առնվազն հետևյալ փաթեթները Linux միջուկը կառուցելու համար (ենթադրելով մաքուր տեղադրում).

- 'build-essential'
- 'flex'
- 'bison'
- 'xz-utils'
- 'wget'
- 'ca-certificates'
- 'bc'
- 'linux-headers'

Դուք կարող եք դրանք տեղադրել հետևյալ հրամանով (որպես root կամ sudo).

apt-get -y install build-essential flex bison xz-utils wget ca-certificates bc 
                   linux-headers-$(uname -r)

Նկատի ունեցեք, որ Linux միջուկի մենյուի տեղադրման ծրագիրը գործարկելը կպահանջի տեղադրել libncurses-dev. Խնդրում ենք համոզվել, որ այն տեղադրված է հետևյալ հրամանով (որպես root կամ sudo).

apt-get -y install libncurses-dev

Միջուկի ներբեռնում

Որոշեք, թե որտեղից պետք է ներբեռնել, ապա կառուցեք միջուկը: Այս գործողության համար ձեզ հարկավոր է կոշտ սկավառակի մոտ 1,3 ԳԲ տարածք հատկացնել, այնպես որ համոզվեք, որ այն ունեք:

Հետո գնալ kernel.org և ստացեք URL վերջին կայուն միջուկը ներբեռնելու համար: Գրելու պահին սա հետևյալն է. https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

Ներբեռնեք այս ֆայլը՝ օգտագործելով 'wget':

wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.1.16.tar.xz

Եվ հանեք այն 'tar':

tar xJf linux-5.1.16.tar.xz

Այժմ մենք մուտքագրում ենք թղթապանակը, որը ստեղծվել է tarball-ը բացելիս.

cd linux-5.1.16

Միջուկի կառուցման կարգավորում

Միջուկի կառուցման համակարգը հավաքածու է Մեյքֆայլեր с շատերը հատուկ գործիքներ և սցենարներ՝ գործընթացը ավտոմատացնելու համար: Նախ, բացեք ինտերակտիվ տեղադրման ծրագիրը.

make ARCH=um menuconfig

Այն մասամբ կկառուցի և կցուցադրի ձեզ համար երկխոսության տուփ: Երբ '[Select]', դուք կկարողանաք կարգավորել՝ օգտագործելով Space կամ Enter ստեղները: Պատուհանի շուրջ նավարկությունը սովորականի պես է, օգտագործելով ստեղնաշարի «վեր» և «ներքև» սլաքները, իսկ տարրերի ընտրությունը՝ «ձախ» կամ «աջ»:

Դիտման ցուցիչը —> նշանակում է, որ դուք գտնվում եք ենթամենյուում, որը հասանելի է Enter ստեղնը սեղմելով: Դրանից ելքը ակնհայտորեն անցնում է «[Exit]'.

Ներառեք հետևյալ ընտրանքները '-ում[Select]և համոզվեք, որ նրանք ունեն «[*]» իրենց կողքին.

UML-specific Options:
  - Host filesystem
Networking support (enable this to get the submenu to show up):
  - Networking options:
    - TCP/IP Networking
UML Network devices:
  - Virtual network device
  - SLiRP transport

Վերջ, դուք կարող եք դուրս գալ այս պատուհանից՝ հաջորդաբար ընտրելով «[Exit]'. Պարզապես համոզվեք, որ ձեզ հուշում է վերջում պահպանել կոնֆիգուրացիան և ընտրել «[Yes]'.

Ես խորհուրդ եմ տալիս այս գրառումը կարդալուց հետո խաղալ միջուկի կառուցման ընտրանքների հետ: Այս փորձերից դուք կարող եք շատ բան սովորել այն մասին, թե ինչպես է աշխատում ցածր մակարդակի միջուկի մեխանիզմը և ինչպես են տարբեր դրոշները ազդում միջուկի կառուցման վրա:

Միջուկի կառուցում

Linux միջուկը մեծ ծրագիր է, որն անում է շատ բաներ: Նույնիսկ հին սարքավորումների նման նվազագույն կոնֆիգուրացիայի դեպքում, դրա կառուցումը կարող է բավականին երկար տևել: Այսպիսով, կառուցեք միջուկը հետևյալ հրամանով.

make ARCH=um -j$(nproc)

Ինչի համար? Այս հրամանը մեր շինարարին կհուշի օգտագործել բոլոր հասանելի պրոցեսորի միջուկները և թելերը կառուցման գործընթացում: Թիմ $(nproc) Build-ի վերջում փոխարինում է հրամանի ելքը nproc, որը մաս է կազմում coreutils Ubuntu-ի ստանդարտ կառուցվածքում:

Որոշ ժամանակ անց մեր միջուկը կկազմվի գործարկվող ֆայլի մեջ ./linux.

Երկուականի տեղադրում

Քանի որ Օգտագործողի ռեժիմը Linux-ում ստեղծում է սովորական երկուական, դուք կարող եք տեղադրել այն, ինչպես ցանկացած այլ կոմունալ: Ահա թե ինչպես ես դա արեցի.

mkdir -p ~/bin
cp linux ~/bin/linux

Արժե նաև դրանում համոզվել ~/bin ձեր մեջ է $PATH:

export PATH=$PATH:$HOME/bin

Հյուրերի ֆայլային համակարգի կարգավորում

Ստեղծեք գրացուցակ հյուրի ֆայլային համակարգի համար.

mkdir -p $HOME/prefix/uml-demo
cd $HOME/prefix

Բացեք alpinelinux.org և մուտք գործեք բեռնել բաժինը գտնել իրական ներբեռնման հղումը MINI ROOT FILESYSTEM. Գրելու պահին սա հետևյալն էր.

http://dl-cdn.alpinelinux.org/alpine/v3.10/releases/x86_64/alpine-minirootfs-3.10.0-x86_64.tar.gz

Ներբեռնեք այս tarball-ը wget-ի միջոցով.

wget -O alpine-rootfs.tgz http://dl-cdn.alpinelinux.org/alpine/v3.10/releases/x86_64/alpine-minirootfs-3.10.0-x86_64.tar.gz

Այժմ մուտքագրեք հյուրի ֆայլային համակարգի գրացուցակը և հանեք արխիվը.

cd uml-demo
tar xf ../alpine-rootfs.tgz

Նկարագրված գործողությունները կստեղծեն փոքր ֆայլային համակարգի ձևանմուշ: Համակարգի բնույթի պատճառով չափազանց դժվար կլինի փաթեթներ տեղադրել Alpine apk մենեջերի միջոցով: Բայց այս FS-ն բավական կլինի ընդհանուր գաղափարը գնահատելու համար։

Մեզ նաև գործիք է պետք տինի հիշողության սպառումը զսպելու համար զոմբիացման գործընթացներ մեր հյուրի միջուկը:

wget -O tini https://github.com/krallin/tini/releases/download/v0.18.0/tini-static
chmod +x tini

Kernel հրամանի տողի ստեղծում

Linux միջուկը, ինչպես շատ այլ ծրագրեր, ունի հրամանի տողի արգումենտներ, որոնց կարելի է մուտք գործել՝ նշելով բանալին --help.

Ինքը՝ օգնություն

linux --help
User Mode Linux v5.1.16
        available at http://user-mode-linux.sourceforge.net/

--showconfig
    Prints the config file that this UML binary was generated from.

iomem=<name>,<file>
    Configure <file> as an IO memory region named <name>.

mem=<Amount of desired ram>
    This controls how much "physical" memory the kernel allocates
    for the system. The size is specified as a number followed by
    one of 'k', 'K', 'm', 'M', which have the obvious meanings.
    This is not related to the amount of memory in the host.  It can
    be more, and the excess, if it's ever used, will just be swapped out.
        Example: mem=64M

--help
    Prints this message.

debug
    this flag is not needed to run gdb on UML in skas mode

root=<file containing the root fs>
    This is actually used by the generic kernel in exactly the same
    way as in any other kernel. If you configure a number of block
    devices and want to boot off something other than ubd0, you
    would use something like:
        root=/dev/ubd5

--version
    Prints the version number of the kernel.

umid=<name>
    This is used to assign a unique identity to this UML machine and
    is used for naming the pid file and management console socket.

con[0-9]*=<channel description>
    Attach a console or serial line to a host channel.  See
    http://user-mode-linux.sourceforge.net/old/input.html for a complete
    description of this switch.

eth[0-9]+=<transport>,<options>
    Configure a network device.
    
aio=2.4
    This is used to force UML to use 2.4-style AIO even when 2.6 AIO is
    available.  2.4 AIO is a single thread that handles one request at a
    time, synchronously.  2.6 AIO is a thread which uses the 2.6 AIO
    interface to handle an arbitrary number of pending requests.  2.6 AIO
    is not available in tt mode, on 2.4 hosts, or when UML is built with
    /usr/include/linux/aio_abi.h not available.  Many distributions don't
    include aio_abi.h, so you will need to copy it from a kernel tree to
    your /usr/include/linux in order to build an AIO-capable UML

nosysemu
    Turns off syscall emulation patch for ptrace (SYSEMU).
    SYSEMU is a performance-patch introduced by Laurent Vivier. It changes
    behaviour of ptrace() and helps reduce host context switch rates.
    To make it work, you need a kernel patch for your host, too.
    See http://perso.wanadoo.fr/laurent.vivier/UML/ for further
    information.

uml_dir=<directory>
    The location to place the pid and umid files.

quiet
    Turns off information messages during boot.

hostfs=<root dir>,<flags>,...
    This is used to set hostfs parameters.  The root directory argument
    is used to confine all hostfs mounts to within the specified directory
    tree on the host.  If this isn't specified, then a user inside UML can
    mount anything on the host that's accessible to the user that's running
    it.
    The only flag currently supported is 'append', which specifies that all
    files opened by hostfs will be opened in append mode.

Այս վահանակը ընդգծում է մեկնարկի հիմնական պարամետրերը: Եկեք գործարկենք միջուկը նվազագույն պահանջվող ընտրանքների հավաքածուով.

linux 
  root=/dev/root 
  rootfstype=hostfs 
  rootflags=$HOME/prefix/uml-demo 
  rw 
  mem=64M 
  init=/bin/sh

Վերևի տողերը մեր միջուկին ասում են հետևյալը.

  • Ենթադրենք, որ արմատային ֆայլային համակարգը կեղծ սարք է /dev/root.
  • Ընտրեք հյուրընկալողներ որպես արմատային ֆայլային համակարգի վարորդ:
  • Տեղադրեք հյուրի ֆայլային համակարգը, որը մենք ստեղծել ենք արմատային սարքի վրա:
  • Եվ այո, կարդալ-գրելու ռեժիմում:
  • Օգտագործեք ընդամենը 64 մեգաբայթ օպերատիվ հիշողություն (կարող եք շատ ավելի քիչ օգտագործել՝ կախված նրանից, թե ինչ եք նախատեսում անել, բայց 64 ՄԲ, կարծես, օպտիմալ քանակն է):
  • Միջուկը ավտոմատ կերպով սկսվում է /bin/sh ինչպես init- գործընթաց.

Գործարկեք այս հրամանը, և դուք պետք է ստանաք հետևյալի նման մի բան.

Եվս մեկ թերթ

Core dump limits :
        soft - 0
        hard - NONE
Checking that ptrace can change system call numbers...OK
Checking syscall emulation patch for ptrace...OK
Checking advanced syscall emulation patch for ptrace...OK
Checking environment variables for a tempdir...none found
Checking if /dev/shm is on tmpfs...OK
Checking PROT_EXEC mmap in /dev/shm...OK
Adding 32137216 bytes to physical memory to account for exec-shield gap
Linux version 5.1.16 (cadey@kahless) (gcc version 7.4.0 (Ubuntu 7.4.0-1ubuntu1~18.04.1)) #30 Sun Jul 7 18:57:19 UTC 2019
Built 1 zonelists, mobility grouping on.  Total pages: 23898
Kernel command line: root=/dev/root rootflags=/home/cadey/dl/uml/alpine rootfstype=hostfs rw mem=64M init=/bin/sh
Dentry cache hash table entries: 16384 (order: 5, 131072 bytes)
Inode-cache hash table entries: 8192 (order: 4, 65536 bytes)
Memory: 59584K/96920K available (2692K kernel code, 708K rwdata, 588K rodata, 104K init, 244K bss, 37336K reserved, 0K cma-reserved)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
NR_IRQS: 15
clocksource: timer: mask: 0xffffffffffffffff max_cycles: 0x1cd42e205, max_idle_ns: 881590404426 ns
Calibrating delay loop... 7479.29 BogoMIPS (lpj=37396480)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes)
Checking that host ptys support output SIGIO...Yes
Checking that host ptys support SIGIO on close...No, enabling workaround
devtmpfs: initialized
random: get_random_bytes called from setup_net+0x48/0x1e0 with crng_init=0
Using 2.6 host AIO
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
futex hash table entries: 256 (order: 0, 6144 bytes)
NET: Registered protocol family 16
clocksource: Switched to clocksource timer
NET: Registered protocol family 2
tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes)
TCP established hash table entries: 1024 (order: 1, 8192 bytes)
TCP bind hash table entries: 1024 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 1024 bind 1024)
UDP hash table entries: 256 (order: 1, 8192 bytes)
UDP-Lite hash table entries: 256 (order: 1, 8192 bytes)
NET: Registered protocol family 1
console [stderr0] disabled
mconsole (version 2) initialized on /home/cadey/.uml/tEwIjm/mconsole
Checking host MADV_REMOVE support...OK
workingset: timestamp_bits=62 max_order=14 bucket_order=0
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 254)
io scheduler noop registered (default)
io scheduler bfq registered
loop: module loaded
NET: Registered protocol family 17
Initialized stdio console driver
Using a channel type which is configured out of UML
setup_one_line failed for device 1 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 2 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 3 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 4 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 5 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 6 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 7 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 8 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 9 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 10 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 11 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 12 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 13 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 14 : Configuration failed
Using a channel type which is configured out of UML
setup_one_line failed for device 15 : Configuration failed
Console initialized on /dev/tty0
console [tty0] enabled
console [mc-1] enabled
Failed to initialize ubd device 0 :Couldn't determine size of device's file
VFS: Mounted root (hostfs filesystem) on device 0:11.
devtmpfs: mounted
This architecture does not have kernel memory protection.
Run /bin/sh as init process
/bin/sh: can't access tty; job control turned off
random: fast init done
/ # 

Վերը նշված մանիպուլյացիաները մեզ կտան հյուրի համակարգ նվազագույնը, առանց նման բաների /proc կամ նշանակված հյուրընկալողի անունը: Օրինակ, փորձեք հետևյալ հրամանները.

- uname -av
- cat /proc/self/pid
- hostname

Հյուրից դուրս գալու համար մուտքագրեք exit կամ սեղմեք հսկողություն-դ. Սա կսպանի կեղևը, որին հաջորդում է միջուկի խուճապը.

/ # exit
Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000000
fish: “./linux root=/dev/root rootflag…” terminated by signal SIGABRT (Abort)

Մենք ստացել ենք միջուկի այս խուճապը, քանի որ Linux միջուկը կարծում է, որ սկզբնավորման գործընթացը միշտ աշխատում է: Առանց դրա, համակարգն այլևս չի կարող գործել և խափանում է: Բայց քանի որ սա օգտագործողի ռեժիմի գործընթաց է, արդյունքում ստացված արդյունքն ինքն իրեն ուղարկում է SIGABRT, որի արդյունքում ստացվում է արդյունք:

Հյուրերի ցանցի կարգավորում

Եվ այստեղ ամեն ինչ սկսում է սխալ գնալ: Լինուքսի օգտատերերի ռեժիմում ցանցի ստեղծումն այն է, որտեղ սահմանափակ «օգտագործողի ռեժիմի» ողջ հայեցակարգը սկսում է քանդվել: Ի վերջո, սովորաբար համակարգի մակարդակով ցանցը սահմանափակ է արտոնյալ կատարման ռեժիմները բոլորիս համար հասկանալի պատճառներով:

Նշում. Դուք կարող եք ավելին կարդալ UML-ում ցանցի հետ աշխատելու տարբեր տարբերակների մասին այստեղ.

Ճանապարհորդություն դեպի Սլիփ

Այնուամենայնիվ, կա հին և գրեթե չաջակցվող գործիք, որը կոչվում է Սայթաքել, որի հետ User Mode Linux-ը կարող է համագործակցել ցանցի հետ: Այն աշխատում է շատ նման օգտվողի մակարդակի TCP/IP փաթեթի և չի պահանջում որևէ համակարգի թույլտվություն գործարկելու համար: Այս գործիքն էր թողարկվել է 1995 թ, և վերջին թարմացումը թվագրված է 2006 տարի. Slirp-ը շատ հին է: Առանց աջակցության և թարմացումների ժամանակի ընթացքում կոմպիլյատորներն այնքան հեռու են գնացել, որ այժմ այս գործիքը կարող է նկարագրվել միայն որպես ծածկագրի փտում.

Այսպիսով, եկեք ներբեռնենք Slirp-ը Ubuntu-ի պահոցներից և փորձենք գործարկել այն.

sudo apt-get install slirp
/usr/bin/slirp
Slirp v1.0.17 (BETA)

Copyright (c) 1995,1996 Danny Gasparovski and others.
All rights reserved.
This program is copyrighted, free software.
Please read the file COPYRIGHT that came with the Slirp
package for the terms and conditions of the copyright.

IP address of Slirp host: 127.0.0.1
IP address of your DNS(s): 1.1.1.1, 10.77.0.7
Your address is 10.0.2.15
(or anything else you want)

Type five zeroes (0) to exit.

[autodetect SLIP/CSLIP, MTU 1500, MRU 1500, 115200 baud]

SLiRP Ready ...
fish: “/usr/bin/slirp” terminated by signal SIGSEGV (Address boundary error)

Օ, աստվածներ: Եկեք տեղադրենք Slirp-ի կարգաբերիչը և տեսնենք, թե արդյոք կարող ենք պարզել, թե ինչ է կատարվում այստեղ.

sudo apt-get install gdb slirp-dbgsym
gdb /usr/bin/slirp
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/bin/slirp...Reading symbols from /usr/lib/debug/.build-id/c6/2e75b69581a1ad85f72ac32c0d7af913d4861f.debug...done.
done.
(gdb) run
Starting program: /usr/bin/slirp
Slirp v1.0.17 (BETA)

Copyright (c) 1995,1996 Danny Gasparovski and others.
All rights reserved.
This program is copyrighted, free software.
Please read the file COPYRIGHT that came with the Slirp
package for the terms and conditions of the copyright.

IP address of Slirp host: 127.0.0.1
IP address of your DNS(s): 1.1.1.1, 10.77.0.7
Your address is 10.0.2.15
(or anything else you want)

Type five zeroes (0) to exit.

[autodetect SLIP/CSLIP, MTU 1500, MRU 1500, 115200 baud]

SLiRP Ready ...

Program received signal SIGSEGV, Segmentation fault.
                                                    ip_slowtimo () at ip_input.c:457
457     ip_input.c: No such file or directory.

Սխալը հարվածում է մեր մեջ այս տողը. Եկեք նայենք stacktrace-ին, միգուցե ինչ-որ բան մեզ օգնի այնտեղ.

(gdb) bt full
#0  ip_slowtimo () at ip_input.c:457
        fp = 0x55784a40
#1  0x000055555556a57c in main_loop () at ./main.c:980
        so = <optimized out>
        so_next = <optimized out>
        timeout = {tv_sec = 0, tv_usec = 0}
        ret = 0
        nfds = 0
        ttyp = <optimized out>
        ttyp2 = <optimized out>
        best_time = <optimized out>
        tmp_time = <optimized out>
#2  0x000055555555b116 in main (argc=1, argv=0x7fffffffdc58) at ./main.c:95
No locals.

Այստեղ մենք տեսնում ենք, որ խափանումը տեղի է ունենում հիմնական հանգույցի գործարկման ժամանակ, երբ slirp-ը փորձում է ստուգել ժամանակային ժամերը: Այս պահին ես ստիպված էի հրաժարվել վրիպազերծման փորձերից: Բայց եկեք տեսնենք, թե արդյոք Slirp-ը կառուցված է սորտերից: Ես նորից ներբեռնեցի արխիվը անմիջապես կայքից Sourceforge- ը, որովհետև հրամանի տողի միջով ինչ-որ բան քաշելը ցավ է.

cd ~/dl
wget https://xena.greedo.xeserv.us/files/slirp-1.0.16.tar.gz
tar xf slirp-1.0.16.tar.gz
cd slirp-1.0.16/src
./configure --prefix=$HOME/prefix/slirp
make

Այստեղ մենք տեսնում ենք չսահմանված ներկառուցված գործառույթների մասին ահազանգեր, այսինքն՝ ստացված երկուական ֆայլը կապելու անհնարինության մասին։ Ըստ երևույթին, 2006-ից մինչ այժմ gcc-ն դադարել է ստեղծել ներկառուցված միջանկյալ գործառույթներում օգտագործվող խորհրդանիշներ: Փորձենք փոխարինել հիմնաբառը inline դատարկ մեկնաբանության վրա և նայեք արդյունքին.

vi slirp.h
:6
a
<enter>
#define inline /**/
<escape>
:wq
make

Ոչ. Սա նույնպես չի աշխատում: Դեռևս չի հաջողվում գտնել այս գործառույթների նշանները:

Այս պահին ես հանձնվեցի և սկսեցի փնտրել Github-ը Հերոկուն կառուցում է փաթեթներ. Իմ տեսությունն այն էր, որ Heroku-ի կառուցման որոշ փաթեթ կպարունակի ինձ անհրաժեշտ երկուականները: Ի վերջո, որոնումն ինձ առաջնորդեց այստեղ. Ներբեռնեցի և հանեցի փաթեթավորումը uml.tar.gz և գտավ հետևյալը.

total 6136
-rwxr-xr-x 1 cadey cadey   79744 Dec 10  2017 ifconfig*
-rwxr-xr-x 1 cadey cadey     373 Dec 13  2017 init*
-rwxr-xr-x 1 cadey cadey  149688 Dec 10  2017 insmod*
-rwxr-xr-x 1 cadey cadey   66600 Dec 10  2017 route*
-rwxr-xr-x 1 cadey cadey  181056 Jun 26  2015 slirp*
-rwxr-xr-x 1 cadey cadey 5786592 Dec 15  2017 uml*
-rwxr-xr-x 1 cadey cadey     211 Dec 13  2017 uml_run*

Սա slirp երկուական տարբերակն է: Նա աշխատում է?

./slirp
Slirp v1.0.17 (BETA) FULL_BOLT

Copyright (c) 1995,1996 Danny Gasparovski and others.
All rights reserved.
This program is copyrighted, free software.
Please read the file COPYRIGHT that came with the Slirp
package for the terms and conditions of the copyright.

IP address of Slirp host: 127.0.0.1
IP address of your DNS(s): 1.1.1.1, 10.77.0.7
Your address is 10.0.2.15
(or anything else you want)

Type five zeroes (0) to exit.

[autodetect SLIP/CSLIP, MTU 1500, MRU 1500]

SLiRP Ready ...

Չի խափանում, ուստի այն պետք է աշխատի: Եկեք տնկենք այս երկուականը ~/bin/slirp:

cp slirp ~/bin/slirp

Փաթեթ ստեղծողի կողմից այն հեռացնելու դեպքում ես հայելի արեց.

Ցանցի կոնֆիգուրացիա

Այժմ եկեք կարգավորենք ցանցը մեր հյուրի միջուկում: Թարմացրեք գործարկման ընտրանքները:

linux 
  root=/dev/root 
  rootfstype=hostfs 
  rootflags=$HOME/prefix/uml-demo 
  rw 
  mem=64M 
  eth0=slirp,,$HOME/bin/slirp 
  init=/bin/sh

Այժմ եկեք միացնենք ցանցը.

mount -t proc proc proc/
mount -t sysfs sys sys/

ifconfig eth0 10.0.2.14 netmask 255.255.255.240 broadcast 10.0.2.15
route add default gw 10.0.2.2

Առաջին երկու կազմաձևման հրամանները /proc и /sys աշխատանքի համար անհրաժեշտ ifconfig, որը կարգավորում է ցանցային ինտերֆեյսը Slirp-ի հետ հաղորդակցվելու համար: Թիմ route սահմանում է միջուկի երթուղային աղյուսակը, որպեսզի ստիպեն ամբողջ երթևեկությունն ուղարկել Slirp թունելով: Եկեք ստուգենք սա DNS հարցումով.

nslookup google.com 8.8.8.8
Server:    8.8.8.8
Address 1: 8.8.8.8 dns.google

Name:      google.com
Address 1: 172.217.12.206 lga25s63-in-f14.1e100.net
Address 2: 2607:f8b0:4006:81b::200e lga25s63-in-x0e.1e100.net

Այն աշխատում է:

Նշում ըստ .. Ըստ երևույթին, սկզբնական գրառումը գրվել է աշխատասեղանի վրա լարային ցանցային քարտով կամ որևէ այլ կոնֆիգուրացիայով, որը չի պահանջում լրացուցիչ վարորդներ: Intel-ից WiFi 8265 ունեցող նոութբուքի վրա ցանցը բարձրացնելիս սխալ է տեղի ունենում

/ # ifconfig eth0 10.0.2.14 netmask 255.255.255.240 broadcast 10.0.2.15
slirp_tramp failed - errno = 2
ifconfig: ioctl 0x8914 failed: No such file or directory
/ #

Ըստ երևույթին, միջուկը չի կարող շփվել ցանցային քարտի վարորդի հետ: Որոնվածը միջուկում հավաքելու փորձը, ցավոք, չշտկեց իրավիճակը: Հրապարակման պահին հնարավոր չէր լուծում գտնել այս կոնֆիգուրացիայի մեջ։ Ավելի պարզ կոնֆիգուրացիաների դեպքում (օրինակ՝ Virtualbox-ում) ինտերֆեյսը ճիշտ բարձրանում է:

Եկեք ավտոմատացնենք վերահղումը, օգտագործելով հետևյալ shell script-ը.

#!/bin/sh
# init.sh

mount -t proc proc proc/
mount -t sysfs sys sys/
ifconfig eth0 10.0.2.14 netmask 255.255.255.240 broadcast 10.0.2.15
route add default gw 10.0.2.2

echo "networking set up"

exec /tini /bin/sh

Եվ նշեք այն կատարվող.

chmod +x init.sh

Եվ այնուհետև մենք փոփոխություններ կկատարենք միջուկի հրամանի տողում.

linux 
  root=/dev/root 
  rootfstype=hostfs 
  rootflags=$HOME/prefix/uml-demo 
  rw 
  mem=64M 
  eth0=slirp,,$HOME/bin/slirp 
  init=/init.sh

Եվ կրկնենք.

SLiRP Ready ...
networking set up
/bin/sh: can't access tty; job control turned off

nslookup google.com 8.8.8.8
Server:    8.8.8.8
Address 1: 8.8.8.8 dns.google

Name:      google.com
Address 1: 172.217.12.206 lga25s63-in-f14.1e100.net
Address 2: 2607:f8b0:4004:800::200e iad30s09-in-x0e.1e100.net

Ցանցը կայուն է։

docker ֆայլ

Որպեսզի ձեզ ավելի հեշտ լինի ստուգել այս ամենը, ես հավաքել եմ dockerfile, որն ավտոմատացնում է նկարագրված քայլերի մեծ մասը և պետք է տա ​​ձեզ աշխատանքային կոնֆիգուրացիա: Ես էլ ունեմ նախապես կազմաձևված միջուկ, որն ունի այն ամենը, ինչ նկարագրված է գրառման մեջ։ Բայց կարևոր է հասկանալ, որ այստեղ ես նախանշել եմ միայն նվազագույն պարամետրերը:

Հուսով եմ, որ այս գրառումը կօգնի ձեզ հասկանալ, թե ինչպես բարձրացնել հյուրի միջուկը: Պարզվեց, որ դա ինչ-որ հրեշ է, բայց հրապարակումը ստեղծվել է որպես ամբողջական ուղեցույց Linux-ում User Mode-ի կառուցման, տեղադրման և կազմաձևման վերաբերյալ այս ընտանիքի օպերացիոն համակարգերի ժամանակակից տարբերակների ներքո: Հաջորդ քայլերը պետք է ներառեն ծառայությունների և այլ ծրագրերի տեղադրում արդեն հյուրերի համակարգում: Քանի որ Docker կոնտեյների պատկերները պարզապես հրապարակված tarballs են, դուք պետք է կարողանաք նկարը հանել միջոցով docker export, և այնուհետև որոշեք այն տեղադրելու ուղին հյուրի միջուկի ֆայլային համակարգի արմատում: Դե, ապա կատարեք shell-ի սցենարը:

Հատուկ շնորհակալություն Rkeene-ին #lobsters-ից Freenode-ում: Առանց Slirp-ին վրիպազերծելու նրա օգնության, ես այսքան հեռու չէի հասնի: Ես գաղափար չունեմ, թե ինչպես է նրա Slackware համակարգը ճիշտ աշխատում slirp-ի հետ, բայց իմ Ubuntu և Alpine համակարգերը չընդունեցին slirp-ը, և երկուական Rkeene-ն ինձ առաջարկեց: Բայց ինձ բավական է, որ գոնե ինձ մոտ ինչ-որ բան ստացվի։

Source: www.habr.com

Добавить комментарий