Home Inhaltsverzeichnis Textausgaben der Programme auf die Console nicht koordiniert Widerspruch: init läuft, obwohl execve zurückkehrt
 

8 COBRA-Boot

(11.04.2008) Wie funktioniert konkret der Boot bei der COBRA-Linux-Version?

Irgendwann wird typischerweise /etc/inittab ausgeführt. Darin finde ich:

andreas@gericom:/suse9.1/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324 \
/romfs/etc>cat inittab
inet:unknown:/bin/inetd
boa:unknown:/bin/boa

Erstmal entspricht dieses Format nicht dem Standardformat, wie man es mittels man inittab auf einem Standard-Linux gezeigt bekommt , wie hier als Beispiel bei SuSE 10.2:

...
# The default runlevel is defined here
id:5:initdefault:

# First script to be executed, if not booting in emergency (-b) mode
si::bootwait:/etc/init.d/boot

# /etc/init.d/rc takes care of runlevel handling
#
# runlevel 0  is  System halt   (Do not use this for initdefault!)
# runlevel 1  is  Single user mode
# runlevel 2  is  Local multiuser without remote network (e.g. NFS)
# runlevel 3  is  Full multiuser with network
# runlevel 4  is  Not used
# runlevel 5  is  Full multiuser with network and xdm
# runlevel 6  is  System reboot (Do not use this for initdefault!)
#
l0:0:wait:/etc/init.d/rc 0
l1:1:wait:/etc/init.d/rc 1
...

Desweiteren finde ich im COBRA-Boot (hier ein Ausschnitt):

...
VFS: Mounted root (romfs filesystem) readonly.
Freeing unused kernel memory: 32k freed (0xfc000 - 0x103000)
Shell invoked to run file: /etc/rc
Command: hostname cobra1
Command: /bin/expand /etc/ramfs.img /dev/ram0
Command: mount -t proc proc /proc
...

nichts von boa oder inetd.

Darum schaue ich mir speziell boa an, warum dieser zur Bootzeit nichts meldet.

Hier ein Boot von uClinux Developers Archive

...
     RAMDISK: Couldn't find valid ramdisk image starting at 0.
     VFS: Mounted root (romfs filesystem).
     DEBUG: inside init (CONFIG_BLK_DEV_INITRD)
     Shell invoked to run file: /etc/rc
     Command: hostname FlightRecorder
     Command: /bin/expand /etc/ramfs.img /dev/ram0
     Command: mount -t proc proc /proc
...

So wie es scheint, kann man einen Debugmodus für das init

andreas@gericom:/suse9.1/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/romfs/bin> ls -l init
-rwxr--r-- 1 andreas users 19176 28. Mär 16:50 init

einrichten!

Hier ein paar wichtige Codezeilen aus boa.c, worin sich main() befindet:

...
#include <syslog.h>
...
int main(int argc, char **argv)
{
...
        openlog("boa", LOG_PID, 0);
...

boa bietet folgenden einfachen Debug-Modus:

andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/user/boa/src> grep DBG *.c
alias.c:        DBG(printf("add_cp_url('%s','%s')\n",fakename,codepage);)
alias.c:        DBG(printf("chroot_aliases (root=%s)\n",server_chroot);)
auth.c: DBG(printf("auth_check_userpass(%s,%s,...);\n",user,pass);)
auth.c:  DBG(printf("auth_authorize\n");)
boa.c:  DBG(printf("main:give out privs\n");)
config.c:#define DBG(x) x
config.c:#define DBG(x)
config.c:       DBG(printf("User %s = ", v1);)
config.c:       DBG(printf("%d\n", server_uid);)
config.c:       DBG(printf("Group %s = ", v1);)
config.c:       DBG(printf("%d\n", server_gid);)
config.c:       DBG(printf("Setting pointer %p to string %s ..", t, v1);)
config.c:               DBG(printf("done.\n");)
config.c:               DBG(printf("skipped.\n");)
config.c:       DBG(printf("Setting pointer %p to integer string %s ..", t, v1);)
config.c:                       DBG(printf(" Integer converted as %d, done\n",i);)
config.c:               DBG(printf("skipped.\n");)
config.c:       DBG(printf ("Setting pointer %p to unity\n", t);)
config.c:       DBG(printf("Checking string '%s' against keyword list\n",c);)
config.c:               DBG(fprintf(stderr, "%s args=%d '%s' '%s' '%s'\n", keyw, args,
hash.c: DBG(printf("chroot_virtual_hosts();\n");)
nls.c:#define DBG(x) x
nls.c:#define DBG(x)
nls.c:  DBG(printf("nls_get_table\n");)
nls.c:  DBG(printf("nls_try_redirect\n");)
nls.c:  DBG(printf("nls_set_codepage\n");)
andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/user/boa/src> grep DBG *.h
boa.h:#define DBG(x) x
boa.h:#define DBG(x)
andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/user/boa/src>

Wobei in boa.h komplett folgendes steht:

#ifdef DEBUG
#define DBG(x) x
#else
#define DBG(x)
#endif

Laut S.31 in "Linux-Treiber entwickeln" ist dieses Define ein Standard-Define, welches direkt in der Quelldatei mit #define DEBUG oder sogar beim Aufruf des "gcc" mit gcc -DDEBUG quellcode.c aufgerufen wird.

Aufgrund dessen schreibe ich direkt in das File "boa.c":

#define DEBUG

#include "boa.h"
...
int main(int argc, char **argv)
{
        int c;                                          /* command line arg */
        int s_port = 80;

        DBG(printf("main: BOA at the beginning\n");)
...

Der Diff zeigt, daß genau boa.c neu compiliert wurde:

andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324> diff out_test2.txt out_test3.txt
527c527,528
< make[3]: Für das Ziel »all« ist nichts zu tun.
---
> m68k-elf-gcc -m5307 -DCONFIG_COLDFIRE -Os -g -fomit-frame-pointer -m5307 -DCONFIG_COLDFIRE  -Dlinux
 -D__linux__ -Dunix -D__uClinux__ -DEMBED
 -I/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/uClibc/include
 -I/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/libm
 -I/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/libcrypt_old
 -I/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324 -fno-builtin -msep-data
 -I/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/linux-2.4.x/include   -c
 -o boa.o boa.c
> m68k-elf-gcc -m5307 -DCONFIG_COLDFIRE -Os -g -fomit-frame-pointer -m5307 -DCONFIG_COLDFIRE  -Dlinux
 -D__linux__ -Dunix -D__uClinux__ -DEMBED
 -I/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/uClibc/include
 -I/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/libm
 -I/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/libcrypt_old
 -I/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324 -fno-builtin -msep-data
 -I/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/linux-2.4.x/include
 -Wl,-elf2flt -Wl,-move-rodata -nostartfiles
 /home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/uClibc/lib/crt0.o
 -L/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/uClibc/.
 -L/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/uClibc/lib
 -L/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/libm
 -L/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/libnet
 -L/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/libdes
 -L/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/libaes
 -L/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/libpcap
 -L/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/libssl
 -L/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/libcrypt_old
 -L/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/prop/libsnapgear++
 -L/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/prop/libsnapgear
 -L/home/andreas/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/lib/zlib -o boa alias.o
 auth.o boa.o cgi.o cgi_header.o config.o get.o hash.o globals.o log.o nls.o pipe.o queue.o read.o request.o
 response.o signals.o timestamp.o util.o -lcrypt_old -lc
663c664
< 30 blocks
---
> 29 blocks
1088,1281c1089,1282
< 2    boa                  [0x30c     , 0x64c26   ] 0100744, sz 79852, at 0x34b80
< 2    tip                  [0x30c     , 0x64c37   ] 0100744, sz 29468, at 0x48390


Beim Start sieht man aber erstmal überhaupt nichts!

Ich schalte noch in "...uClinux-dist-20040218-cobra-20040324/user/init" in der Datei "simpleinit.c" das Define "DEBUGGING" ein.

Allerdings wieder keine Änderung in der Boot-Ausgabe sichtbar. Jetzt sehe ich:

andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/linux-2.4.x/init> ls
do_mounts.c  do_mounts.o  main.c  main.o  version.c  version.o
andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/linux-2.4.x/init>

daß es noch ein zweites init gibt! Darin finden sich dann z.B. diese Zeilen:

        if (execute_command)
                run_init_process(execute_command);

        run_init_process("/sbin/init");
        run_init_process("/etc/init");
        run_init_process("/bin/init");
        run_init_process("/bin/sh");

        panic("No init found.  Try passing init= option to kernel.");

Mit run_init_process fogendermaßen definiert:

static void run_init_process(char *init_filename)
{
        argv_init[0] = init_filename;
        execve(init_filename, argv_init, envp_init);
}

Also wird doch zumindest laut Code das existierende "/bin/init" aufgerufen

Der COBRA-Boot (hier nochmals unser wichtiger Ausschnitt):

...
VFS: Mounted root (romfs filesystem) readonly.
Freeing unused kernel memory: 32k freed (0xfc000 - 0x103000)
Shell invoked to run file: /etc/rc
Command: hostname cobra1
Command: /bin/expand /etc/ramfs.img /dev/ram0
Command: mount -t proc proc /proc
...

Ich finde:

andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324 \
/user> find . -name "*.c" | xargs -n3 grep 'Shell invoked'
./sash/sash.c:          printf("Shell invoked to run file: %s\n",argv[1]);
andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/user>

Also scheint zum Zeitpunkt der Ausführung des obigen Codes "/bin/init" nicht sichtbar zu sein, da in der Rangfolge effektiv "/bin/sh" aufgerufen wird.

Denn der Aufruf execve(init_filename, argv_init, envp_init); sorgt dafür, daß der laufende Prozess seinen Programmcode auswechselt. Da der Code wohl gegen den von der "sash" ausgewechselt wurde, wie die Ausgabe auf den Bildschirm beweist, kann der zuvor vollzogene Versuch "init" aufzurufen, nicht geklappt haben. Oder wird doch "init" aufgerufen und danach normal beendet?

Viele offene Fragen!!!!

Ich finden den hier:

andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/linux-2.4.x/init> ls
do_mounts.c  do_mounts.o  main.c  main.o  version.c  version.o
andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/linux-2.4.x/init>

in main.c gefundenen Quellcode:

asmlinkage void __init start_kernel(void)
{
...
        printk("Kernel command line: %s\n", saved_command_line);
...

auch in der Bootausgabe:

...
Building zonelist for node : 0
Kernel command line:
PID hash table entries: 16 (order 4: 128 bytes)
Memory available: 6280k/8192k RAM, 0k/0k ROM (876k kernel code, 146k data)
Calibrating delay loop... 6.98 BogoMIPS
kmem_create: Forcing size word alignment - mm_struct
kmem_create: Forcing size word alignment - filp
...

void __init start_kernel(void) wird gerufen von:

andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/linux-2.4.x> find . -name "*.c" | xargs -n3 grep 'start_kernel('
./arch/ia64/sn/kernel/setup.c: * for bringup.  See start_kernel() in init/main.c.
./arch/m68k/mac/debug.c: * that is called from start_kernel() before setup_arch() and just registers
./arch/mips/baget/balo.c:static void start_kernel(void)
./arch/mips/baget/balo.c:       start_kernel();
./arch/mips/galileo-boards/ev96100/time.c: * called from start_kernel()
./arch/mips/kernel/setup.c:extern asmlinkage void start_kernel(void);
./arch/mips/kernel/setup.c:     start_kernel();
./arch/alpha/boot/main.c:void start_kernel(void)
./arch/alpha/boot/bootp.c:start_kernel(void)
./arch/alpha/boot/bootpz.c:start_kernel(void)
./arch/niosnommu/kernel/start.c:        extern void start_kernel(void);
./arch/niosnommu/kernel/start.c:        start_kernel();
./arch/blackfin/kernel/traps.c:/* Initiate the event table handler  ---- called from init/main.c start_kernel()
./arch/mips64/kernel/setup.c:extern ATTRIB_NORET asmlinkage void start_kernel(void);
./arch/mips64/kernel/setup.c:   start_kernel();
./arch/parisc/kernel/smp.c: * Do what start_kernel() and main() do for boot strap processor (aka monarch)
./arch/parisc/kernel/setup.c:   ** called by start_kernel(). In other words, this code can't
./arch/parisc/kernel/setup.c:   ** start_kernel().
./arch/x86_64/kernel/head64.c:void __init x86_64_start_kernel(char * real_mode_data)
./arch/x86_64/kernel/head64.c:  start_kernel();
./init/main.c:asmlinkage void __init start_kernel(void)
andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/linux-2.4.x>

Und bei unserem COBRA-Board:

andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324 \
/linux-2.4.x/arch/m68knommu/platform/5282/senTec> ls
crt0_ram.o  crt0_ram.S  ram.ld
andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324 \
/linux-2.4.x/arch/m68knommu/platform/5282/senTec> less crt0_ram.S
andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324 \
/linux-2.4.x/arch/m68knommu/platform/5282/senTec> tail crt0_ram.S

        /*
         *      Assembler start up done, start code proper.
         */
        jsr     start_kernel                    /* Start Linux kernel */

_exit:
        jmp     _exit                           /* Should never get here */

/*****************************************************************************/
andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324 \
/linux-2.4.x/arch/m68knommu/platform/5282/senTec>

Dieser Code:

#ifdef DEBUGGING
        for(i = 0; i < numcmd; i++) {
        char **p;
                p = inittab[i].toks;
                printf("toks= %s %s %s %s\n",p[0], p[1], p[2], p[3]);
                printf("tty= %s\n", inittab[i].tty);
                printf("termcap= %s\n", inittab[i].termcap);
        }
        /*exit(0);*/
#endif

welcher sich in user/init/simpleinit.c findet, wird jetzt doch gezeigt:

Command: cat /etc/motd
===============================================
               COBRA5282 board
               Version 20040324
===============================================
Command:
Execution Finished, Exiting
toks= /bin/sh (null) (null) (null)
tty= console
termcap= linux
toks= /bin/inetd (null) (null) (null)
tty= inet
termcap= unknown
toks= /bin/boa (null) (null) (null)
tty= boa
termcap= unknown

Sash command shell (version 1.1.1)
/>

Dieser in:

andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/linux-2.4.x/init> ls
do_mounts.c  do_mounts.o  main.c  main.o  version.c  version.o
andreas@gericom:~/Development/COBRA_rot/uClinux/uClinux-dist-20040218-cobra-20040324/linux-2.4.x/init>

dort in main.c zu findende Code:

static int init(void * unused)
{
        struct files_struct *files;
        lock_kernel();
        do_basic_setup();
        printk("do_basic_setup() done\n");
        prepare_namespace();

        /*
         * Ok, we have completed the initial bootup, and
         * we're essentially up and running. Get rid of the
         * initmem segments and start the user-mode stuff..
         */
        free_initmem();
        unlock_kernel();

wurde hier in der Bootausgabe mit ausgegeben:

...
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP
kmem_create: Forcing size word alignment - ip_dst_cache
IP: routing cache hash table of 512 buckets, 4Kbytes
TCP: Hash tables configured (established 512 bind 512)
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
do_basic_setup() done
VFS: Mounted root (romfs filesystem) readonly.
Freeing unused kernel memory: 24k freed (0xdc000 - 0xe1000)
Shell invoked to run file: /etc/rc
Command: hostname cobra1
...

Die in start_kernel() eingeschobenen printk()-Aufrufe finden sich hier:

dBUG> go 10000
Linux version 2.4.24-uc0 (andreas@gericom) (gcc version 2.95.3 20010315 (release)(ColdFire patches - 20010318 from http://fiddes.net/coldfire/)(uClinux XIP and s8

uClinux/COLDFIRE(m5282)
COLDFIRE port done by Greg Ungerer, gerg@snapgear.com
Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne
On node 0 totalpages: 2048
zone(0): 0 pages.
zone(1): 2048 pages.
zone(2): 0 pages.
Kernel command line:

Kernel init_modules() fertig, falls aktiviert

Calibrating delay loop... 6.96 BogoMIPS
Memory available: 6268k/8192k RAM, 0k/0k ROM (713k kernel code, 203k data)
kmem_create: Forcing size word alignment - vm_area_struct
kmem_create: Forcing size word alignment - mm_struct
kmem_create: Forcing size word alignment - filp
Dentry cache hash table entries: 1024 (order: 1, 8192 bytes)
Inode cache hash table entries: 512 (order: 0, 4096 bytes)
Mount cache hash table entries: 512 (order: 0, 4096 bytes)
kmem_create: Forcing size word alignment - bdev_cache
kmem_create: Forcing size word alignment - cdev_cache
kmem_create: Forcing size word alignment - kiobuf
Buffer cache hash table entries: 1024 (order: 0, 4096 bytes)
Page-cache hash table entries: 2048 (order: 1, 8192 bytes)
POSIX conformance testing by UNIFIX

/init/main.c: Kernel vor Aufruf von rest_init()

Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039
...


Copyright © Andreas Birkert
Letzte Aktualisierung am 20. Dezember 2013
Home Inhaltsverzeichnis Textausgaben der Programme auf die Console nicht koordiniert Widerspruch: init läuft, obwohl execve zurückkehrt