25.Linux/Unix 系统编程手册(上) -- 进程的终止

1.进程的终止 : _exit() 和 exit()
	1. _exit(int status), status 定义了终止状态,父进程可调用 wait 获取。仅低8位可用,
	  调用 _exit() 总是成功的。
	2.程序一般不会调用 _exit(), 而是调用库函数 exit()。
	  exit() 执行如下动作:
	  	1.调用退出处理程序(通过 atexit() 和 on_exit() 注册的函数),其执行顺序与注册顺序相反。
	  	2.刷新 stdio 流缓冲区
	  	3.使用由 status 提供的值执行 _exit() 系统调用。
	与专属的Unix的 _exit 不同, exit() 则属于标准C语言函数库。


2.进程终止的细节
	无论进程是否正常终止,都会发生如下动作:
	1.关闭所有打开文件描述符,目录流,信息目录描述符,以及转换描述符
	2.作为文件描述符关闭的后果之一,将释放该进程所持有的任何文件锁
	3.分离任何已经连接的 System V 共享内存段,且对应于各段的 shm_nattch 计数器值减一
	4.进程为每个 System V 信号量所设置的 semadj 值将会被加到信号量值中。
	5.如果该进程是一个管理终端的管理进程,那么系统会向该终端前台进程组中的每个进程发送 sighup 信号,
	  接着终端会于会话脱离。
	6.将关闭该进程打开的任何 POSIX 有名信号量,类似调用 sem_close()
	7.将关闭该进程打开的任何 POSIX 消息队列,类似于调用 mq_close()
	8.作为进程退出的后果之一,如果某进程组称为孤儿,且该组中存在任何已停止进程,则组中所有进程都将收到 sighup 
	  信号,随着为 sigcont 信号。
	9.移除该进程通过 mlock() 和 mlockall() 锁建立的任何内存锁
	10.取消该进程调用 mmap() 所创建的任何内存映射。


3.退出处理程序
	退出处理程序是一个由程序设计者提供的函数,可于进程生命周期的任意时间点注册,并在该进程调用 exit() 正常终止时
  自动执行。如果程序直接调用 _exit() 或者因信号而异常终止,则不会调用退出处理程序。
    当程序收到信号而终止时,将不会调用退出处理程序。这一事实一定程序上限制了它们的效用。此时最佳的应对方式莫若为可能发送
  给进程的信号建立信号处理程序,并于其中设置标志位,领主程序据此来调用 exit()。因为 exit() 不属于异步信号安全函数,所有通常
  不能在信号处理程序中对其发起调用。
  
  atexit();
  on_exit(); 

  	通过 fork 创建的子进程会继承退出处理程序,而 exec 会清除退出处理程序。


4.fork,stdio缓冲区以及_exit 之间的交互

#include <stdio.h>

int main()
{
        printf("start:\n");
        if ( fork() == -1 ) {
                exit(1);
        }
        exit(0);
}

	printf() 信息输出了2次,是在进程的用户空间内存维护 stiod 缓冲区的。因此,通过 fork 创建的子进程会复制这些缓冲区。
  父子进程调用 exit() 时,会各自刷新 stdio 缓冲区,从而导致重复输出。

  可以采用以下2种方法避免:
  1.可以在调用 fork 之前,使用 fflush() 来刷新 stdio 缓冲区,作为另外一种选择,使用 setvbuf() 和 setbuf() 来关闭 stdio 流缓冲。
  2.子进程可以调用 _exit() 而非 exit(),以便不刷新 stdio 缓冲区。
  这一技术例证了更为通用的原则:在创建子进程的应用中,典型情况下仅一个进程(一般为父进程)应通过调用 exit() 终止,而其他进程应调用 _exit()终止,
 从而确保一个进程调用退出处理程序刷新 stdio 缓冲区。

  write 并未出现2次,是因为 write 会将数据直接传递给内核缓冲区,fork 不会复制这一缓冲区。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值