一、进程创建
1、fork函数:
可以在代码中创建一个子进程。
pid_t fork(void)
- a. 没有参数
- b. pid_t:·本质是整形
- c. 原理:fork创建的子进程的PCB拷贝父进程的PCB
- d. 返回值:
创建失败:-1
创建成功:>0(子进程的PID号):返回给父进程
=0:返回给子进程
注意:
- 子进程是拷贝父进程的PCB的,子进程的大部分数据来源于父进程,例如:内存指针(数据段、代码段)
- 父进程创建子进程成功之后,父子进程是两个独立的进程(进程的独立性),父子进程的调度取决于操作系统内核
- 进程是抢占式执行的,父子进程谁先运行是不能确定的
- 写时拷贝:写时拷贝是一种可以推迟甚至免除拷贝数据的技术。 内核此时并不复制整个进程地址空间,而是让父进程和子进程共享同一个拷贝。 只有在需要写入的时候,数据才会被复制,从而使各个进程拥有各自的拷贝。 也就是说, 资源的复制只有在需要写入的时候才进行 ,在此之前,只是以只读方式共享。
2、vfork函数:
父进程与子进程的内存指针指向同一块进程虚拟地址空间
调用方法:与fork函数完全相同
- vfork函数调用栈混乱的问题:子进程调用函数不出栈,则父进程调用函数也出不了栈
- 解决方法:子进程先调用,子进程调用完毕之后,父进程再调用
二、进程终止
- 进程终止的方法:
1、从main函数的return返回
2、exit函数
3、_exit函数
exit函数是库函数,在调用时会刷新缓冲区;
而_exit函数是库函数,在调用时不会刷新缓冲区。
三、进程等待
1、进程等待的作用:
父进程进行进程等待,子进程在先于父进程退出之后,由于父进程在等待子进程,所以父进程会回收子进程的退出资源,从而防止子进程产生僵尸进程。
2、wait函数:
pid_t wait(int *status)
- 返回值:成功返回子进程的pid号;失败返回-1
- 参数:整形指针,4个字节中只使用到2个字节。在这2个字节中,前8个比特位为进程退出码,中间一位为coredump标志位,后7位为终止信号。
见下图:
coredump标志位:
取值为1:表示当前的进程是由coredump(核心转储文件)产生
取值为0:表示当前进程没有coredump产生
终止信号:当前程序是由什么信号导致的终止
参数int *status是一个出参:
调用者准备一个int型的变量,将地址传给wait函数,wait函数在自己实现的内部进行赋值,当wait函数返回后,调用者就可以通过int变量,获取进程退出的信息。
下面对wait函数进行测试,看调用wait函数之后,子进程是否还会产生僵尸进程:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>
int main()
{
pid_t pid=fork();
if(pid<0)
{
printf("create process failed\n"