lienhua34
2014-10-02

1 进程的终止方式

进程的终止方式有 8 种,其中 5 种为正常终止,它们是

1. 从 main 返回。

2. 调用 exit。

3. 调用_exit 或_Exit。

4. 最后一个线程从其启动例程返回。

5. 最后一个线程调用pthread_exit。

另外三种为异常终止方式,它们是

1. 调用 abort。

2. 接到一个信号并终止。

3. 最后一个线程对取消请求做出响应。

2 exit 函数

有三个函数用于正常终止一个程序:_exit 和_Exit 立即进入内核,exit 则先执行一些清理处理(包括调用执行各终止处理程序,关闭所有标准 I/O 流等),然后进入内核。

#include <stdlib.h>

void exit(int status);

void _Exit(int status);

#include <unistd.h>

void _exit(int status);

三个 exit 函数都带一个整型参数,称之为终止状态(或退出状态,exit status)。main 函数返回一个整型值与用该值调用 exit 是等价的,即 exit(0)等价于 return(0)。

如果(a)main 执行了一个无返回值的 return 语句,或(b)main 没有声明返回类型为整型,则该进程的终止状态是未定义的。若 main 函数的返回类型是整型,并且 main 执行到最后一条语句时隐形返回(没有显示使用 return 或者调用 exit 函数),历史版本的终止状态是未定义的,而 ISOc 标准 1999 规定该进程的终止状态为 0.

3 终止处理程序

前面一节讲到调用 exit 函数,在进入内核之前,进程会调用一些终止处理程序(exit handler)。我们可以通过调用 atexit 函数注册终止处理程序。按照 ISO C 的规定,一个进程可以注册多达 32 个终止处理函数。

#include <stdlib.h>

int atexit(void (*func)(void));

返回值:若成功则返回0,若出错则返回非0值。

atexit 的参数是一个函数地址,注册的函数没有参数也没有返回值。exit 调用这些函数的顺序与它们注册时候的顺序相反。同一个函数如果被注册多次,则也会被调用多次。

例子:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
static void my_exit1(void);
static void my_exit2(void);
int
main(void)
{
if (atexit(my_exit2) != ) {
printf("can't register my_exit2: %s\n", strerror(errno));
}
if (atexit(my_exit1) != ) {
printf("can't register my_exit1: %s\n", strerror(errno));
}
if (atexit(my_exit1) != ) {
printf("can't register my_exit1: %s\n", strerror(errno));
}
printf("main is done\n");
exit();
}
static void
my_exit1(void)
{
printf("first exit handler\n");
}
static void
my_exit2(void)
{
printf("second exit handler\n");
}

编译该程序,生成 atexitdemo 文件,然后执行该文件,

lienhua34:demo$ gcc -o atexitdemo atexitdemo.c
lienhua34:demo$ ./atexitdemo
main is done
first exit handler
first exit handler
second exit handler

(done)

