Linux系统的进程管理

系统的进程管理:

  1. 系统的进程的运转方式

    系统时间:(jiffies 系统滴答)

    CPU内部有一个RTC(定时器),会在上电的时候调用mktime函数算出从1970年的1月1日0时开始到当前开机点所过的秒数 给mktime传递的参数是从rtc芯片中读出,转化为时间存入全局变量中,并且会为jiffies所用

    1个jiffies 系统滴答是10ms,每隔10ms会引发一个定时器中断,这个中断中进行以下操作:

    1. 执行timer_interrupt进行了jiffies的自加
    2. call do_timer

    调用do_timer函数:

    if(cpl)				//CPL变量是内核中用来指示被中断程序的特权  0表示内核进程  1表示被中断用户进程
    	current->utime++;	//utime用户程序的运行时间
    else
    	current->stime++;	//stime内核程序的运行时间
    	
    next_timer :是嫁接于jiffies变量的所有定时器的事件链表,这个结构体中的jiffies是指当前时间距离要执行时间的差值,小于等于0时执行这个结构体中的函数指针fn
    task_struct  中的current 是指当前进程
    task_struct[]  task:进程向量表
    current->counter:进程的时间片
    	counter在哪里用?	进程的调度就是task_struct[]进程链表的检索,找时间片最大的那个进程对象,然后进行调用,直到时间片为0,退出   之后再进行新一轮的调用
    	counter在哪里被设置?	当全部的task_struct[] task[] 所有的进程的counter都为0,就进行新一轮的时间片分配   (*p)->counter = ((*p)->counter >>1 ) + (*p)->priority;   优先级时间片轮转调度算法
    
    • task_struct结构体介绍:内核进程就是一个结构体的链表task_struct task[]

    • 每个进程中有

      1. LDT 局部描述符(描述符都是指针) 包含:数据段 代码段

      2. TSS 进程的状态描述符 :在进程运行的过程中,CPU需要知道的进程的状态标识,以及

      3. 堆栈

        每个进程内存分布如下

        高地址

        ​ 栈

        ​ 堆

        ​ TSS

        ​ 数据段

        ​ 代码段

        低地址

        [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KLsVobKF-1630857764883)(C:\Users\zwh\AppData\Roaming\Typora\typora-user-images\image-20210905230801330.png)]

      - 系统级别  GDT  **全局描述符表**   (每个CPU都有一个GDT)
    

    在这里插入图片描述

  2. 如何进行创建一个新的进程

Linux在初始化过程中会进行0号进程的创建,用fork方法

之前的这些初始化操作都是在内核态完成

sched_init() 做了什么事情?

内核态 :不可以抢占

用户态 :可以抢占

move_to_user_mode()之后会执行fork() 创建0号用户空间进程,0号进程是所有进程的父进程,然后执行用户态的init()函数,对用户空间进行初始化

  • 0号进程:

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

    2. 创建1号进程,如果创建成功(fork返回为0),在1号进程中打开"/etc/rc"配置文件,并执行shell程序"/bin/sh"

      在调用pid = fork()时

      子程序的pid返回为零

      而父程序返回的pid值为生成子程序在系统中的真实pid值而非父程序本身在系统中的真实pid值

    3. 0号进程退出init()函数,不会结束,他会在没有其他进程调用的时候调用,只会执行for(;;)pause()暂停

  • 进程创建:

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

    2. 创建一个task_struct

    3. 设置task_struct

  • 进程的创建就是对0号进程或者当前进程的复制,task_struct task[0]结构体的复制,并进行栈堆的复制

  • 进程的创建就是一个系统调用 sys_fork

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

  2. 创建一个子进程的task_struct结构体

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

  4. 设置创建好的task_struct结构体

    1. 如果当前进程使用了协处理器,那就设置当前创建进程的协处理
    2. copy_mem 进行老进程向新进程代码段 数据段(LDT)的拷贝
    3. 如果老进程打开了某个文件,那么子进程也同样打开了这个文件,所以将文件的计数++
    4. 设置进程的两个段,并结合刚才拷贝过来的数据 组装成一个进程
    5. 给进程的状态标志设置成一个可运行的状态
    6. 返回进程的pid

进程调度

void schedule(void) 进程调度函数

switch_to(next) 进程切换函数

进程的状态:

  1. 运行状态 可以被运行 就绪状态 进程切换只能在运行状态
  2. 可中断睡眠状态 可以被信号中断(kill -8 -6 SIGCHLD 等 ) 使其变成RUNING 对应poll机制 wait/waitpid
  3. 不可中断睡眠状态 只能被wakeup所唤醒 使其编程RUNING 当多个进程等待资源的时候会进入sleep,对应这个状态
  4. 暂停状态 收到SIGSTOP SIGTSTP SIGTTIN进入暂停状态
  5. **僵尸状态 ** 进程停止运行了,但是父进程还没有将其清空 waitpid
  • 进程切换

    1. 将需要切换的进程赋值给当前进程指针 current
    2. 进行进程的上下文切换
      • 上下文:程序运行时 CPU的特殊寄存器 通用寄存器 (TSS)等信息 + 当前堆栈中的信息

sleep_on() :可以多个进程组成一个睡眠链表 ,例如某个资源是互斥的,当资源被某一个进程占用时,其他进程便无法访问此资源。那么若某进程无法得到资源,其使用sleep_on(&res_wait) 在资源的wait队列上睡眠,注意到这里的wait只是指针变量

在这里插入图片描述

《Linux内核设计的艺术》》

  1. 进程的退出
  1. 进程销毁函数 exit() --> 一个系统调用 do_exit()

    首先该函数会释放进程的代码段和数据段占用的内存,清空

  2. 关闭进程打开的所有文件,对当前的目录和i节点进行同步(文件操作)

  3. 如果当前要销毁的进程有子进程,那么就让1号进程作为新的父进程(init进程)

  4. 如果当前进程是一个会话头进程,则会终止会话中的所有进程

  5. 改变当前进程的运行状态,变成TASK_ZOMBIE僵死状态,并且向其父进程发送SIGCHLD信号

    release(struct task_struct * p )

    完成清空任务描述表中的对应进程表项,释放对应的内存页(代码段 数据段 堆栈)

    static inline int send_sig(long sig,struct task_struct *p,int priv)

    给指定的进程p发送对应的sig,task结构体中一个信号列表(*p)->signal

    static void kill_session(void)

    终止会话,终止当前进程的会话,给其发送SIGHUP信号

    int sys_kill(int pid,int sig)

    kill 不是杀死的意思,向对应的进程号或者进程组号发送任何信号

    pid >0 给对应的pid发送sig

    pid =0 给当前进程的进程组发送sig

    pid =-1 给任何进程发送

    pid <-1 给进程组号为-pid的进程组发送信号

    static void tell_father(int pid)

    向父进程发送SIGCHLD信号

    int do_exit(long code)

    ldt[1] ldt段 ldt[2] tss段


    1. 父进程在运行子进程的时候 一般都会运行wait waitpid这两个函数(父进程等待某个子进程终止的),当父进程收到SIGCHLD信号时,父进程会终止僵死状态的子进程
    2. 首先父进程会把子进程的运行时间累加到自己的进程变量中
    3. 把对应的子进程的进程描述结构体进行释放,置空任务数组中的空槽

syscall_xxx 或者do_xxx 一般都是一个中断调用的函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值