نحوه شروع استفاده از حالت کاربر در لینوکس

مقدمه ای از مترجم: در پس زمینه ورود گسترده انواع ظروف به زندگی ما، می تواند بسیار جالب و مفید باشد که بفهمیم همه چیز یک بار با چه فناوری هایی شروع شده است. برخی از آنها را می توان تا به امروز به طور مفید مورد استفاده قرار داد، اما همه چنین روش هایی را به خاطر نمی آورند (یا می دانند که آیا در طول توسعه سریع خود دستگیر نشده اند). یکی از این فناوری ها لینوکس حالت کاربر است. نویسنده نسخه اصلی، حفاری های زیادی انجام داد و فهمید که کدام یک از پیشرفت های قدیمی هنوز کار می کند و کدام یک کار نمی کند، و چیزی شبیه به یک دستورالعمل گام به گام در مورد چگونگی تهیه UML خانگی خانگی در 2k19 گردآوری کرد. و بله، ما نویسنده پست اصلی را به هابر دعوت کردیم کیدی، بنابراین اگر سوالی دارید - در نظرات به زبان انگلیسی بپرسید.

نحوه شروع استفاده از حالت کاربر در لینوکس

حالت کاربر در لینوکس در واقع یک پورت از هسته لینوکس برای خودش است. این حالت به شما امکان می دهد یک هسته کامل لینوکس را به عنوان یک فرآیند کاربر اجرا کنید و معمولاً توسط توسعه دهندگان برای آزمایش درایورها استفاده می شود. اما این حالت به عنوان یک ابزار جداسازی عمومی نیز مفید است که اصل آن مشابه عملکرد ماشین های مجازی است. این حالت نسبت به Docker ایزوله بیشتری دارد، اما کمتر از یک ماشین مجازی تمام عیار مانند KVM یا Virtual Box.

به طور کلی، حالت کاربری ممکن است ابزاری عجیب و دشوار به نظر برسد، اما همچنان کاربردهای خود را دارد. پس از همه، این یک هسته کامل لینوکس است که از یک کاربر غیرمجاز اجرا می شود. این ویژگی به کدهای بالقوه نامعتبر اجازه می دهد تا بدون هیچ تهدیدی برای ماشین میزبان اجرا شوند. و از آنجایی که این یک هسته تمام عیار است، فرآیندهای آن از ماشین میزبان جدا شده است، یعنی فرآیندهای در حال اجرا در حالت کاربر برای میزبان قابل مشاهده نخواهد بود. این مانند کانتینر معمولی 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}]

و این را با pstree هسته لینوکس در حالت کاربر مقایسه کنید:

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

هنگام کار با کانتینرهای Docker، می توانم نام فرآیندهایی که در مهمان اجرا می شوند را از میزبان ببینم. با حالت کاربر لینوکس، این امکان پذیر نیست. چه مفهومی داره؟ این بدان معنی است که ابزارهای نظارتی که از طریق زیرسیستم حسابرسی لینوکس اجرا می شوند نمی بینم فرآیندهای در حال اجرا در سیستم مهمان اما در برخی شرایط، این ویژگی می تواند به یک شمشیر دولبه تبدیل شود.

به طور کلی، کل پست زیر مجموعه ای از تحقیقات و تلاش های خشن برای رسیدن به نتیجه مطلوب است. برای انجام این کار، مجبور بودم از ابزارهای مختلف باستانی استفاده کنم، منابع هسته را بخوانم، کدهایی را که در دوران ابتدایی نوشته شده بود را به طور فشرده اشکال زدایی کنم، و همچنین با استفاده از یک باینری خاص، ساخت‌های Heroku را برای یافتن ابزارهای مورد نیاز خود سرهم کنم. . همه این کارها باعث شد که بچه ها در IRC من را جادو صدا کنند. امیدوارم این پست به عنوان یک سند قابل اعتماد برای کسی باشد که بتواند همین کار را با هسته های جدیدتر و نسخه های سیستم عامل امتحان کند.

تنظیم

راه اندازی حالت کاربری لینوکس در چند مرحله انجام می شود:

  • نصب وابستگی ها بر روی هاست؛
  • دانلود هسته لینوکس؛
  • راه اندازی ساخت هسته؛
  • مونتاژ هسته؛
  • نصب باینری؛
  • پیکربندی سیستم فایل مهمان؛
  • انتخاب پارامترهای راه اندازی هسته؛
  • راه اندازی یک شبکه مهمان؛
  • شروع کرنل مهمان

