前言
提示:这里要解决以下问题
- 进程是如何退出的,具体过程是什么?
- exit,_exit,return,有什么区别?
- 块缓冲和行缓冲的区别?
一、进程是如何退出的,具体过程是什么?
- 看看return和exit的差别
在linux上分别跑一下这个代码
int main()
{
return 0;
//exit(0);
}
return 0
exit 0
结论:
return()
会弹出栈,将释放局部变量。而exit()
会进入内核,告知内核进程已死,并回收资源。
规定vfork()绝不可以调用return()
二. exit,_exit,return,有什么区别?
- return() 代表调用栈的返回,exit()代表一个过程的结束。
- 从main函数退出,会隐式的调用exit()函数,并将return的返回值传递给exit().
- 从exit()退出,会先调用退出程序,刷新stdio流缓冲区,使用由status提供的值执行_exit()系统调用
- return 是关键字,exit()是库函数。
三. 块缓冲和行缓冲的区别
用例子来引出问题:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char **argv)
{
printf("hello world\n");
write(STDOUT_FILENO,"Ciao\n",5);
if (fork() == -1)
exit(-1);
exit(EXIT_SUCCESS);
}
输出到终端时:
>>> a.out
hello world
Ciao
输出到文件中时:
>>> a.out > test.md
[xxxx@ubuntu ~/practice]@practice
>>> cat test.md
Ciao
hello world
hello world
printf()输出行出现了两次,且write()的输出先于printf()
要理解这个问题,那么要记住:stdio缓冲区是维护在进程的用户空间内存中的,fork()会复制缓冲区给子进程。第一次因为缺省缓冲区为行缓冲区,可以立即显示printf()输出的包含换行符的字符串。
但是输出到文件就成了块缓冲区,只有到了父进程和子进程调用exit()之后,刷新了两次stdio缓冲区,所以打印了两次printf();
- 那么为什么write()会出现在printf之前呢,还只出现了一次?
这是因为write(),会将数据传送至内核缓冲,fork()不会复制这一缓冲区。 - 行缓冲区遇到换行符/时间够长/数据够多/程序结束,就会输出;而块缓冲区,只会因为数据量足够多的时候才会输出。
以下代码不会出现上述问题
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char **argv)
{
printf("hello world\n");
fflush(stdout);
write(STDOUT_FILENO,"Ciao\n",5);
if (fork() == -1)
exit(-1);
exit(EXIT_SUCCESS);
}