什么是进程?
程序被加载到内存中运行,这样的动态过程,就是进程。
进程号
每个进程都有进程号,系统中用于识别不同进程,通常为正数。程序中获取进程号可调用getpid()、getppid()函数进行获取。(命令 man 2 getpid 或 man 2 getppid 获取函数使用说明)
子进程
子进程被创建出来之后,便是一个独立的进程,拥有自己独立的进程空间,系统内唯一的进程号,子进程会被内核同等调度执行,参与到系统的进程调度中。
fork创建子进程
这是一个简单的fork创建子进程函数,程序中关于缓冲区,可以参考第三节内容了解。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
__pid_t pid;
pid = fork(); //创建子进程
switch (pid)
{
case -1:
perror("fork error");
exit(-1);
case 0:
printf("子进程执行: 子进程PID: %d 父进程PID: %d\n",
getpid(), getppid());
_exit(0);//程序退出时不会刷新缓冲区
//exit(0);//程序退出时刷新缓冲区
default:
printf("父进程执行: 子进程PID: %d 父进程PID: %d\n",
getpid(), getppid());
break;
}
exit(0);
}
函数说明:
用__pid_t创建一个进程号类型的变量(有的函数库里是pid_t)。
fork()创建子进程,此时程序中有两个进程,称为父进程和子进程。
父子进程根据进程号不同,执行各自相关内容。
从执行结果可知case 0 和 default 内容都会被执行,其原因是:子进程拷贝了父进程的数据段、堆、栈,同时还继承了父进程打开的文件描述符,父进程与子进程并不共享这些存储空间。所以fork函数调用后的内容,会被子进程和父进程各执行一次。
vfork创建子进程
这是一个用vfork函数创建子进程的例程。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
int main(void)
{
pid_t pid;
pid = vfork();
switch (pid){
case -1:
perror("vfork error");
exit(-1);
case 0:
printf("子进程\n");
exit(0);
default:
printf("父进程\n");
exit(0);
}
}
该函数与fork函数一样,都是创建出子进程,区别如下
1. vfork()函数会保证子进程优先执行。
2. vfork函数创建新进程时并不复制子进程的地址空间,在必要的时候才重新申请新的存储空间,这相对于fork函数而言,一定程度上提高了代码的执行效率。