من فرض می‌کنم که اگر تصمیم بگیرید خودتان این کار را انجام دهید، به احتمال زیاد تمام کارهایی را که در برخی از سیستم‌های اوبونتو یا دبیان توضیح داده شده است، انجام خواهید داد. من سعی کردم همه موارد فوق را در توزیع مورد علاقه خود - Alpine پیاده سازی کنم، اما هیچ نتیجه ای حاصل نشد، ظاهراً به دلیل این واقعیت است که هسته لینوکس دارای یک glibc-isms سخت برای درایورها در حالت کاربر است. من قصد دارم بعد از اینکه بالاخره مشکل را فهمیدم، این را به upstream گزارش کنم.

نصب وابستگی ها بر روی هاست

اوبونتو حداقل به بسته های زیر برای ساخت هسته لینوکس نیاز دارد (با فرض نصب تمیز):

- '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)

توجه داشته باشید که اجرای برنامه تنظیم منوی هسته لینوکس نیاز به نصب دارد libncurses-dev. لطفاً مطمئن شوید که با دستور زیر (به صورت روت یا با sudo) نصب شده باشد:

apt-get -y install libncurses-dev

دانلود کرنل

تصمیم بگیرید که کجا دانلود شود و سپس هسته را بسازید. برای این عملیات، باید حدود 1,3 گیگابایت فضای هارد دیسک را اختصاص دهید، بنابراین مطمئن شوید که آن را دارید.

بعد از رفتن به هسته هسته و 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

اکنون دایرکتوری ایجاد شده هنگام باز کردن تاربول را وارد می کنیم:

cd linux-5.1.16

راه اندازی ساخت هسته

سیستم ساخت هسته یک مجموعه است فایل های ایجاد شده с زیاد ابزارها و اسکریپت های سفارشی برای خودکار کردن فرآیند. ابتدا برنامه تنظیم تعاملی را باز کنید:

make ARCH=um menuconfig

تا حدی یک کادر محاوره ای را برای شما می سازد و نمایش می دهد. چه زمانی '[Select]'، می‌توانید با استفاده از کلیدهای Space یا Enter پیکربندی کنید. طبق معمول، پنجره را با فلش های صفحه کلید "بالا" و "پایین" هدایت کنید و عناصر را انتخاب کنید - "چپ" یا "راست".

نشانگر view -> به این معنی است که شما در یک زیر منو قرار دارید که با استفاده از کلید 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]".

توصیه می کنم بعد از خواندن این پست با گزینه های ساخت هسته بازی کنید. از این آزمایش‌ها می‌توانید در مورد نحوه عملکرد مکانیک هسته سطح پایین و چگونگی تأثیر پرچم‌های مختلف بر نحوه ساخت هسته اطلاعات زیادی کسب کنید.

ساخت هسته

هسته لینوکس یک برنامه بزرگ است که کارهای زیادی انجام می دهد. حتی با چنین پیکربندی حداقلی در سخت افزار قدیمی، ساخت آن می تواند زمان زیادی را ببرد. بنابراین با دستور زیر هسته را بسازید:

make ARCH=um -j$(nproc)

برای چی؟ این دستور به سازنده ما می گوید که از تمام هسته ها و رشته های CPU موجود در فرآیند ساخت استفاده کند. تیم $(nproc) در انتهای Build خروجی دستور را جایگزین می کند nproc، که بخشی از coreutils در یک ساخت استاندارد اوبونتو.

پس از مدتی، هسته ما در یک فایل اجرایی کامپایل می شود ./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 manager بسیار دشوار خواهد بود. اما این FS برای ارزیابی ایده کلی کافی خواهد بود.

ما همچنین به یک ابزار نیاز داریم تینی برای توقف مصرف حافظه فرآیندهای زامبی هسته مهمان ما

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

ایجاد خط فرمان هسته

هسته لینوکس، مانند اکثر برنامه های دیگر، دارای آرگومان های خط فرمان است که با تعیین کلید قابل دسترسی است. --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.
  • انتخاب کنید hostfs به عنوان یک درایور سیستم فایل ریشه
  • فایل سیستم مهمان را که ایجاد کرده‌ایم روی دستگاه روت مونت کنید.
  • و بله، در حالت خواندن و نوشتن.
  • فقط از 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 یا کنترل-d را فشار دهید. این کار باعث از بین رفتن پوسته و به دنبال آن وحشت هسته می شود:

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

