Linux内核-进程管理

Linux内核-进程管理


1.进程

#内核调度的对象是线程,不是进程

#对Linux而言,线程只是特殊的进程

#进程提供两种虚拟机制:虚拟处理器、虚拟内存

#创建进程通过fork()来从父进程复制创建进程


2.进程描述符

#任务队列:双向链表(每一项都是task_struct--->进程描述符)

#Linux通过slab分配器分配task_struct

#内核通过唯一的进程标识值(PID)来标识进程

#五种进程状态:  1.TASK_RUNNING 进程可执行

                        2.TASK_INTERRUPTIBLE 可中断

                        3.TASK_UNINTERRUPTIBLE 不可中断

                        4._TASK_TRACED 被其他进程跟踪

                        5._TASK_STOPPED 进程停止执行

#设置进程状态: set_task_state(task, state)函数和set_surrent_state(state)函数

#所有进程都是PID为1的init进程的后代

#init进程描述符 init_task


3.进程创建

#fork()和exec()

 fork()拷贝当前进程创建子进程

 exec()读入可执行文件并载入空间地址开始执行

#写时拷贝:fork()使用写时拷贝(copy-on-write)使得地址空间的页拷贝被推迟到实际发生写入时才进行

                   (fork()后立即执行exec()就无需进行拷贝)

                    fork()的实际开销就是复制父进程的页表以及分配进程描述符

#fork()执行过程:通过系统调用clone()调用fork()

    clone()调用do_fork(),do_fork()调用copy_process()

    copy_process()过程:

        1.调用dum_task_struct()为新进程创建内核栈、thread_info、task_struct

        2.确保创建子进程后当前进程数没有超过限制

        3.子进程开始与父进程区别开来,进程描述符中的许多成员初始化或清0

        4.子进程的状态被设置为TASK_UNINTERRUPTIBLE

        5.调用copy_flags()更新来更新task_struct的flags成员

        6.调用alloc_pid()为新进程分配PID

        7.copy_process()拷贝共享打开的文件、文件系统信息、信号处理函数、进程地址空间和命名空间

        8.copy_process()做扫尾工作并返回一个指向子进程的指针

#vfork():向clone()系统调用传递一个特殊标志来进行:

    ​    ​1.调用copy_process()时,task_struct的vfork_done成员被设置为NULL

    ​    ​2.如果执行do_fork()时给定地址,vfork_done会指向一个特定地址

    ​    ​3.子进程开始执行后,父进程不会立即开始执行,直到vfork_done指针向它发出信号

    ​    ​4.调用mm_release()进程退出地址空间,并检查vfork_done是否为空,若不为空,等待父进程发送信号

    ​    ​5.回到do_fork(),父进程醒来并返回


4.线程在Linux中的实现

#线程机制提供了在同一程序中共享内存地址的空间运行的一组线程

#Linux将所有的线程当做进程来实现

#创建线程:

    ​clone(CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND , 0)


5.进程终结

#发生在进程调用exit()系统调用时:

    ​任务大部分要靠do_exit()来完成:

    ​    ​1.将task_struct的标志成员设置为PF_EXITING

    ​    ​2.调用del_timer_sync()删除任一内核定时器

    ​    ​3.如果BSD的进程记账开启,do_exit()调用acct_update_integrals()来输出记账信息

    ​    ​4.调用exit_mm()释放进程占用的mm_struct

    ​    ​5.调用sem_exit(),如果进程等待IPC信号,则离开队列

    ​    ​6.调用exit_files()和exit_fs()

    ​    ​7.把存放在task_struct的exit_code成员中的任务退出代码置为由exit()提供的退出代码

    ​    ​8.调用exit_notify()向父进程发送信号,为子进程寻找养父,养父为线程组中的其他线程或者init,并把进程状态设为EXIT_ZOMBIE

    ​    ​9.do_exit()调用schedule()切换到新的进程

#删除进程描述符:调用了do_exit(),进程僵死,但是系统还保留了进程描述符

    ​释放进程描述符时,release_task()会被调用:

    ​    ​1.调用_exit_signal(),该函数调用_unhash_process(),后者又调用 detach_pid()从pidhash上删除该进程,同时也要从任务列表中删除该进程

    ​    ​2._exit_signal()释放目前僵死进程的资源,进行统计记录

    ​    ​3.如果该进程为进程组最后一个进程,并且领头已经死掉,release_task()通知领头进程的父进程

    ​    ​4.release_task()调用put_task_struct()释放进程内核栈和thread_info所占的页

#孤儿进程造成的进退维谷:如果父进程在子进程之前退出,必须有机制保证子进程能找到新的父亲

  

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值