Chinaunix首页 | 论坛 | 博客
  • 博客访问: 993169
  • 博文数量: 200
  • 博客积分: 5011
  • 博客等级: 大校
  • 技术积分: 2479
  • 用 户 组: 普通用户
  • 注册时间: 2008-06-27 15:07
文章分类

全部博文(200)

文章存档

2009年(12)

2008年(190)

我的朋友

分类:

2008-11-18 15:40:32

7.2 main function

一个c程序启动后,首先执行的是一个startup routne,它会将命令行参数,环境变量等准备好,以备main的执行。这个startup routine可以看作:

Exit(main(argc, argv))及当main返回后,就调用exit.

7.3 process termination

本章节融合了8.5 exit function的内容

一个程序退出的几种情况;

(一)正常退出的情况

1. main 调用return

2. 调用exit函数

3. 调用_exit或者_Exit函数

4. Return of the last thread from its start routine

5Calling pthread_exit () from the last thread

(二)非正常退出的情况

1Abort调用,其实会发出SIGABRT信号

2.收到signal

3Response of the last thread to a cancellation request ( and )

 

三个exit函数的区别:

#include 
void exit(int status);
void _Exit(int status);
 
#include 
void _exit(int status);
1.exit()_Exit()ISO C的函数,而_exitPOSIX.1的接口。
2.exit()会对standard library进行cleanup工作,比如关闭所有打开的streams(但是实际上,这个工作貌似并不去做,而仅仅是将stream 进行了flush,而并不关闭)。_Exit_exit就直接返回到kernel,不会进行cleanup工作(但是实际上究竟是否flush 标准库的streamimplementation dependent)。
3.其实exit()最终是要通过调用_exit或者_Exit来返回到kernel的。
4. 不管是正常还是不正常退出,kernel都会将打开的descriptors关闭。所以exit()不去关闭stream也是可以的。

返回值:

这几个函数都带有参数,如果如下情况发生:

他们不带任何参数

Main函数return语句没有带参数

Main函数被声明为非int返回值

那么程序的返回值就是undefined

 

支持C99的编译器会对这些进行警告。

 

#include

 

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

 

Returns: 0 if OK, nonzero on error

Atexit函数用来指定在程序退出的时候执行的工作,前提是我们必须调用exit()函数,一般最多注册32个函数,而且允许重复,重复的注册会重复的调用,而且是逆序的调用。这个最大数值应该可以通过sysconf来获得。

Exit()函数在调用这些exit handler函数之后,在进行standard library 的清除工作,然后会调用_exit或者_Exit返回到kernel

本章节的figure 7.2是一个很好的说明C程序的执行图。

Figure 7.2. How a C program is started and how it terminates

[View full size image]

 

不管函数是normal 还是abnormal的结束,总有个exit status(normal)或者termination status(abnormal),而kernel会将exit status也弄成一个termination status。那么父进程要想获得子进程的termination status就得调用wait()或者waitpid()函数。而实际上,wait()waitpid不仅是用来等待子进程结束的,还可以用来等待他的state change,即它的状态变化,比如被stopped了,比如有被continued了,等。这就需要提供参数给wait或者waitpid告诉她要等什么。等wait函数返回后(可能会block),对返回的status使用一些宏来检查,就可以知道发生了什么样的状态变化:

Figure 8.4. Macros to examine the termination status returned by wait and waitpid

Macro

Description

WIFEXITED(status)

True if status was returned for a child that terminated normally. In this case, we can execute

WEXITSTATUS (status)

to fetch the low-order 8 bits of the argument that the child passed to exit, _exit,or _Exit.

WIFSIGNALED (status)

True if status was returned for a child that terminated abnormally, by receipt of a signal that it didn't catch. In this case, we can execute

WTERMSIG (status)

to fetch the signal number that caused the termination.

Additionally, some implementations (but not the Single UNIX Specification) define the macro

WCOREDUMP (status)

that returns true if a core file of the terminated process was generated.

WIFSTOPPED (status)

True if status was returned for a child that is currently stopped. In this case, we can execute

WSTOPSIG (status)

to fetch the signal number that caused the child to stop.

WIFCONTINUED (status)

True if status was returned for a child that has been continued after a job control stop (XSI extension to POSIX.1; waitpid only).

 

进程结束了会怎样:

1.如果父进程调用了wait系列函数,那么父进程会为子进程收尸,收什么尸?释放子进程占用的memory,关闭子进程打开的descriptors,取得子进程的termination status。等等。

2.如果父进程没有等待子进程呢?那么在子进程结束之后,父进程结束之前,结束的子进程就成了僵尸进程,用PS查看时,其状态为Z。如果接着,父进程自己也结束了,那么那个僵尸子进程会一直是僵尸么?否,init会接管他的,前提是他们都是init的子孙。如果不是呢?可能么?除非你修改内核吧。

经测试,的确是这样的:

Int main()

{

    If( fork() == 0 )

{

    //child

    Exit(0);

}

Else

{

    //parent

    Sleep(10);

}

}

子进程立马结束了,父进程开始睡眠,此时我们ps以下,就会看到有两个a.out进程,一个是僵尸,一个是在Sleep10秒钟后,他们都消失了,因为父进程消失了,应该是被shell处理了(a.out父进程是shell forck出来的嘛),子进程就给init处理了。

阅读(421) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~