49_进程之程序的开始和结束

原则:覆盖面广,不会展开讲很深,要点都会让大家理解,不会大而全。

程序的开始和结束:a.out 每次运行都是一次开始和结束。

程序的开始,main是开始,但是谁调用的main,系统调用的,不完全准确,有一个汇编阶段的引导代码,start。s,在操作系统里面也是,编译器编译链接时候叠加的,起始引导代码,在main之前,任务有,构建c语言运行环境,这一段引导代码使系统提供的,我们不用考虑,程序链接时,链接器把这一段引导代码放在应用程序之前,构成可执行文件。

。c文件先编译,变成。o文件,再由链接器链接生成类似。out的可执行程序

加载器:当我们执行a.out(exec族函数)时,加载器负责将这个程序加载到内存中去运行,有一个重定位的功能。

编译器,链接器,加载器,

编译链接时,用链接器,运行时用加载器

argc和argv是如何实现的

shell会给加载器,加载器给函数的引导代码,给main函数


程序如何结束

正常结束,程序自己明确表示退出,例如,main函数中最后return 0,也可以exit或_exit,大部分没有区别,

不正常结束,通过信号来终止进程,信号就是程序在运行时,其他进程发来的一个标志/标记/信号,跟高权限的进程可以关闭更低权限的进程。ctrl+C推出当前程序,所有的进程都可以被ctrl+c来终止,除非额外设置。

atexit注册进程终止处理函数:进程终止之前要做的一些处理,类似于下班前上洗手间打卡,无论什么时候终止,这个程序都会被运行。只有在进程终止的时候才运行

#include
#include 


void func1(void)
{
	printf("This is atexitFunc.\n");	
}

int main(void)
{
	printf("Hello world!\n");
	atexit(func1);//注意打印的时候,这一句最后才显示
	printf("LT is a good boy!\n");
	
	return 0;
}

49_进程之程序的开始和结束_第1张图片

有的时候需要多个进程终止处理函数,先进后出,跟栈是一样的

先注册的后执行

后注册的先执行

#include
#include 


void func1(void)
{
	printf("This is atexitFunc1.\n");	
}

void func2(void)
{
	printf("This is atexitFunc2.\n");	
}

int main(void)
{
	printf("Hello world!\n");
	atexit(func1);//注意打印的时候,这一句最后才显示
	atexit(func2);//注意打印的时候,这一句最后才显示
	printf("LT is a good boy!\n");
	
	return 0;
}
49_进程之程序的开始和结束_第2张图片

压栈方式来处理,还是应该好好看看C语言。

return与exit效果一样,都会执行进程终止处理函数。

_exit(0)不会执行进程终止处理函数,终止进程时,并不执行进程终止处理函数。记住这个结论就行了。

return和exit的回调函数会跟func函数绑定

_exit不会跟进程终止处理函数相绑定,所以没执行进程终止处理函数。

一般能看懂别人写的就可以的,自己还用不起来。知道原理就行了,遇到了能看懂就行了。
















你可能感兴趣的:(Linux)