Linux内核-进程管理

举报
远航 | FIBOS 发表于 2020/12/01 22:38:51 2020/12/01
【摘要】 Linux内核-进程管理 1.进程 #内核调度的对象是线程,不是进程 #对Linux而言,线程只是特殊的进程 #进程提供两种虚拟机制:虚拟处理器、虚拟内存 #创建进程通过fork()来从父进程复制创建进程 2.进程描述符 #任务队列:双向链表(每一项都是task_struct--->进程描述符) #Linux通过s...

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所占的页

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

  

文章来源: blog.csdn.net,作者:冰水比水冰,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/luoyhang003/article/details/40262147

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。