三、Linux进程
1.进程
1.1.进程的概念
-
程序:二进制文件,占用的磁盘空间
-
进程: 启动的程序 所有的数据都在内存中
-
需要占用更多的系统资源
-
cpu,物理内存
1.2.并发和并行
-
并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是 在同一个处理机上运行
并发不是真正意义上的“同时进行”,只是CPU把一个时间段划分成几个时间片段(时间区间),然后在这几 个时间区间之间来回切换,由于CPU处理的速度非常快,只要时间间隔处理得当,即可让用户感觉是多个应 用程序同时在进行。如:打游戏和听音乐两件事情在同一个时间段内都是在同一台电脑上完成了从开始到结 束的动作。那么,就可以说听音乐和打游戏是并发的。
-
并行:当系统有一个以上CPU时,当一个CPU执行一个进程时,另一个CPU可以执行另一个进程,两个进程 互不抢占CPU资源,可以同时进行,这种方式我们称之为并行(Parallel)。
其实决定并行的因素不是CPU的数量,而是CPU的核心数量,比如一个CPU多个核也可以并行
并行和并发的区别:
-
并发,指的是多个事情,在同一时间段内同时发生了。
-
并行,指的是多个事情,在同一时间点上同时发生了。
-
并发的多个任务之间是互相抢占资源的。
-
并行的多个任务之间是不互相抢占资源的。
-
只有在多CPU或者一个CPU多核的情况中,才会发生并行。否则,看似同时发生的事情,其实都是并发执行的
1.3.PCB(进程控制块)
每个进程在内核中都有一个进程控制块(PCB)来维护进程相关的信息,linux内核的进程控制块是task_struct结构体。
/user/src/linux-headers-3.16.0-30/include/linux/sched.h头文件中可以查看struct task_struct结构体定义。内部 成员有很多,我们重点掌握以下部分即可。
- 进程id。系统中每个进程有唯一的id,在C语言中用pit_t类型表示,其实就是一个非负整数
- 进程的状态,有就绪,运行,挂起,停止等状态。
- 进程切换时需要保存和恢复一些CPU寄存器
- 描述虚拟地址空间的信息(个人理解->方便找到实际物理地址空间的映射)
- 描述控制终端的信息
- 当前工作目录(Cueernt Working Directory)------->例如pwd
- umask掩码
- 文件描述符,包含很多指向file结构体的指针
- 和信号相关的信息
- 用户id和组id,stat
- 会话(Session)和进程组(进程组之间的交流叫会话)
- 进程可以适用的资源上线(Resource Limit),umilit -a
1.4.进程状态
进程基本的状态有五种,分别为初始态,就绪态,运行态,挂起态和终止态。 其中初始态为进程准备阶段,常常与就绪态结合来看
2.进程的控制
2.1.fork函数
一个进程,包括代码、数据和分配给进程的资源。 fork()函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的 事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。 一个进程调用fork()函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进 程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
包含的头文件:
#include <sys/types.h>
#include <unistd.h>
函数原型:
pid_t fork(void);
两个返回值:
=0:当前进程为子进程-----pid = 0
>0:当前进程为父进程-----pid = 子进程pid
‐1,出错
注意:用户数据一样,进程ID不一致。
- 1.fork函数的返回值 —>0|=0|<0
- 2.子进程创建成功之后,子进程的执行位置 ------fork之后的区域为子进程执行区域
- 3.父子进程的执行顺序 不一定 -----fork的进程两个进程会打架
- 4.如何区分父子进程----判断返回值来区分
2.2.getpid/getppid函数
getpid:得到当前进程的PID getppid:得到当前进程的父进程的PID
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
pid_t pid;
int i = 0;
for(;i<4;i++)
{
printf("----i = %d\n",i);
}
pid = fork();//>0 return child pid
if(pid == -1)
{
printf("create process failed\n");
return -1;
}
else if(pid > 0)
{
printf("parent process pid is %d\n",getpid());
}
else if(pid == 0)
{
printf("child process pid is %d ppid is %d\n",getpid(),getppid());
}
for(i = 0;i<4;i++)
{
i++;
printf("i = %d\n",i);
}
return 0;
}