1、进程创建 使用fork()函数创建子进程,返回值为pid_t,其实就是int
#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
int main(){
pid_t pid=fork();//创建子进程,在父进程中返回子进程ID,在子进程中返回0,返回-1表示子进程创建失败
pritf("%d %d ",getpid(),getppid());//返回pid ppid
return 0;
}
所创建的父子进程虚拟空间示意:
父子进程的数据互不干扰,对于子进程而言,他的数据在读时创建。父子进程的诗句读时共享,写时拷贝。
sleep()函数
在Windows系统中:
Sleep(2*1000); //sleep for 2 seconds
在Unix系统中:
sleep(2); //sleep for 2 seconds
使用exec函数组创建进程
exec并不像fork建立新的函数 而是在现有进程基础上替换现有进程基础的内存,如代码段,数据段,堆栈等,但进程ID不变,并且失败返回-1
2、进程退出
exit(0)是c++库函数,会刷新缓冲区。
#include<stdib.h>
#include<unistd.h>
#inlcude<stdio.h>
int main(){
printf("jiayou\n");//\n会刷新缓冲区
printf("jiayou");
exit(0);//作用相当于main函数的return 0;
_exit(0);//不刷新I/O缓冲区,第二行不会打印出来
return 0;
}
3、孤儿进程
父进程结束后还在运行的子进程叫做孤儿进程。因为孤儿进程的内存需要父进程来回收,所有需要进行处理。内核会把孤儿进程的子进程的父进程设置为init,由init进程来回收它的资源。
当前终端是在终端中执行文件的父进程。
创建多进程是为了实现多道程序并发,提高运行效率。
4、僵尸进程
每个进程结束后,都会释放掉自己的资源。但内核区的PCB没有办法释放掉。需要父进程去释放。
子进程运行结束后,父进程并没有回收子进程的PCB,可能是还在运行。最重要的是会占用进程号,而进程号本身有限。并且kill -9 pid不可以杀死僵尸进程。杀不死,怪不得叫僵尸进程。
父进程使用wait()或者waitpid()就可以释放资源,并且可以得到子进程结束时的状态。wait()函数会阻塞父进程,阻塞到子进程结束或者收到信号,如果子进程结束,返回子进程ID,如果没有子进程,返回-1。而waitpid()函数可以设置不阻塞,并且回收指定进程号的子进程。
wait()/waitpid()等待进程状态改变。
pid_t wait(int *status);
pid_t waitpid(pid_t pid, int *status, int options);
fork();
fork();//产生4个进程,因为共享接下来的代码
如果子进程没有死,wait()会阻塞在当时,不执行以下的代码。
wait()函数的参数 可以获取exit(int). 子进程退出的状态。