目录
1. 进程
1.1 并发和并行
并发和并行的概念
- 并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行
- 并行:当系统有一个以上 CPU 时,当一个 CPU 执行一个进程时,另一个 CPU 可以执行另一个进程,两个进程互不抢占 CPU 资源,可以同时进行,这种方式我们称之为并行(Parallel)。
并发和并行的区别
- 并发:指的是多个事情,在同一时间段内同时发生了。
- 并行:指的是多个事情,在同一时间点上同时发生了。
- 并发的多个任务之间是互相抢占资源的。
- 并行的多个任务之间是不互相抢占资源的、只有在多CPU或者一个CPU多核的情况中,才会发生并行。否则,看似同时发生的事情,其实都是并发执行的
1.2 进程的状态
进程基本的状态有五种,分别为初始态,就绪态,运行态,挂起态和终止态。其中初始态为进程准备阶段,常常与就绪态结合来看。
2. 进程的控制
2.1 fork 函数
- fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
- 一个进程调用 fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
函数原型:
pid_t fork(void);
返回值: =0:当前进程为子进程
>0:当前进程为父进程
‐1,出错
2.2 如何区分父子进程
getpid/getppid 函数
- getpid:得到当前进程的PID
- getppid:得到当前进程的父进程的PID
2.3 父子进程间的数据共享
fork 之前两个地址空间区数据完全相同, fork 后续各自进行了不同的操作
程序演示:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
int cnt = 0;
pid = fork();
if (pid > 0) // 父进程
{
while (1)
{
printf("this is father print, pid = %d, cnt = %d\n", getpid(), cnt);
sleep(1);
}
}
else if (pid == 0) // 子进程
{
while (1)
{
printf("this is chilid print, pid = %d, cnt = %d\n", getpid(), cnt);
sleep(1);
cnt++;
if (cnt == 3)
{
exit(0);
}
}
}
return 0;
}
程序执行结果:
证明了 fork 后父子进程之间不可通过全局变量通信,父子进程两者之间的数据互不干涉,各自运作。
2.4 vfork 函数
vfork也可以创建进程,与fork有什么区别呢?
- 区别一:vfork 可以直接使用父进程存储空间,不拷贝
- 区别二:vfork 可以保证子进程先运行,当子进程调用 exit 退出后,父进程才执行
程序演示:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
int cnt = 0;
pid = vfork();
if (pid > 0) //父进程
{
while (1)
{
printf("this is father print, pid = %d, cnt = %d\n", getpid(), cnt);
sleep(1);
}
}
else if (pid == 0) // 子进程
{
while (1)
{
printf("this is chilid print, pid = %d, cnt = %d\n", getpid(), cnt);
sleep(1);
cnt++;
if (cnt == 3)
{
exit(0);
}
}
}
return 0;
}
程序执行结果: