《3.linux应用编程和网络编程-第4部分-3.4.linux进程全解》3.4.1.程序的开始和结束 atexit();

第一部分、章节目录
3.4.1.程序的开始和结束
3.4.2.进程环境
3.4.3.进程的正式引入
3.4.4.fork创建子进程
3.4.5.父子进程对文件的操作
3.4.6.进程的诞生和消亡
3.4.7.父进程wait回收子进程
3.4.8.waitpid介绍
3.4.9.exec族函数及实战1
3.4.10.exec族函数及实战2
3.4.11.进程状态和system函数
3.4.12.进程关系
3.4.13.守护进程的引入
3.4.14.编写简单守护进程
3.4.15.使用syslog来记录调试信息
3.4.16.让程序不能被多次运行
3.4.17.linux的进程间通信概述
3.4.18.linux的IPC机制1-管道
3.4.19.SystemV IPC介绍

第二部分、章节介绍
3.4.1.程序的开始和结束
    本节讲述一个典型程序的开始运行和结束运行,引入引导代码让大家更容易的理解操作系统是如何运行一个程序的。
3.4.2.进程环境
    本节讲解进程的环境变量和虚拟地址空间,这些都是一个进程在系统中运行时的外部环境。
3.4.3.进程的正式引入
    本节正式引入进程的概念,讲述了进程的ID以及获取进程ID的函数,多进程调度实现宏观上并行的原理。
3.4.4.fork创建子进程
    本节引入子进程,并且讲解并实战演示了fork函数如何创建子进程。
3.4.5.父子进程对文件的操作
    本节通过父子进程对文件的操作来说明父子进程的区别和联系。
3.4.6.进程的诞生和消亡
    本节讲述进程的诞生和消亡过程,着重讲了僵尸进程和孤儿进程的概念,进程资源回收和状态返回等。
3.4.7.父进程wait回收子进程
    本节讲解wait函数回收子进程的信号式异步通信工作原理,并且实战演练了使用wait来回收子进程的过程。
3.4.8.waitpid介绍
    本节首先介绍waitpid和wait函数的差别,然后实战演示了waitpid函数的3种常见用法,最后简单讲解了竟态的概念。
3.4.9.exec族函数及实战1
    本节开始讲解exec族函数的作用和各个API的差异,并且写代码进行演示。
3.4.10.exec族函数及实战2
    本节演示了exec族的p后缀和e后缀函数的用法。
3.4.11.进程状态和system函数
    本节详细讲解了linux中进程的5种状态和状态转换图,最后讲了下system函数
3.4.12.进程关系
    本节讲解进程的四种关系:无关系、父子关系、进程组和会话。
3.4.13.守护进程的引入
    本节引入守护进程的概念,并且介绍了常见的一些系统级服务器守护进程及其作用。
3.4.14.编写简单守护进程
    本节实践编程自己实现一个守护进程,让大家熟悉守护进程的创建过程。
3.4.15.使用syslog来记录调试信息
    本节讲解如何在程序中使用syslog记录日志信息,这是一种非常常见的程序调试信息输出手段,也是守护进程必用的调试信息输出手段。
3.4.16.让程序不能被多次运行
    本节介绍如何让我们的程序只能运行一次,即所谓单例运行的常规实现方法。这个在实际工作中很有用。
3.4.17.linux的进程间通信概述
    本节进行linux中进程间通信IPC的概述,指明了后面如何讲解IPC。
3.4.18.linux的IPC机制1-管道
    本节详细讲了传统Unix的进程间通信方法:管道和有名管道。
3.4.19.SystemV IPC介绍    
    本节对SystemV IPC的三种(信号量、消息队列、共享内存)方式进行概括性讲解和对比。
 

3.4.1.程序的开始和结束
3.4.1.1、main函数由谁调用
(1)编译链接时的引导代码。操作系统下的应用程序其实在main执行前也需要先执行一段引导代码才能去执行main我们写应用程序时不用考虑引导代码的问题,编译连接时(准确说是连接时)由链接器将编译器中事先准备好的引导代码给连接进去和我们的应用程序一起构成最终的可执行程序。


(2)  ./a.out  运行时的加载器。加载器是操作系统中的程序,当我们去执行一个程序时(譬如./a.out,譬如代码中用exec族函数来运行)加载器负责将这个程序加载到内存中去执行这个程序。
(3)程序在编译连接时用链接器,运行时用加载器,这两个东西对程序运行原理非常重要


(4)argc和argv的传参如何实现: 其实蛮 复杂的  

  我们之前说 argc 和 argv 是给man传参的,

当前shell这个进程接收到的参数,会传给加载器,加载器会传给引导代码,最后传给 main 

3.4.1.2、程序如何结束
(1)正常终止:return、exit、_exit

    return 0 正常终止,return -1 非正常终止
(2)非正常终止:自己或他人发信号终止进程:程序在运行的时候,有好多进程,信号就是一个标志或电话,你有一个事情需要另一个人帮忙,另一个人的工作就终止了,过来帮忙

所有的进程 : 默认都会被 ctrl+c 终止


3.4.1.3、atexit注册进程终止处理函数
(1)实验演示
(2)atexit注册多个进程终止处理函数,先注册的后执行(先进后出,和栈一样)

 代码:

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


void func1 (void)
{
	printf("func1 \n");
}

int main(void)
{
	printf("hello word \n");
	
	//注册了 func1 为 我们的进程终止程序
	//效果是什么呢? 当我们的进程被进程正常终止时,系统会调用注册 func1 执行
	atexit(func1);
	
	
	return 0;
}

运行结果:

 

这样看不出来效果!!

在修改一下

添加到 atexit 下面一行代码

代码:

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


void func1 (void)
{
	printf("func1 \n");
}

int main(void)
{
	printf("hello word \n");
	
	//注册了 func1 为 我们的进程终止程序
	//效果是什么呢? 当我们的进程被进程正常终止时,系统会调用注册 func1 执行
	atexit(func1);
	
	printf("my name shi LiLei \n");
	
	return 0;
}


运行结果:

 (2)atexit注册多个进程终止处理函数,先注册的后执行(先进后出,和栈一样)

     如果 atexit 注册两次 会怎么样呢

代码:

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


void func1 (void)
{
	printf("func1 \n");
}

void func2(void)
{
	printf("func2 \n");
}


int main(void)
{
	printf("hello word \n");
	
	//注册了 func1 为 我们的进程终止程序
	//效果是什么呢? 当我们的进程被进程正常终止时,系统会调用注册 func1 执行
	atexit(func1);
	/* 注册第二次  */
	atexit(func2);
	
	printf("my name shi LiLei \n");
	
	return 0;
}

 

运行结果:

      跟栈是一样,先进后出


(2)return、exit和_exit的区别:return和exit效果一样,都是会执行进程终止处理函数,

 

 

(2.2 )但是用_exit终止进程时并不执行atexit注册的进程终止处理函数。

 

 回调函数被执行 就是在 return 0;之后 执行 atexit();

代码来自:物联网大讲堂

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大漠飞鹰6666

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值