首页 > 编程知识 正文

c语言exit函数的头文件是,strpos() 函数的作用是什么

时间:2023-05-06 00:23:40 阅读:118186 作者:554

注: exit ) )结束。 传入的参数是程序结束时的状态代码,0表示正常结束,其他表示异常结束。 通常使用-1或1。 标准c有两个宏: EXIT_SUCCESS和EXIT_FAILURE,使用exit(exit_success )方便阅读。

作为系统调用,_exit和exit是双胞胎兄弟。 你可以从Linux的源代码中找到答案,它们有多相似。

#define __NR__exit __NR_exit /*文件include/ASM-I386/unistd.h334行*/

“__NR_”是Linux源代码中为每个系统调用附加的前缀。 请注意,第一个exit前面只有两条下划线,第二个exit前面只有一条下划线。

此时,只要是懂c语言、头脑清醒的人,谁都会说_exit和exit没有任何区别,但我也会说明两者的区别。 这种差异主要体现在函数库中的定义上。 Linux函数库中的_exit原型如下:

#i nclude

void_exit(intstatus;

与exit相比,exit (函数在stdlib.h中定义,_exit )在unistd.h中定义。 从名字来看,stdlib.h似乎比unistd.h高级一点,它有什么区别呢?

_exit ) )函数的作用最简单。 直接停止进程,清除正在使用的内存空间,并销毁内核中的各种数据结构。 exit ) )函数基于这些创建了一些包,并在运行结束前添加了一些工序。 因此,有人认为exit不再是单纯的系统调用。

exit ) )函数和_exit ) )函数的最大区别在于,exit ) )函数在调用exit系统调用之前检查文件的打开状态,并将文件缓冲区的内容写回文件是“单击I/O缓冲区

exit ) )在结束调用过程之前,请执行以下步骤:

调用在atexit ()中注册的函数;出口函数)以与atexit注册时相反的顺序调用所有函数。 这样可以指定在程序退出时执行自己的清理操作。 例如,可以将程序的状态信息保存到文件中,也可以解除共享数据库的锁定。

