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进程运行流程:

  1. arch/x86/include/asm/unistd_32.h:fork()        用户空间来调用(如C程序)
  2. --->int $0×80        产生0x80软中断
  3. --->arch/x86/kernel/entry_32.S:ENTRY(system_call)  中断处理程序system_call()
  4. --->执行SAVE_ALL宏      保存所有CPU寄存器值
  5. --->arch/x86/kernel/syscall_table_32.S:ENTRY(sys_call_table) 系统调用多路分解表
  6. --->arch/x86/kernel/process_32.c:sys_fork()
  7. --->kernel/fork.c:do_fork()  复制原来的进程成为另一个新的进程
  8. --->kernel/fork.c:copy_process()
  9. --->struct task_struct *p;  定义新的进程描述符(PCB)
  10. --->clone_flags标志的合法性检查
  11. --->security_task_create()    安全性检查(SELinux机制)
  12. --->kernel/fork.c:dup_task_struct()   复制进程描述符
  13. --->struct thread_info *ti;  定义线程信息结构
  14. --->alloc_task_struct()      为新的PCB分配内存
  15. --->kernel/fork.c:arch_dup_task_struct()  复制父进程的PCB
  16. --->atomic_set(&tsk->usage,2)    将PCB使用计数器设置为2,表示活动状态
  17. --->copy_creds()   复制权限及身份信息
  18. --->检测进程总数是否超过max_threads
  19. --->初始化PCB中各个字段
  20. --->sched_fork()    调度器相关设置
  21. --->复制进程所有信息copy_semundo(), copy_files(),
  22. --->copy_signal(), copy_mm()
  23. --->copy_thread()    复制线程
  24. --->alloc_pid()    分配pid
  25. --->更新属性和进程数量计数
  26. --->kernel/sched.c:wake_up_new_task()  把进程放到运行队列上,让调度器进行调度
  27. --->kernel/sched.c:select_task_rq()  选择最佳的CPU(SMP中有多个CPU)
  28. --->p->state = TASK_RUNNING    设置成TASK_RUNNING状态
  29. --->activate_task()
  30. --->enqueue_task()  把当前进程插入到对应CPU的runqueue上
  31. --->有CLONE_VFORK标志:wait_for_completion()  让父进程阻塞,等待子进程结束
  32. --->返回分配的pid
  33. kernel/sched.c:schedule()    调度新创建的进程
  34. 进程运行中
  35. exit()        用户空间来调用(如C程序)
  36. --->0x80中断跳转到include/linux/syscalls.h:sys_exit()
  37. --->kernel/exit.c:do_exit()    负责进程的退出
  38. --->struct task_struct *tsk = current;    获取我的PCB
  39. --->set_fs(USER_DS)    设置使用的文件系统模式
  40. --->exit_signals()     清除信号处理函数并设置PF_EXITING标志
  41. --->清除进程一系列资源exit_mm(), exit_files()
  42. --->exit_fs(), exit_thread()
  43. --->kernel/exit.c:exit_notify()  退出通知
  44. --->forget_original_parent()  把我的所有子进程过继给init进程
  45. --->kill_orphaned_pgrp()      向进程组内各进程发送挂起信号SIGHUP及SIGCONT
  46. --->tsk->exit_signal = SIGCHLD;  向我的父进程发送SIGCHLD信号
  47. --->kernel/exit.c:do_notify_parent()  通知父进程
  48. --->如果父进程处理SIGCHLD信号,返回DEATH_REAP
  49. --->如果父进程不处理SIGCHLD信号,返回传入时的信号值
  50. --->__wake_up_parent()    唤醒父进程
  51. --->通知返回DEATH_REAP,设置exit_state为EXIT_DEAD    我退出并且死亡
  52. --->否则设置我为EXIT_ZOMBIE      我退出但没死亡,成为僵尸进程
  53. --->如果为DEATH_REAP:release_task()    我自己清理相关资源
  54. --->如果为僵尸,在我的父进程退出时我会过继给init进程,由init负责清理
  55. --->exit_io_context()    清理IO上下文
  56. --->preempt_disable()    禁用抢占
  57. --->tsk->state = TASK_DEAD;    设置我为进程死亡状态
  58. --->kernel/sched.c:schedule()  释放我的PCB,调度另一个新的进程
  59. 清理僵尸进程:wait系统调用         等待子进程结束
  60. --->0x80中断最后到达kernel/exit.c:do_wait()
  61. --->do_wait_thread()
  62. --->wait_consider_task()
  63. --->如果子进程为EXIT_DEAD,返回0,wait调用返回,子进程自己清理自己
  64. --->如果子进程为EXIT_ZOMBIE:wait_task_zombie()
  65. --->xchg()    设置僵尸子进程为EXIT_DEAD
  66. --->release_task()    清理僵尸子进程

下面是基本的执行流程图:


图1 Linux进程管理的执行流程