UNIX环境编程学习笔记(15)——进程管理之进程终止的更多相关文章

  1. UNIX环境编程学习笔记(21)——进程管理之获取进程终止状态的 wait 和 waitpid 函数

    lienhua342014-10-12 当一个进程正常或者异常终止时,内核就向其父进程发送 SIGCHLD信号.父进程可以选择忽略该信号,或者提供一个该信号发生时即被调用的函数(信号处理程序).对于这 ...

  2. UNIX环境编程学习笔记(19)——进程管理之fork 函数的深入学习

    lienhua342014-10-07 在“进程控制三部曲”中,我们学习到了 fork 是三部曲的第一部,用于创建一个新进程.但是关于 fork 的更深入的一些的东西我们还没有涉及到,例如,fork ...

  3. UNIX环境编程学习笔记(18)——进程管理之进程控制三部曲

    lienhua342014-10-05 1 进程控制三部曲概述 UNIX 系统提供了 fork.exec.exit 和 wait 等基本的进程控制原语.通过这些进程控制原语,我们即可完成对进程创建.执 ...

  4. UNIX环境编程学习笔记(17)——进程管理之进程的几个基本概念

    lienhua342014-10-05 1 main 函数是如何被调用的? 在编译 C 程序时,C 编译器调用链接器在生成的目标可执行程序文件中,设置一个特殊的启动例程为程序的起始地址.当内核执行 C ...

  5. UNIX环境编程学习笔记(24)——信号处理进阶学习之信号集和进程信号屏蔽字

    lienhua342014-11-03 1 信号传递过程 信号源为目标进程产生了一个信号,然后由内核来决定是否要将该信号传递给目标进程.从信号产生到传递给目标进程的流程图如图 1 所示, 图 1: 信 ...

  6. UNIX环境编程学习笔记(26)——多线程编程(一):创建和终止线程

    lienhua342014-11-08 在进程控制三部曲中我们学习了进程的创建.终止以及获取终止状态等的进程控制原语.线程的控制与进程的控制有相似之处,在表 1中我们列出了进程和线程相对应的控制原语. ...

  7. UNIX环境编程学习笔记(23)——信号处理初步学习

    lienhua342014-10-29 1 信号的概念 维基百科中关于信号的描述是这样的: 在计算机科学中,信号(英语:Signals)是 Unix.类 Unix 以及其他 POSIX 兼容的操作系统 ...

  8. UNIX环境编程学习笔记(9)——文件I/O之文件访问权限的屏蔽和更改

    lienhua342014-09-10 1 文件访问权限 在文件访问权限和进程访问控制中,我们已经讲述过文件访问权限位,为了方便,我们重新列在下面, 表 1: 文件的 9 个访问权限位  st_mod ...

  9. UNIX环境编程学习笔记(3)——文件I/O之内核 I/O 数据结构

    lienhua342014-08-27 内核使用三种数据结构表示打开的文件,分别是文件描述符表.文件表和 V 节点表. (1) 每个进程在进程表中都有一个记录项,记录项中包含有一张打开文件描述符表,每 ...

随机推荐

  1. 4. 支持向量机(SVM)原理

    1. 感知机原理(Perceptron) 2. 感知机(Perceptron)基本形式和对偶形式实现 3. 支持向量机(SVM)拉格朗日对偶性(KKT) 4. 支持向量机(SVM)原理 5. 支持向量 ...

  2. div模态显示内容

    业务需要,上传的图片,本地显示大图: 模态代码: <div onclick="hidebigimg()" class = "bg-model" style ...

  3. spring security 注解@EnableGlobalMethodSecurity详解

     1.Spring Security默认是禁用注解的,要想开启注解,需要在继承WebSecurityConfigurerAdapter的类上加@EnableGlobalMethodSecurity注解 ...

  4. 【WPF/C#】图层筛选/拾取——Color Picker

    文章标题实在不懂怎么表述才清楚. 描述问题:多个图片(图层)重叠时,如何通过鼠标点击来拾取到相应的图层.因为图层中会有很多空白的地方(比如图片四周),要求是获取鼠标点击位置的像素颜色值,如果为空白时或 ...

  5. bluetooth在linux应用开发

    linux内Bluetooth的协议栈为BlueZ,http://www.bluez.org/.在4.46上,BlueZ实现了对A2DP Sink的支持,而之前的版本只支持A2DP Source.

  6. Spark硬件配置推荐

    1.存储系统 如果可以的话,把Spark的hadoop的节点安装在一起,最容易的方式是用standalone的模式安装,用mapred.child.java.opts设置每个任务的内存,用mapred ...

  7. SQL Server创建远程链接服务器

    --使用sp_addlinkedserver增加链接 EXEC sys.sp_addlinkedserver @server='127.0.0.1', --被访问的服务器别名(习惯上直接使用目标服务器 ...

  8. Coneroller执行时候的-26374及-26377错误

    有时候一些不必要的关联也会引起这个问题, 1.首先看下脚本中有没有使用了自动关联(web_reg_save_param) 2.在Virtual的脚本里查询下web_reg_save_param的参数使 ...

  9. $(window).height() 和 $(document).height()的区别

    $(window).height() 和 $(document).height()的区别 $(window).height()代表了当前可见区域的大小,$(document).height()则代表了 ...

  10. String、StringBuffer与StringBuilder 复习回顾总结

    1.三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String 2.String <(StringBuffer,StringBuild ...