Linux进程管理(3):总结
7. exit与_exit的差异
为了理解这两个系统调用的差异,先来讨论文件内存缓存区的问题。 在linux中,标准输入输出(I/O)函数都是作为文件来处理。对应于打开的每个文件,在内存中都有对应的缓存,每次读取文件时,会多读一些记录到缓存中,这样在下次读文件时,就在缓存中读取;同样,在写文件时也是写在文件对应的缓存中,并不是直接写入硬盘的文件中,等满足了一定条件(如达到一定数量,遇到换行符\n或文件结束标志EOF)才将数据真正的写入文件。这样做的好处就是加快了文件读写的速度。但这样也带来了一些问题,比如有一些数据,我们认为已经写入了文件,但实际上没有满足一定条件而任然驻留在内存的缓存中,这样,如果我们直接用_exit()函数直接终止进程,将导致数据丢失。如果改成exit,就不会有数据丢失的问题出现了,这就是它们之间的区别了.要解释这个问题,就要涉及它们的工作步骤了。
exit():通过前面源代码分析可知,在执行该函数时,进程会检查文件打开情况,清理I/O缓存,如果缓存中有数据,就会将它们写入相应的文件,这样就防止了文件数据的丢失,然后终止进程。
_exit():在执行该函数时,并不清理标准输入输出缓存,而是直接清除内存空间,当然也就把文件缓存中尚未写入文件的数据给销毁了。由此可见,使用exit()函数更加安全。
此外,对于它们两者的区别还有各自的头文件不同。exit()在stdlib.h中,_exit()在unistd.h中。一般情况下exit(0)表示正常退出,exit(1),exit(-1)为异常退出,0、1、-1是返回值,具体含义可以自定。还要注意return是返回函数调用,如果返回的是main函数,则为退出程序 。exit是在调用处强行退出程序,运行一次程序就结束。
下面是完整的Linux进程运行流程:
- arch/x86/include/asm/unistd_32.h:fork() 用户空间来调用(如C程序)
- --->int $0×80 产生0x80软中断
- --->arch/x86/kernel/entry_32.S:ENTRY(system_call) 中断处理程序system_call()
- --->执行SAVE_ALL宏 保存所有CPU寄存器值
- --->arch/x86/kernel/syscall_table_32.S:ENTRY(sys_call_table) 系统调用多路分解表
- --->arch/x86/kernel/process_32.c:sys_fork()
- --->kernel/fork.c:do_fork() 复制原来的进程成为另一个新的进程
- --->kernel/fork.c:copy_process()
- --->struct task_struct *p; 定义新的进程描述符(PCB)
- --->clone_flags标志的合法性检查
- --->security_task_create() 安全性检查(SELinux机制)
- --->kernel/fork.c:dup_task_struct() 复制进程描述符
- --->struct thread_info *ti; 定义线程信息结构
- --->alloc_task_struct() 为新的PCB分配内存
- --->kernel/fork.c:arch_dup_task_struct() 复制父进程的PCB
- --->atomic_set(&tsk->usage,2) 将PCB使用计数器设置为2,表示活动状态
- --->copy_creds() 复制权限及身份信息
- --->检测进程总数是否超过max_threads
- --->初始化PCB中各个字段
- --->sched_fork() 调度器相关设置
- --->复制进程所有信息copy_semundo(), copy_files(),
- --->copy_signal(), copy_mm()
- --->copy_thread() 复制线程
- --->alloc_pid() 分配pid
- --->更新属性和进程数量计数
- --->kernel/sched.c:wake_up_new_task() 把进程放到运行队列上,让调度器进行调度
- --->kernel/sched.c:select_task_rq() 选择最佳的CPU(SMP中有多个CPU)
- --->p->state = TASK_RUNNING 设置成TASK_RUNNING状态
- --->activate_task()
- --->enqueue_task() 把当前进程插入到对应CPU的runqueue上
- --->有CLONE_VFORK标志:wait_for_completion() 让父进程阻塞,等待子进程结束
- --->返回分配的pid
- kernel/sched.c:schedule() 调度新创建的进程
- 进程运行中
- exit() 用户空间来调用(如C程序)
- --->0x80中断跳转到include/linux/syscalls.h:sys_exit()
- --->kernel/exit.c:do_exit() 负责进程的退出
- --->struct task_struct *tsk = current; 获取我的PCB
- --->set_fs(USER_DS) 设置使用的文件系统模式
- --->exit_signals() 清除信号处理函数并设置PF_EXITING标志
- --->清除进程一系列资源exit_mm(), exit_files()
- --->exit_fs(), exit_thread()
- --->kernel/exit.c:exit_notify() 退出通知
- --->forget_original_parent() 把我的所有子进程过继给init进程
- --->kill_orphaned_pgrp() 向进程组内各进程发送挂起信号SIGHUP及SIGCONT
- --->tsk->exit_signal = SIGCHLD; 向我的父进程发送SIGCHLD信号
- --->kernel/exit.c:do_notify_parent() 通知父进程
- --->如果父进程处理SIGCHLD信号,返回DEATH_REAP
- --->如果父进程不处理SIGCHLD信号,返回传入时的信号值
- --->__wake_up_parent() 唤醒父进程
- --->通知返回DEATH_REAP,设置exit_state为EXIT_DEAD 我退出并且死亡
- --->否则设置我为EXIT_ZOMBIE 我退出但没死亡,成为僵尸进程
- --->如果为DEATH_REAP:release_task() 我自己清理相关资源
- --->如果为僵尸,在我的父进程退出时我会过继给init进程,由init负责清理
- --->exit_io_context() 清理IO上下文
- --->preempt_disable() 禁用抢占
- --->tsk->state = TASK_DEAD; 设置我为进程死亡状态
- --->kernel/sched.c:schedule() 释放我的PCB,调度另一个新的进程
- 清理僵尸进程:wait系统调用 等待子进程结束
- --->0x80中断最后到达kernel/exit.c:do_wait()
- --->do_wait_thread()
- --->wait_consider_task()
- --->如果子进程为EXIT_DEAD,返回0,wait调用返回,子进程自己清理自己
- --->如果子进程为EXIT_ZOMBIE:wait_task_zombie()
- --->xchg() 设置僵尸子进程为EXIT_DEAD
- --->release_task() 清理僵尸子进程
下面是基本的执行流程图:

图1 Linux进程管理的执行流程
Linux进程管理(3):总结的更多相关文章
- Linux进程管理子系统分析【转】
本文转载自:http://blog.csdn.net/coding__madman/article/details/51298732 Linux进程管理: 进程与程序: 程序:存放在磁盘上的一系列代码 ...
- 12个Linux进程管理命令介绍(转)
12个Linux进程管理命令介绍 [日期:2015-06-02] 来源:Linux中国 作者:Linux [字体:大 中 小] 执行中的程序在称作进程.当程序以可执行文件存放在存储中,并且运行的 ...
- Linux进程管理知识整理
Linux进程管理知识整理 1.进程有哪些状态?什么是进程的可中断等待状态?进程退出后为什么要等待调度器删除其task_struct结构?进程的退出状态有哪些? TASK_RUNNING(可运行状态) ...
- Linux性能及调优指南(翻译)之Linux进程管理
本文为IBM RedBook的Linux Performanceand Tuning Guidelines的1.1节的翻译原文地址:http://www.redbooks.ibm.com/redpap ...
- Linux进程管理专题
Linux进程管理 (1)进程的诞生介绍了如何表示进程?进程的生命周期.进程的创建等等? Linux支持多种调度器(deadline/realtime/cfs/idle),其中CFS调度器最常见.Li ...
- [转帖]十二 个经典 Linux 进程管理命令介绍
https://www.cnblogs.com/swordxia/p/4550825.html 接了 http referer 头 没法显示图片 可以去原始blog 里面去查看. 随笔- 109 ...
- Linux进程管理 (1)进程的诞生
专题:Linux进程管理专题 目录: Linux进程管理 (1)进程的诞生 Linux进程管理 (2)CFS调度器 Linux进程管理 (3)SMP负载均衡 Linux进程管理 (4)HMP调度器 L ...
- Linux进程管理 (2)CFS调度器
关键词: 目录: Linux进程管理 (1)进程的诞生 Linux进程管理 (2)CFS调度器 Linux进程管理 (3)SMP负载均衡 Linux进程管理 (4)HMP调度器 Linux进程管理 ( ...
- Linux进程管理 (7)实时调度
关键词:RT.preempt_count.RT patch. 除了CFS调度器之外,还包括重要的实时调度器,有两种RR和FIFO调度策略.本章只是一个简单的介绍. 更详细的介绍参考<Linux进 ...
- Linux进程管理工具
Linux进程管理工具 Htop yum install htop 参考帮助: http://blog.csdn.net/skh2015java/article/details/53173896 Li ...
随机推荐
- 《Scrum实战》第3次课【富有成效的每日站会】作业汇总
1组 崔儒: http://kecyru.blog.163.com/blog/static/2741661732017626101944123/ 2017-07-26 孟帅: http://www.c ...
- Markdown,后缀MD
Markdown 算是一门新兴语言,现在 7-8 岁了吧.它设计的初衷就是让写字的人专注于写字,用纯文本简单的符号标记格式,最后再通过工具转换成鬼畜的 HTML/XHTML.如果你玩过 wikiped ...
- python - work - 2
#-*- coding:utf-8 -*-# author:jiaxy# datetime:2018/11/3 11:48# software: PyCharm Community Edition d ...
- day04_02 知识回顾、赋值运算符
input命令输出的是字符串 数字转换成字符串 字符串转换成数字 以上成为类型的强制转换 运算符
- 【转】Building a RESTful Web Service
目标 构建一个service,接收如下HTTP GET请求: [plain] view plain copy http://localhost:8080/greeting 并返回如下JSON格式的 ...
- 关于iOS 7的几个开源项目
MBSwitch MBSwitch是一个体现了iOS 7扁平化设计风格的UISwitch,支持iOS 7以下系统.允许使用者进行颜色的深度自定义,你可以定义边框的颜色,开/关的颜色以及按钮的颜色. ...
- ACM程序设计选修课——1018: Common Subsequence(DP)
问题 L: Common Subsequence 时间限制: 1 Sec 内存限制: 32 MB 提交: 70 解决: 40 [提交][状态][讨论版] 题目描述 A subsequence of ...
- [NOIP2009] 最优贸易 (最短路,分层图)
题目链接 Solution 分层图+\(SPFA\). 建立3层图,其中每一层之中的边权赋为0. 对于任意一条边 \(t\) ,其起点 \(x\) 和终点 \(y\). 我们将 \(x\) 在第一层的 ...
- 表单编码 appliation/x-www-form-urlencoded 与 multipart/form-data 的区别
当表单使用POST方法时,表单数据提交到服务器端之前有两种编码类型可供选择.默认编码类型为 application/x-www-form-urlencoded,此时所有非字母数字类型的字符都需要转换为 ...
- 机器人操作系统ROS Indigo 入门学习(1)——安装ROS Indigo【转】
转自:http://blog.csdn.net/bobsweetie/article/details/43638761 Ubuntu14.04安装ROS Indigo 一.安装ROS 1.1配置Ubu ...