• 内核进程初始化和创建


    task_struct

            1.进程的状态

    分时技术进行多进程调度

    重点:进程的创建是如何的?

            linux在初始化的过程中那个会进行0号进程的创建,fork

            sched_init();  做了什么

    内核态  不可抢占

    用户态  可以抢占

    move_to_user_mode();  把内核状态切换到用户态

    在内核初始化的过程中,会手动创建0号进程,0号进程是所有进程的父进程

    进程初始化:

    在o号进程中:

            1.打开标准输入、输出、错误控制台句柄

            2.创建1号进程,如果创建成功,则在1号进程中

                    首先打开"/etc/rc"文件

                    执行SHELL程序"/bin/sh"

            3.0号进程不可能结束,他会在没有其他进程调用时运行,只会执行for(;;) pause();

    进程创建:

    fork

    1.在task链表中找一个空位存放进程

    2.创建一个task_struct

    3.设置task_struct

    进程的创建就是对0号进程或者当前进程的复制

            0号进程复制 结构体的复制 把task[0]对应的task_struct复制给新创建的task_struct

            对于栈堆的拷贝  当进程创建的时候要复制原有栈堆(复制完清空)

    进程的创建是系统调用:

    .align 2
    _sys_fork:
        call _find_empty_process
        testl %eax,%eax
        js 1f
        push %gs
        pushl %esi
        pushl %edi
        pushl %ebp
        pushl %eax
        call _copy_process
        addl $20,%esp
    1:    ret

    1.给当前要创建的进程分配一个进程号:find_empty_process

    2.进程创建主体copy_process,为子进程创建一个task_struct结构体

            struct task_struct *p;

            p = (struct task_struct *) get_free_page();

    3.将当前子进程放入到整体进程链表中

            task[nr] = p;

    4.设置创建的task_struct

    1. p->state = TASK_RUNNING;
    2. p->pid = last_pid;
    3. p->father = current->pid;
    4. p->counter = p->priority;
    5. p->signal = 0;
    6. p->alarm = 0;
    7. p->leader = 0; /* process leadership doesn't inherit */
    8. p->utime = p->stime = 0;
    9. p->cutime = p->cstime = 0;
    10. p->start_time = jiffies;
    11. p->tss.back_link = 0;
    12. p->tss.esp0 = PAGE_SIZE + (long) p;
    13. p->tss.ss0 = 0x10;
    14. p->tss.eip = eip;
    15. p->tss.eflags = eflags;
    16. p->tss.eax = 0;
    17. p->tss.ecx = ecx;
    18. p->tss.edx = edx;
    19. p->tss.ebx = ebx;
    20. p->tss.esp = esp;
    21. p->tss.ebp = ebp;
    22. p->tss.esi = esi;
    23. p->tss.edi = edi;
    24. p->tss.es = es & 0xffff;
    25. p->tss.cs = cs & 0xffff;
    26. p->tss.ss = ss & 0xffff;
    27. p->tss.ds = ds & 0xffff;
    28. p->tss.fs = fs & 0xffff;
    29. p->tss.gs = gs & 0xffff;
    30. p->tss.ldt = _LDT(nr);
    31. p->tss.trace_bitmap = 0x80000000;

    如果当前进程使用了协处理器,那就设置协处理器

    if (last_task_used_math == current)

            __asm__("fnsave %0"::"m" (p->tss.i387));

    进行老进程向新进程代码段 数据段(LDT)的拷贝

        if (copy_mem(nr,p)) {

            free_page((long) p);

            return -EAGAIN;

        }

    如果父进程打开了某个文件,那么子进程也同样打开这个文件,所以讲文件打开计数+1

        for (i=0; i

            if (f=p->filp[i])

                f->f_count++;

    将父进程的属性继承

        if (current->pwd)

            current->pwd->i_count++;

        if (current->root)

            current->root->i_count++;

    设置进程的两个段,并结合上文设置的变量,组合成一个进程

        set_tss_desc(gdt+(nr<<1)+FIRST_TSS_ENTRY,&(p->tss));

        set_ldt_desc(gdt+(nr<<1)+FIRST_LDT_ENTRY,&(p->ldt));

    返回创建的进程id

        return last_pid;

  • 相关阅读:
    【C++】类和对象(中)
    计算机网络 --- TCP与UDP协议
    2024考研王道计算机408数据结构+操作系统+计算机组成原理+计算机网络
    vite 使用本地 ip + localhost 访问服务
    C语言——qsort()函数_学习笔记
    SpringBoot集成Lombok
    CSDN获评2022年科创中国开源创新榜「开源机构」
    jvm调优思路
    Java基础面试题
    公众号突破2个限制技巧
  • 原文地址:https://blog.csdn.net/weixin_66218530/article/details/134036735