Linux进程管理(3):总结的更多相关文章

  1. Linux进程管理子系统分析【转】

    本文转载自:http://blog.csdn.net/coding__madman/article/details/51298732 Linux进程管理: 进程与程序: 程序:存放在磁盘上的一系列代码 ...

  2. 12个Linux进程管理命令介绍(转)

    12个Linux进程管理命令介绍 [日期:2015-06-02] 来源:Linux中国  作者:Linux [字体:大 中 小]   执行中的程序在称作进程.当程序以可执行文件存放在存储中,并且运行的 ...

  3. Linux进程管理知识整理

    Linux进程管理知识整理 1.进程有哪些状态?什么是进程的可中断等待状态?进程退出后为什么要等待调度器删除其task_struct结构?进程的退出状态有哪些? TASK_RUNNING(可运行状态) ...

  4. Linux性能及调优指南(翻译)之Linux进程管理

    本文为IBM RedBook的Linux Performanceand Tuning Guidelines的1.1节的翻译原文地址:http://www.redbooks.ibm.com/redpap ...

  5. Linux进程管理专题

    Linux进程管理 (1)进程的诞生介绍了如何表示进程?进程的生命周期.进程的创建等等? Linux支持多种调度器(deadline/realtime/cfs/idle),其中CFS调度器最常见.Li ...

  6. [转帖]十二 个经典 Linux 进程管理命令介绍

    https://www.cnblogs.com/swordxia/p/4550825.html 接了 http referer 头 没法显示图片 可以去原始blog 里面去查看.   随笔- 109  ...

  7. Linux进程管理 (1)进程的诞生

    专题:Linux进程管理专题 目录: Linux进程管理 (1)进程的诞生 Linux进程管理 (2)CFS调度器 Linux进程管理 (3)SMP负载均衡 Linux进程管理 (4)HMP调度器 L ...

  8. Linux进程管理 (2)CFS调度器

    关键词: 目录: Linux进程管理 (1)进程的诞生 Linux进程管理 (2)CFS调度器 Linux进程管理 (3)SMP负载均衡 Linux进程管理 (4)HMP调度器 Linux进程管理 ( ...

  9. Linux进程管理 (7)实时调度

    关键词:RT.preempt_count.RT patch. 除了CFS调度器之外,还包括重要的实时调度器,有两种RR和FIFO调度策略.本章只是一个简单的介绍. 更详细的介绍参考<Linux进 ...

  10. Linux进程管理工具

    Linux进程管理工具 Htop yum install htop 参考帮助: http://blog.csdn.net/skh2015java/article/details/53173896 Li ...

随机推荐

  1. HDU 1827 强连通 缩点 Summer Holiday

    求出强连通分量,因为强连通中只要有一个人被通知到了,所有人都能被通知到. 缩点以后形成一个DAG,找出那些入度为0的点,累加上它们的权值就是答案.一个点的权值等于SCC中权值最小的那个点. #incl ...

  2. 02_ThreadLocal语法与源码分析

    文章导读: 早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程 ...

  3. PHP函数参数传递(相对于C++的值传递和引用传递)

    学语言学得比较多了,今天突然想PHP函数传递,对于简单类型(基本变量类型)和复杂类型(类)在函数参数传递时,有没有区别呢,今天测试了下: 代码如下: <?php function test($a ...

  4. 常见python快捷键

    http://www.cnblogs.com/toutou/p/4778818.html Ctrl+/注释(取消注释)选择的行 Shift + Enter开始新行 Ctrl + Enter智能换行 T ...

  5. linux快速查看同局域网的其他在线主机

    安装一个nmap工具,直接 nmap -sP 192.168.1.1/24 即可

  6. 刷题总结——Tree2cycle(hdu4714 树形dp)

    题目: A tree with N nodes and N-1 edges is given. To connect or disconnect one edge, we need 1 unit of ...

  7. [NOIP2009] $Hankson$ 的趣味题 (数论,gcd)

    题目链接 Solution 此题,用到的结论都是比较浅显的,但是,我竟然没想到反过来枚举... 只有50分... 被自己蠢哭... 结论比较浅显: 1.对于两个正整数\(a\),\(b\),设 \(g ...

  8. UVa1073 Glenbow Museum

    可以把R看成顺时针转90°,O看成逆时针转270° 设R有x个,则180*(n-2)=90*x+270*(n-x) 解得R有(n+4)/2个 O有(n-4)/2个 所以n<4或者n是奇数时无解. ...

  9. canvas之webgl的浏览器开启方式

    引自百度知道的回答 1.开启方式: 第一种:打开cmd,切换到Chorme的安装目录,敲入chrome.exe --enable -webgl,回车就会打开一个chrome浏览器窗口: 第二种:找到C ...

  10. 【MFC】半透明对话框(转)

    原文转自 http://jingyan.baidu.com/article/656db918fd5b0ee381249ca1.html 在OnInitDialog()函数添加以下代码: //设置半透明 ...