目录
一、写时拷贝
二、创建多进程
三、进程终止
(一)main函数的返回值
1. main函数的返回值
2. 退出码
3. 查看进程的退出码
(二)错误码VS退出码
(三)代码异常终止
1. 基本概念
2. 信号
(四)进程常见退出方法
1. exit函数
2. _exit函数
3. exit和_exit的区别
一、写时拷贝
- 通常,父子代码共享,父子再不写入时,数据也是共享的,当任意一方试图写入,便以写时拷贝的方式各自一份副本。
二、创建多进程
父进程创建了5个子进程,每个子进程都会执行 Worker()
函数
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<stdlib.h>//exit的头文件
#define N 5
void Worker()
{
int cnt = 10;
while(cnt)
{
printf("I am a child process, pid: %d, ppid: %d, cnt: %d\n",getpid(),getppid(),cnt);
sleep(1);
cnt--;
}
}
int main()
{
int i;
for(i=0;i<N;i++)
{
sleep(1);
pid_t id =fork();
if(id == 0)//子进程
{
Worker();
exit(0);
}
}
sleep(100);
return 0;
}
三、进程终止
(一)main函数的返回值
1. main函数的返回值
- main函数的返回值也称进程的退出码
- 在多进程环境中,创建子进程的目的是“帮我办事”,怎么得知子进程将事办的怎么样,获取子进程的退出码
2. 退出码
- 进程因为什么原因失败的,1,2,3..,不同的数字表示不同的原因,但是纯数字不方便人阅读,所以需要将退出码转换成退出码字符串描述
errno
是一个全局变量,它在C标准库中被定义为一个int
类型,用于记录发生在程序中的错误信息strerror
是一个C标准库中的函数,用于将一个错误码(通常是由系统调用返回的errno)转换为相应的错误信息字符串
测试2:
#include<stdio.h>
#include<string.h>//strerror的头文件
#include<errno.h>
int main()
{
printf("before: %d\n",errno);
FILE* fp = fopen("./log.txt","r");
printf("after: %d, error string: %s\n",errno,strerror(errno));
return 0;
}
3. 查看进程的退出码
- ?:保存最近一个子进程执行完毕时的退出码
echo $?
(二)错误码VS退出码
- 错误码通常是衡量一个库函数或者是一个系统调用一个函数的调用情况
- 退出码通常是一个进程退出的时候,他的退出结果
- 两者都是,当失败的时候,用来衡量函数,进程出错是出错详细原因
(三)代码异常终止
1. 基本概念
- 进程出异常,本质是进程收到了对应的信号,自己终止了。
- 一个进程是否出异常,我们只要看有没有收到信号即可(保存信号的位置如果是0,表示没收到信号;非0,表示收到了信号)
2. 信号
- 代码中出现异常,操作系统会将异常转化成信号,操作系统给进程发送信号将进程终止
kill -l //列出信号
#include<stdio.h>
int main()
{
int a = 10;
a /=0;
return 0;
}
(四)进程常见退出方法
1. exit函数
#include <unistd.h>
void exit(int status);
2. _exit函数
#include <unistd.h>
void _exit(int status);
参数:status 定义了进程的终止状态,父进程通过wait来获取该值
3. exit和_exit的区别
- exit是库函数,_exit是系统调用
- exit终止进程的时候,自动刷新缓冲区。_exit终止进程的时候,不会自动刷新缓冲区