ما این وحشت هسته را گرفتیم زیرا هسته لینوکس فکر می کند که فرآیند اولیه سازی همیشه در حال اجرا است. بدون آن، سیستم دیگر نمی تواند کار کند و از کار می افتد. اما از آنجایی که این یک فرآیند در حالت کاربر است، خروجی حاصل خود را به آن ارسال می کند SIGABRT، که منجر به یک خروجی می شود.

راه اندازی شبکه مهمان

اما اینجاست که همه چیز برای ما بد می شود. شبکه سازی در حالت کاربر لینوکس جایی است که کل مفهوم یک "حالت کاربری" محدود شروع به از هم پاشیدن می کند. از این گذشته، شبکه معمولاً در سطح سیستم محدود است ممتاز حالت های اجرا به دلایل قابل درک همه ما.

توجه داشته باشید. برای .: می توانید در مورد گزینه های مختلف کار با یک شبکه در UML بیشتر بخوانید اینجا.

سفر به اسلیپ

با این حال، یک ابزار قدیمی و تقریبا پشتیبانی نشده به نام وجود دارد لغزش، که با آن لینوکس حالت کاربر می تواند با شبکه تعامل داشته باشد. این کار بسیار شبیه یک پشته TCP/IP در سطح کاربر است و برای اجرا به هیچ مجوزی از سیستم نیاز ندارد. این ابزار بود در سال 1995 منتشر شد، و آخرین به روز رسانی تاریخ است 2006. اسلیپ خیلی قدیمی است. در طول مدت بدون پشتیبانی و به روز رسانی، کامپایلرها به حدی پیش رفته اند که اکنون این ابزار را فقط می توان به عنوان توصیف کرد پوسیدگی کد.

پس بیایید Slirp را از مخازن اوبونتو دانلود کنیم و سعی کنیم آن را اجرا کنیم:

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. تئوری من این بود که برخی از بسته های ساخت 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

این کار می کند

توجه: ظاهراً پست اصلی روی دسکتاپ با کارت شبکه سیمی یا پیکربندی دیگری که نیاز به درایورهای اضافی ندارد نوشته شده است. در لپ تاپ با 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)، رابط به درستی افزایش می یابد.

بیایید تغییر مسیر را با اسکریپت پوسته زیر خودکار کنیم:

#!/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

شبکه پایدار است!

فایل داکر

برای اینکه بررسی همه اینها را برای شما آسانتر کنم، من جمع آوری کرده ام dockerfile، که اکثر مراحل توضیح داده شده را خودکار می کند و باید یک پیکربندی کاری به شما ارائه دهد. من نیز دارم پیکربندی هسته آماده، که همه چیزهایی که در پست توضیح داده شده است. اما درک این نکته مهم است که در اینجا من فقط حداقل تنظیمات را بیان کرده ام.

امیدوارم این پست به شما کمک کرده باشد که چگونه هسته مهمان را بالا ببرید. معلوم شد که این یک نوع هیولا است، اما انتشار به عنوان یک راهنمای جامع در مورد ساخت، نصب و پیکربندی حالت کاربر در لینوکس تحت نسخه های مدرن سیستم عامل های این خانواده در نظر گرفته شد. مراحل بعدی باید شامل نصب سرویس ها و سایر نرم افزارهای موجود در سیستم مهمان باشد. از آنجایی که تصاویر کانتینر Docker فقط تاربال های عمومی هستند، باید بتوانید تصویر را از طریق استخراج کنید docker exportو سپس مسیر نصب آن را در ریشه سیستم فایل هسته مهمان مشخص کنید. خوب، سپس اسکریپت پوسته را اجرا کنید.

تشکر ویژه از Rkeene از #lobsters در Freenode. بدون کمک او در رفع اشکال Slirp، من تا این حد پیش نمی رفتم. من نمی دانم سیستم Slackware او چگونه با slirp درست کار می کند، اما سیستم های اوبونتو و آلپاین من slirp را قبول نکردند و Rkeene باینری به من پیشنهاد داد. اما برای من کافی است که حداقل چیزی برای من کار کند.

منبع: www.habr.com

اضافه کردن نظر