Main.c of linux kernel analysis

The main function mainly does some initialization, such as the initialization of memory, block devices, character devices, etc., and then creates a child process to open bin/sh

 

    mem_init(main_memory_start,memory_end);
    trap_init(); // Initialize the trap gate (hardware interrupt vector). (Kernel/traps.c)
    blk_dev_init(); // Block device initialization. (Kernel/blk_dev/ll_rw_blk.c)
    chr_dev_init(); // Character device initialization. (Kernel/chr_dev/tty_io.c) is empty to prepare for future expansion.
    tty_init(); // tty initialization. (Kernel/chr_dev/tty_io.c)
    time_init(); // Set startup time -> startup_time.
    sched_init(); // Scheduler initialization (loaded tr, ldtr of task 0) (kernel/sched.c)
    buffer_init(buffer_memory_end); // Initialize buffer management, build memory linked list, etc. (Fs/buffer.c)
    hd_init(); // Initialize the hard disk. (Kernel/blk_dev/hd.c)
    floppy_init(); // Initialize the floppy drive. (Kernel/blk_dev/floppy.c)

 

 

Create task 1 in task 0

    if (!fork()) {        /* we count on this going ok */
        init();
    }

 

init function: initialize the shell environment, execute bin/sh
void init(void)
{     int pid,i;

// Read hard disk parameters including partition table information and create virtual disks and install root file system devices.
// This function is defined by the macro on line 25, and the corresponding function is sys_setup(), in kernel/blk_drv/hd.c.
    setup((void *) &drive_info);

    (void) open("/dev/tty0",O_RDWR,0); // Open the device "/dev/tty0" with read-write access,
                                        // here corresponds to the terminal console.
                                        // The returned handle number 0 - stdin standard input device.
    (void) dup(0); // Duplicate the handle and generate handle No. 1 - stdout standard output device.
    (void) dup(0); // Duplicate the handle and generate handle No. 2 - stderr standard error output device.
    printf("%d buffers = %d bytes buffer space\n\r",NR_BUFFERS, \
        NR_BUFFERS*BLOCK_SIZE); // Print buffer blocks and total bytes, 1024 bytes each.
    printf("Free mem: %d bytes\n\r",memory_end-main_memory_start);//The number of free memory bytes.

// The following fork() is used to create a subprocess (subtask). For the created child process, fork() will return a value of 0,
// for the original (parent process) it will return the process number of the child process. So if (!(pid=fork())) {...} is the content executed by the child process.
// The child process closes handle 0 (stdin), opens the /etc/rc file in read-only mode, and executes the /bin/sh program. The parameters and
// environment variables are given by the argv_rc and envp_rc arrays respectively. See the description below.
    if (!(pid=fork())) {         close(0);         if (open("/etc/rc",O_RDONLY,0))             _exit(1); // If opening the file fails, exit (/lib /_exit.c).         execve("/bin/sh",argv_rc,envp_rc); // Load the /bin/sh program and execute it. (/lib/execve.c)         _exit(2); // If execve() fails to execute, exit (error code 2, "File or directory does not exist").     }





// Below is the statement executed by the parent process. wait() is to wait for the child process to stop or terminate, and its return value should be the child process
// process number (pid). The function of these three sentences is that the parent process waits for the end of the child process. &i is the
// location where the returned status information is stored . If the return value of wait() is not equal to the child process number, continue to wait.
    if (pid>0)
        while (pid != wait(&i))
        {/* nothing */;}

// -
// If the execution ends here, it means that the execution of the newly created child process has stopped or terminated. In the following loop, first create
a child process. If an error occurs, the message "The initialization program failed to create the child process" will be displayed and the execution will continue. To
// create a child process to close all previously also left handle (stdin, stdout, stderr), a newly created
// session and set process group number, and then re-open / dev / tty0 as stdin, stdout and copy to And stderr.
// Execute the system interpreter /bin/sh again. However, another set of parameters and environment arrays were selected for this execution (see above).
// Then the parent process runs wait() again to wait. If the child process stops executing again, an error message is displayed on the standard output
// "The child process pid stopped running, the return code is i",
// and then continue to try again..., forming a "big" endless loop.
    while (1) {         if ((pid=fork())<0) {             printf("Fork failed in init\r\n");             continue;         }         if (!pid) {             close(0);close(1) ;close(2);             setsid();             (void) open("/dev/tty0",O_RDWR,0);








            (void) dup(0);
            (void) dup(0);
            _exit(execve("/bin/sh",argv,envp));
        }
        while (1)
            if (pid == wait(&i))
                break;
        printf("\n\rchild %d died with code %04x\n\r",pid,i);
        sync();
    }
    _exit(0);    /* NOTE! _exit, not exit() */
}

Guess you like

Origin blog.csdn.net/wyyy2088511/article/details/108367223