进程创建
进程创建比较简单。有两个函数可以调用:fork()和vfork()。
fork()
pid_t id = fork();
fork()函数测试代码:
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
int glob = 10;
int main()
{
pid_t pid;
printf("Before:pid is %d\n",getpid());
if((pid =fork())==-1)
{
perror("fork()");
exit(1);
}
printf("After:pid is %d,fork return %d\n",getpid(),pid);
sleep(1);
}
fork()成功之后,创建一个子进程,多了一整套数据结构,内核会分配新的内存块和内核数据结构给子进程。fork函数返回子进程的pid给父进程,给子进程返回0;fork()之后,父子进程哪个先结束完全由调度器决定,并不保证哪个进程先运行。
vfork()
pid_t pid = vfork();
vfork()跟fork()有两个区别:
- vfork()会保证子进程先运行;
- vfork()父子进程共享,而fork的子进程具有独立地址空间
vfork()函数测试代码:
#include<stdlib.h>
#include<stdio.h>
#include<unistd.h>
int glob = 10;
int main()
{
pid_t pid=vfork();
if(pid==0)
{
glob = 30;
printf("I am child , pid: %d, glob = %d, &glob %d\n",getpid(),glob,&glob);
sleep(3);
exit(0);
}else{
printf("I am parent , pid: %d, glob = %d, &glob %d\n",getpid(),glob,&glob);
sleep(1);
}
sleep(1);
}
我们运行可以发现,子进程先于父进程运行,在子进程中改变glob值,父进程的glob值也被改变,而且glob的地址是一样的,说明父子进程共用地址空间。
进程终止
https://www.cnblogs.com/zfyouxi/p/5204052.html
进程退出有三种场景:
- 代码运行完毕,结果正确
- 代码运行完毕,结果不正确
- 代码异常终止,也就是进程收到了信号
1、2种场景是正常退出的情况,有退出码
退出码:正确为0,错误为非0
status 低七位:收到的异常信号 status & 0x7F
没有收到信号,说明至少正常跑完,如果退出码为0,结果正确。没收到信号 如果退出码不为0,正常跑完,结果不正确。
1到64 没有32,33 一共有62个信号, 前面1到31位普通信号
中间一位 core dump 核心转储
status 次低八位:退出码 (status >> 8) & 0x7F
先看低七位有没有信号,没有信号再看退出码
进程常见退出方法:
正常终止(可以使用 echo $? 查看进程退出码)
- 从main函数return
- 调用exit
- 调用_exit
异常退出
- ctrl+c,信号终止
_exit函数用来结束一个进程
#include<unistd.h>
void _exit(int status);
参数status定义了进程的终止状态,父进程通过wait来获取该值,status是int类型,但仅有低8位可以被父进程所用。所以_exit(-1)时,在终端执行$?发现返回值时255
exit函数也是用来结束一个进程