Linux基础5-进程控制1(fork创建子进程,写时拷贝,进程退出)
上篇文章:Linux基础4-进程5(程序地址空间详解)-CSDN博客
本篇重点:fork,写实拷贝,进程退出
目录
一. fork创建子进程
1.1 fork用法
1.2 fork返回值有两个的理解
二. 进程退出码
2.1 进程退出码
2.2 进程退出码所对应的退出信息
三. 进程退出
四. 下篇重点:进程退出和阻塞,非阻塞等待
一. fork创建子进程
1.1 fork用法
上篇文章提到,我们可以使用fork来创建一个子进程,详细用法如下:
//所需头文件
#include <unistd.h>
//函数原型
pid_t fork(void);
//返回值
//成功的情况下,在父进程返回子进程的pid,在子进程中返回0
//失败则会返回-1
//子进程不会执行父进程fork之后的代码
fork常用于:
1 一个父进程希望复制自己,让子进程执行不同的代码段(如父进程等待客户端请求,生成子进程来处理收到的请求)
2 一个进程想要执行一个不同的程序,如创建子进程进行exec(进程替换)
1.2 fork返回值有两个的理解
1 为什么父进程返回子进程的pid,而子进程返回0?
因为fork之后,各自执行自己的代码。各自获得自己的return值
2 为什么通过if,else可以让父子进程同时执行自己的代码?
如:上篇文章提到的代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int global_value = 100;
int main()
{
pid_t id = fork();
if(id < 0)
{
printf("fork error!\n");
return -1;
}
else if(id == 0) //子进程
{
int cnt = 0;
while(1)
{
printf("子进程,pid:%d ppid:%d | global_value:%d,&global_value: %p\n",getpid(),getppid(),global_value,&global_value);
sleep(1);
cnt++;
if(cnt == 10)
{
global_value = 1234;
printf("子进程已经修改了全局变量!\n");
}
}
}
else
{
//父进程
while(1)
{
printf("父进程,pid:%d ppid:%d | global_value:%d,&global_value: %p\n",getpid(),getppid(),global_value,&global_value);
sleep(2);
}
}
return 0;
}
我们在上篇文章知道了,父子进程一方写入会发生写实拷贝
当我们调用了fork之后,return pid的时候就会发生写实拷贝,让父子进程有了不同的返回值,这样一来就能够通过if else 来判断各自的p返回值从而达到执行不同的代码
二. 进程退出码
2.1 进程退出码
我们知道,一个程序结束之后我们会返回0
我们可以使用 下面这个命令获取上一次进程退出的返回值
echo $?
适当修改代码:
这个值我们称为进程退出码,通过进程退出码我们可以知道进程退出的信息!
进程退出后:
代码执行完了,并且返回了0:说明进程正常执行并且退出
代码执行完了,但是没有返回0:这个时候我们通过进程退出码,来获取相关信息
进程崩溃了,退出码就无意义
如:下例代码,正确返回0,计算失败返回1。由于sum我们最后加了100,所以返回值是1
#include <stdio.h>
#include <unistd.h>
int sum(int begin,int end)
{
int sum = 0;
for(int i = begin; i <= end; i++)
{
sum += i;
}
sum += 100;
return sum;
}
int main()
{
int ans = sum(1,10);
if(ans == 55)
return 0;
else
return 1;
}
进程退出的时候,会给出进程退出码,用于标定进程是否正确
那么我们如何设定退出码呢?
如果我们不关心进程退出码的话,直接返回0即可!关心进程退出码,我们返回特定的进程退出码即可
一般用0标定正确返回,非0标定错误。我们使用不同的数字标定不同的退出信息!
对于退出信息,系统的一个进程退出码有一个退出信息。
我们可以自定义退出信息,也可以使用系统设置的退出信息
2.2 进程退出码所对应的退出信息
我们使用 strerror(进程退出码) 即可获取系统标定的信息!(系统共有134个退出码)
#include <stdio.h>
#include <string.h>
#include <errno.h>
int main()
{
//显示进程退出码信息
for(int i = 0; i <= 134; i++)
{
printf("%d -> %s\n", i, strerror(i));
}
return 0;
}
运行结果如下:
三. 进程退出
让进程正常退出的方法!
1 main函数返回
2 exit() 函数(C语言库函数)
3 _exit() 系统调用
//exit 所需头文件
#include <stdlib.h>
void exit(int status);
//status就是我们想要退出的退出码
//_exit 所需头文件
#include <unistd.h>
//用法和eixt一样
void _exit(int status);
直接 exit(退出码),即可将该进程退出,并且返回对应的退出码
exit 和 _exit 的区别
exit 终止进程会主动刷新C语言的用户级缓冲区
_exit 由于是系统调用,不会刷新该缓冲区
如:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void f()
{
exit(0);
}
int main()
{
printf("hello yzc!\n");
f();
while(1) sleep(1); //休眠
return -1;
}