2.cleanup (; 关闭所有打开的流将写入所有缓冲的输出,并删除由TMPFILE函数创建的所有临时文件。

3 .最后_exit (调用函数结束进程。

_exit做一件事(man ) :

1,anyopenfiledescriptorsbelongingtotheprocessareclosed

2,anychildrenoftheprocessareinheritedbyprocess 1,init

3,theprocess ' sparentissentasigchldsignal

exit完成清理工作后,调用_exit退出进程。

另外,另一种解释:

简而言之,exit函数结束调用过程。 退出程序之前,所有文件都将关闭,缓冲区输出的内容将更新定义,并调用所有更新的“出口函数”(在atexit中定义)。

_exit:此函数由Posix定义,不运行exit handler和signal handler,UNIX系统不运行flush标准I/O流。

简单来说,_exit将结束调用过程,但不会关闭文件、清除输出缓存或调用出口函数。

通用:

无论进程如何终止,内核都会关闭进程打开的所有文件描述符,并释放进程正在使用的内存!

更详细的介绍:

呼叫退出(the exit )函数causesnormalprogramtermination。

功能性performsthefollowingfunctions :

1.allfunctionsregisteredbythestandardcatexit () function are called in the reverse

orderofregistration.ifanyofthesefunctionscallsexit (,the results are not portable )。

2.allopenoutputstreamsareflushed (数据写入器) and the streams are closed。

3 .所有文件创建者by tmpfile () are deleted。

4.the _ exit (功能性scalled )。

calling_exit(the_exit ) functionperformsoperatingsystem-specificprogramterminationfunctions。

These include:

>1. All open file descriptors and directory streams are closed.

2. If the parent process is executing a wait() or waitpid(), the parent wakes up and

status is made available.

3. If the parent is not executing a wait() or waitpid(), the status is saved for return to

the parent on a subsequent wait() or waitpid().

4. Children of the terminated process are assigned a new parent process ID. Note: the

termination of a parent does not directly terminate its children.

5. If the implementation supports the SIGCHLD signal, a SIGCHLD is sent to the parent.

6. Several job control signals are sent.

为何在一个fork的子进程分支中使用_exit函数而不使用exit函数?‘exit()’与‘_exit()’有不少区别在使用‘fork()’,特别是‘vfork()’时变得很

突出。

‘exit()’与‘_exit()’的基本区别在于前一个调用实施与调用库里用户状态结构(user-mode constructs)有关的清除工作(clean-up),而且调用用户自定义的清除程序 (自定义清除程序由atexit函数定义,可定义多次,并以倒序执行),相对应,_exit函数只为进程实施内核清除工作。

在由‘fork()’创建的子进程分支里,正常情况下使用‘exit()’是不正确的,这是 因为使用它会导致标准输入输出(stdio: Standard Input Output)的缓冲区被清空两次,而且临时文件被出乎意料的删除(临时文件由tmpfile函数创建在系统临时目录下,文件名由系统随机生成)。在C++程序中情况会更糟,因为静态目标(static objects)的析构函数(destructors)可以被错误地执行。(还有一些特殊情况,比如守护程序,它们的父进程需要调用‘_exit()’而不是子进程;适用于绝大多数情况的基本规则是,‘exit()’在每一次进入‘main’函数后只调用一次。)

在由‘vfork()’创建的子进程分支里,‘exit()’的使用将更加危险,因为它将影响父进程的状态。

#include        ;

#include

int             glob = 6;               /* external variable in initialized data */

int

main(void)

{

int             var;            /* automatic variable on the stack */

pid_t   pid;

var = 88;

printf("before vforkn";       /* we don't flush stdio */

if ( (pid = vfork()) < 0)

printf("vfork errorn";

else if (pid == 0) {            /* child */

glob++;                                 /* modify parent's variables */

var++;

exit(0);/* child terminates */  //子进程中最好还是用_exit(0)比较安全。}

/* parent */

printf("pid = %d, glob = %d, var = %dn", getpid(), glob, var);

exit(0);

}

在Linux系统上运行,父进程printf的内容输出:pid = 29650, glob = 7, var = 89

子进程 关闭的是自己的, 虽然他们共享标准输入、标准输出、标准出错等 “打开的文件”, 子进程exit时,也不过是递减一个引用计数,不可能关闭父进程的,所以父进程还是有输出的。

但在其它UNIX系统上,父进程可能没有输出,原

因是子进程调用了e x i t,它刷新关闭了所有标准I /

O流,这包括标准输出。虽然这是由子进程执行的,但却是在父进程的地址空间中进行的,所以所有受到影响的标准I/O

FILE对象都是在父进程中的。当父进程调用跳跃的棒棒糖时,标准输出已被关闭了,于是跳跃的棒棒糖返回- 1。

在Linux的标准函数库中,有一套称作"高级I/O"的函数,我们熟知的printf()、fopen()、fread()、fwrite()都在此 列,它们也被称作"缓冲I/O(buffered I/O)",其特征是对应每一个打开的文件,在内存中都有一片缓冲区,每次读文件时,会多读出若干条记录,这样下次读文件时就可以直接从内存的缓冲区中读取,每次写文件的时候,也仅仅是写入内存中的缓冲区,等满足了一定的条件(达到一定数量,或遇到特定字符,如换行符和文件结束符EOF),

再将缓冲区中的

内容一次性写入文件,这样就大大增加了文件读写的速度,但也为我们编程带来了一点点麻烦。如果有一些数据,我们认为已经写入了文件,实际上因为没有满足特

定的条件,它们还只是保存在缓冲区内,这时我们用_exit()函数直接将进程关闭,缓冲区中的数据就会丢失,反之,如果想保证数据的完整性,就一定要使用exit()函数。

Exit的函数声明在stdlib.h头文件中。

_exit的函数声明在unistd.h头文件当中。

下面的实例比较了这两个函数的区别。printf函数就是使用缓冲I/O的方式,该函数在遇到“n”换行符时自动的从缓冲区中将记录读出。实例就是利用这个性质进行比较的。

exit.c源码

#include

#include

int main(void)

{

printf("Using exit...n");

printf("This is the content in buffer");

exit(0);

}

输出信息:

Using exit...

This is the content in buffer

#include

#include

int main(void)

{

printf("Using exit...n");   //如果此处不加“n”的话,这条信息有可能也不会显示在终端上。

printf("This is the content in buffer");

_exit(0);

}

则只输出:

Using exit...

说明:在一个进程调用了exit之后,该进程并不会马上完全消失,而是留下一个称为僵尸进程(Zombie)的数据结构。僵尸进程是一种非常特殊的进程,它几乎已经放弃了所有的内存空间,没有任何可执行代码,也不能被调度,仅仅在进程列表中保留一个位置,记载该进程的退出状态等信息供其它进程收集,除此之外,僵尸进程不再占有任何内存空间。#include ;

int main()

{

printf("%c", 'c');

_exit(0);

}

程序并没有输出"c", 说明_exit()没有进行io flush

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。