kernel学习:浅析do_exit

进程在退出时,必须释放它所拥有的资源,并通过某种方式告诉父进程。进程的退出一般是显示或隐式地调用了eixt(),或者接受了某种信号。不过什么原因退出,最终都调用了do_exit。

用于进程退出的系统调用有两个exit和exit_group,exit只是终止某个进程,而exit_group整个线程中的进程。它们在内核中的服务函数分别为sys_exit和sys_exit_group,它们又分别调用了do_exit和do_group_exit。而do_group最终又调用了do_exit。

do_exit定义在kernel/exit.c中:

僵死进程:僵死进程是一个进程已经退出,它的内存和资源已经释放掉了,但是位了时系统在它退出后能够获得它的退出状态等信息,它的进程描述符仍然保留。

一个进程退出时,它的父进程会接收到一个SIGCHLD信号,一般情况下这个信号的处理函数会执行wait系列函数等待子进程的结束。从子进程退出到父进程调用wait(子进程结束)的这段时间,子进程称为僵死进程。执行ps –ef命令以“z”结尾的为僵死进程。

僵死进程很特殊,它没有任何可执行代码,不会被调度,只有一个进程描述符用来记录退出等状态,除此之外不再占用其他任何资源。

查看本栏目更多精彩内容:http://www.bianceng.cnhttp://www.bianceng.cn/OS/unix/

如果僵死进程的父进程没有调用wait,则该进程会一直处于僵死状态。如果父进程结束,内核会在当前线程组里为其找一个父进程,如果没找到则把init作为其父进程,此时新的父进程将负责清楚其进程。如果父进程一直不结束,该进程会一直僵死。在root下用kill -9 也不能将其杀死。

下面只对do_exit重点地方解析下:

struct task_struct *tsk = current;//获取当前要释放进程的进程描述符

exit_signals(tsk);  /* sets PF_EXITING 以免内和其他部分访问该进程*/

exit_mm(tsk);  

    if (group_dead)
        acct_process();
    trace_sched_process_exit(tsk);  

    exit_sem(tsk);
    exit_files(tsk);
    exit_fs(tsk);
    check_stack_usage();
    exit_thread();
/*更新父子关系,并告诉父进程正在退出*/
    exit_notify(tsk, group_dead);

最后要切换为其他进程

/*切换到其他进程*/
    schedule();

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索函数
, 进程
, 其他
, exit
, 信号
, 状态
, 一个
exit()
,以便于您获取更多的相关知识。

时间: 2016-02-07

kernel学习:浅析do_exit的相关文章

kernel学习之分析sys_reboot

系统调用的内容到这里已经讲述了很多,该到去kernel中窥看一个服务例程具体实现的时候了.在linux中关机和重启命令有shutdown,reboot,init,poweroff,halt,telinit.它们都是通过sys_reboot来实现的.在kernel/sys.c中. /* *kernel/sys.c文件中定义 * Reboot system call: for obvious reasons only root may call it, * and even root needs t

kernel学习之动手添加系统调用(ARM)

我是在linux2.6.38中添加的系统调用,在mini6410开发板上测试的. 添加系统调用: 向内核中添加系统调用,需要执行三个步骤: 1.添加新的内核函数 2.更新unistd.h 3.更新系统调用表 1. 在kernel/sys.c中添加函数 asmlinkageint sys_add(int a,int b) { return a+b; } 2. 在arch/arm/include/asm/unistd.h 添加: #define_NR_add (_NR_SYSCALL+BASE +

kernel学习之sys_fork,sys_vfork,sys_clone和kernel_thread

用户空间进程创建接口:fork,vfork,clone函数,这里只做简单说明. fork:使用该系统调用时,子进程复制父进程的全部资源.由于要复制父进程进程描述符给子进程(进程描述的结构很大!!),这一过程开销是很大的.linux采用了"写时复制技术"(copy on write,COW),使子进程先共享父进程的物理页,只有子进程进行写操作时,再复制对应的物理页,避免了无用的复制开销,提高了系统的性能. 实现代码(x86):arch/x86/kernel/process.c int s

kernel学习:copy_process

在do_fork中调用了copy_process,该函数及其重要.该函数创建进程描述符和子进程需要的其他数据结构.它定义在linux2.6.xxx/kernel/fork.c. 只对关键部分进行了注释如下: /* * This creates a new process as a copy of the old one, * but does not actually start it yet. * * It copies the registers, and all the appropria

kernel学习:内核线程

由于内核对进程和线程不做区分,所以内核线程(kernel thread)又称为内核进程(kernel process).注意不能把普通进程中的线程理解为进程. 内核线程和普通进程的区别: 1.内核线程只运行在内核态,普通进程可以运行在内核态和用户态. 2.内核线程只能调用内核函数,普通进程可以通过系统调用调用内核函数. 3.内核线程只能运行在大于PAGE_OFFSET的地址空间,而普通进程可以4G的地址空间(除了访问用户空间的3G,通过系统调用可以访问内核空间的1G空间). 由于内核线程不受用户

kernel学习之系统调用过程分析

过程分析: 1.系统调用需要一个用户空间到内核空间的转换,不同的平台有不同的指令来完成这样的转换,这个指令也叫做操作系统陷入(operating systemtrap)指令.在linux中对于x86来说是用软中断0x80,也即是int $0x80.软中断由软件指令触发,硬中断由硬件触发. 通过软中断,系统会跳到一个预定的内核空间.它指向了系统调用处理程序(不是系统调用服务程序)system_call函数(arch/x86/kernel/entry32.h).如上图. 2.system_call到

kernel学习之进程调度的目标,nice值,静态优先级,动态优先级

进程调度的目标,nice值,静态优先级,动态优先级,实时优先级,时间片 进程调度的目标: 1.高效性:高效意味着在相同的时间下要完成更多的任务.调度程序会被频繁的执行,所以调度程序要尽可能的高效. 2.加强交互性能(interactivity):在系统相当的负载下,也要保证系统的响应时间. 3.保证公平和避免饥渴. 4.SMP调度:调度程序必须支持多处理系统.系统必须追踪哪些进程在哪个cpu上运行.确保在同一时间中,一个进程不能再多于1个的cpu上运行. 5.软实时调度(soft real-ti

kernel学习之task_struct

程序和进程: 程序是存放在磁盘上的一系列代码和数据的可执行镜像,是一个静态的实体: 进程是一个执行的程序,它是动态的实体,它除了包含指令段,数据段等静态数据外(数据是可以是动态变化的),还包括当前的状态信息,如临时数据堆栈信息,当前处理器的寄存器信息等动态信息.这些动态信息通常称为进程上下文. 从内核角度来看,进程是操作系统分配内存,cpu时间片等资源的最小单位.其中它用到的数据和信息大部分都是在动态变化的.在linux内核中进程上下文通常用task_struct来描述,进程切换负责保存当前进程

kernel学习之do_fork

在上次的文章中详细的介绍了几个系统调用,它们最终都是调用了do_fork来实现进程的创建.do_fork主要完成了进程描述符的创建和pid的创建,以及进程描述符的拷贝. 本系列文章所用源码均来自2.6.38. 源码分析如下: /* * Ok, this is the main fork-routine. * * It copies the process, and if successful kick-starts * it and waits for it to finish using th