Linux环境编程--linux中的perror、exit、_exit、wait 和 waitpid

  perror:
  #include<stdio.h>   
       #include<stdlib.h>

定义函数

  void perror(const char *s);  perror ("open_port");

函数说明

  perror ( )用 来 将 上 一 个 函 数 发 生 错 误 的 原 因 输 出 到 标 准 错误 (stderr) 。参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。此错误原因依照全局变量error 的值来决定要输出的字符串。   
       在库函数中有个error变量,每个error值对应着以字符串表示的错误类型。当你调用"某些"函数出错时,该函数已经重新设置了error的值。perror函数只是将你输入的一些信息和现在的error所对应的错误一起输出。

exit:(#include <stdlib.h>)
    在C语言的main函数中我们通常使用return (0);这样的方式返回一个值。但这是限定在非void情况下的,也就是非void main()这样的形式。       exit()通常是用在子程序中用来终结程序用的,使用后程序自动结束,跳出操作系统。   
    exit(0) 表示程序正常退出,
    exit(1)/exit(-1)表示程序异常退出。
 exit() 结束当前进程/当前程序/,在整个程序中,只要调用 exit ,就结束。
 但在如果把exit用在main内的时候无论main是否定义成void返回的值都是有效的,并且exit不需要考虑类型,exit(1)等价于return (1) 。   
例如:   
#include<stdlib.h>   
int main()   
{
   exit (1);//等价于return (1);   
}
  exit()是一个函数 ,结束一个进程,它将删除进程使用的内存空间,同时把错误信息返回父进程,在父进程中wait系统调用将接受到此返回信息。



进程就好比人一样有其生命,我们通过fork()函数来创建一个进程,那么我们又是如何来中止进程呢。

进程退出

1.在Linux中任何让一个进程退出

进程退出表示进程即将结束。在Linux中进程退出分为了正常退出和异常退出两种。

1>正常退出

a. 在main()函数中执行return 。

 

b.调用exit()函数   #include <stdlib.h>    void exit(int status)

c.调用_exit()函数   #include <unistd.h>   void _exit(int status)

status 是一个整型的参数,可以利用这个参数传递进程结束时的状态。一般来说,
0 表示正常结束;其他的数值表示出现了错误,进程非正常结束。
在实际编程时,可以用 wait 系统调用接收子进程的返回值,从而针对不同的情况
进行不同的处理

2>异常退出

a.调用about函数

b.进程收到某个信号,而该信号使程序终止。


Tiger-John说明:
不管 是那种 退出方式,系统最终都会执行内核中的同一代码。这段代码用来关闭进程所用已打开的文件描述符,释放它所占用的内存和其他资源。

 

 

3>比较以上几种退出方式的不同点

(1)exit和return 的区别:

a.exit是一个函数,有参数。exit执行完后把控制权交给系统

b.return是函数执行完后的返回。renturn执行完后把控制权交给调用函数

(2)exit和abort的区别:

a.exit是正常终止进程

b.about是异常终止。

 

 

现在我们重点了解exit()和_exit()函数

 

2.exit()和_exit()的学习

1>exit和_exit函数都是用来终止进程的。

当程序执行到exit或_exit时,系统无条件的停止剩下所有操作,清除包括PCB在内的各种数据结构,并终止本进程的运行。

2>exit在头文件stdlib.h中声明,而_exit()声明在头文件unistd.h中声明。 exit中的参数exit_code为0代表进程正常终止,若为其他值表示程序执行过程中有错误发生。

3>exit()和_exit()的区别:


a._exit()执行后立即返回给内核,而exit()要先执行一些清除操作,然后将控制权交给内核。

b. 调用_exit函数时,其会关闭进程所有的文件描述符,清理内存以及其他一些内核清理函数,但不会刷新流(stdin, stdout, stderr  ...).   exit函数是在_exit函数之上的一个封装,其会调用_exit,并在调用之前先刷新流。

Tiger-John说明:

exit()函数与_exit()函数最大区别就在于exit()函数在调用exit系统之前要检查文件的打开情况,把文件缓冲区的内容写回文件。 由于Linux的标准函数库中,有一种被称作“缓冲I/O”的操作,其特征就是对应每一个打开的文件,在内存中都有一片缓冲区。每次读文件时,会连续的读 出若干条记录,这样在下次读文件时就可以直接从内存的缓冲区读取;同样,每次写文件的时候也仅仅是写入内存的缓冲区,等满足了一定的条件(如达到了一定数 量或遇到特定字符等),再将缓冲区中的内容一次性写入文件。这种技术大大增加了文件读写的速度,但也给编程代来了一点儿麻烦。比如有一些数据,认为已经写 入了文件,实际上因为没有满足特定的条件,它们还只是保存在缓冲区内,这时用_exit()函数直接将进程关闭,缓冲区的数据就会丢失。因此,要想保证数 据的完整性,就一定要使用exit()函数。

c . 通过一个函数实例来看看它们之间的区别:

函数实例1 : exit.c

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3
 4 int main()
 5 {
 6         printf("using exit----\n");
 7         printf("This is the content in buffer\n");
 8         exit(0);
9 }

函数经过调试后

$ gcc exit.c -o exit
$ ./exit


执行结果为:

using exit----
This is the content in buffer

函数实例2:_exit.c

 1 #include<stdio.h>
 2 #include<unistd.h>
 3
 4 int main(void)
 5 {
 6         printf("using _exit--\n");
 7         printf("This is the content in buffer");
 8         _exit(0);
 9 }
  函数经过调试后

$ gcc _exit.c -o _exit
$ ./_exit


执行结果为 :

using _exit--


Tiger-John说明:

1.printf函数就是使用缓冲I/O的方式,该函数在遇到“\n”换行符时自动的从缓冲区中将记录读出。所以exit()将缓冲区的数据写完后才退出,而_exit()函数直接退出。

2.大家也可以把函数实例2中的printf("This is the content in buffer");改为printf("This is the content in buffer\n")(即在printf中最后加一个\n看运行结果是什么,为什么会产生这样的结果呢?)

小知识

在一个进程调用了 exit 之后,该进程并不马上就完全消失,而是留下一个称为 僵尸进程
(Zombie)的数据结构。僵尸进程是一种非常特殊的进程,它几乎已经放弃了所有内存空间,
没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出
状态等信息供其他进程收集,除此之外,僵尸进程不再占有任何内存空间。
wait
      wait 函数是用于使父进程(也就是调用 wait 的进程) 阻塞,直到一个子进程结束或者该进程接到了一个指定的信号为止。
如果该父进程没有子进程或者他的子进程已经结束, wait则就会立即返回。
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status)


waitpid
      waitpid 的作用和 wait 一样,但它并不一定要等待第一个终止的子进程,它还有若干选项,如可提供一个非阻塞版本的 wait 功能,也能支持作业控制。实际上 wait 函数只是 waitpid 函数的一个特例,在 Linux 内部实现 wait 函数时直接调用的就是 waitpid 函数。
#include <sys/types.h>
#include <sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options)

你可能感兴趣的:(Linux环境编程--linux中的perror、exit、_exit、wait 和 waitpid)