2019-2020-1 20199315 "Linux kernel principle and Analysis" in the seventh week of work

Six experimental lab building

Analysis of the Linux kernel process create a new process

Reading data structure task_struct http://codelab.shiyanlou.com/xref/linux-3.18.6/include/linux/sched.h#1235;

  • Process is computer programs run entities. In the thread-oriented design system (Linux 2.6 and later versions), the process itself is not the basic operation of the unit, but the container thread.

  • In Linux, task_struct in fact, is commonly referred to the PCB. The structure is defined in:

/include/linux/sched.h
  • Three functions of the operating system: process management, memory management and file system

  • Process control block PCB - task_struct

    • In TASK_RUNNING process is running, but it has not run depends on it has no control over the cpu to get, that this process has not actually executed on the CPU

    • Marked pid process

    • Process creates a parent-child relationship, when programming often need to refer to such a parent-child relationship. There are several process descriptor field is used to represent such relationships.

Linux kernel state transition diagram:

Analysis fork function corresponding kernel process sys_clone, create a new understanding of how to create and modify processes task_struct data structure;

1.Linux in the process of creating a total of three functions:

  • fork, create a child process

  • vfork, fork and similar, but the parent and child shared address space, and the child process to run the parent process.

  • clone, primarily used for creating threads

  • fork, vfork, and clone three system calls can create a new process, and they are to achieve the creation process by calling do_fork, do_fork completed most of the work created in the function call copy_process () function, and then let the process begin run.

  • copy_process () function works as follows:

    • Call dup_task_struct () to create a kernel stack, thread_info task_struct for the new structure and process, these values ​​are the same as the value of the current process

    • an examination

    • The child started to distinguish themselves from the parent process open. Many members in the process descriptor is cleared or set to an initial value

    • Child process status is set to TASK_UNINTERRUPTIBLE, to ensure that it will not be put into operation

    • copy_process () call copy_flags () to update the flags of the members of task_struct. It indicates whether the process has superuser privileges PF_SUPERPRIV flag is cleared. It indicates that the process has not been called exec () PF_FORKNOEXEC mark function is set

    • Call alloc_pid () to assign a valid PID for the new process

    • The transfer to the clone () parameter flag, copy_process () copied or shared file open, file system information, the signal processing function, the process address space and other namespaces

    • Finally, copy_process () to do outstanding work and returns a pointer to the child process

2. The process of creation

YSCALL_DEFINE0(fork)
{
    return do_fork(SIGCHLD, 0, 0, NULL, NULL);
}
#endif
 
SYSCALL_DEFINE0(vfork)
{
    return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0,
            0, NULL, NULL);
}
 
SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
         int __user *, parent_tidptr,
         int __user *, child_tidptr,
         int, tls_val)
{
    return do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr);
}

3. Analyze do_fork Code

long do_fork(unsigned long clone_flags,
          unsigned long stack_start,
          unsigned long stack_size,
          int __user *parent_tidptr,
          int __user *child_tidptr)
{
    struct task_struct *p;
    int trace = 0;
    long nr;
 
    // ...
     
    // 复制进程描述符,返回创建的task_struct的指针
    p = copy_process(clone_flags, stack_start, stack_size,
             child_tidptr, NULL, trace);
 
    if (!IS_ERR(p)) {
        struct completion vfork;
        struct pid *pid;
 
        trace_sched_process_fork(current, p);
 
        // 取出task结构体内的pid
        pid = get_task_pid(p, PIDTYPE_PID);
        nr = pid_vnr(pid);
 
        if (clone_flags & CLONE_PARENT_SETTID)
            put_user(nr, parent_tidptr);
 
        // 如果使用的是vfork,那么必须采用某种完成机制,确保父进程后运行
        if (clone_flags & CLONE_VFORK) {
            p->vfork_done = &vfork;
            init_completion(&vfork);
            get_task_struct(p);
        }
 
        // 将子进程添加到调度器的队列,使得子进程有机会获得CPU
        wake_up_new_task(p);
 
        // ...
 
        // 如果设置了 CLONE_VFORK 则将父进程插入等待队列,并挂起父进程直到子进程释放自己的内存空间
        // 保证子进程优先于父进程运行
        if (clone_flags & CLONE_VFORK) {
            if (!wait_for_vfork_done(p, &vfork))
                ptrace_event_pid(PTRACE_EVENT_VFORK_DONE, pid);
        }
 
        put_pid(pid);
    } else {
        nr = PTR_ERR(p);
    }
    return nr;
}

4.do_fork work

  • Call copy_process, copy the current process out to a child process, the child process and set a corresponding context information.
  • The completion of the initialization process information vfork (if vfork call)
  • Call wake_up_new_task, the child process into a scheduler queue, in which case the child process can be selected scheduling process, to be run.
  • If vfork call, needs to block parent, know child process exec.

Analysis of a fork system call handler kernel sys_clone, verify that you create a new process of understanding on the Linux system, it is recommended to complete the experiment under laboratory building Linux virtual machine environment using gdb track.

Update to the latest version of the code menu, make rootfs compiled:

Check with the help newly added fork command:

Into the gdb debugger:

Using gdb debugging kernel tracing, set breakpoints in a number of important functions at

Start n ......

Of particular concern is where to start a new process execution? Why can successfully execute down from there? That is the starting point for how to ensure consistency with the kernel stack.

  • ret_from_fork; determine the address of the first instruction of the new process.

  • Before ret_from_fork, that is copy_thread () function childregs = current_pt_regs (); This sentence will regs parameters assigned to the parent process child process kernel stack

  • * Childregs of type pt_regs, the parameters stored inside pushed onto the stack in the SAVE ALL

  • Therefore, in RESTORE ALL after the smooth implementation continues

Problems encountered

Connection timeout problem mentioned last week, the reason should be found to be wrongly suspended QEMU interface closed ......

The correct approach should be: cd .. back LinuxKernel-- split screen - input terminal 1

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S

- without closing the graphical interface, the terminal 2 goes directly gdb

This is my seventh week of the Linux learning content, if insufficient, please criticism and be grateful.

the above

Guess you like

Origin www.cnblogs.com/qianxiaoxu/p/11785971.html