目录
前驱图
程序的执行
顺序执行
并发执行
进程的定义
进程的状态
总结
前驱图
现在有两个任务分别为p1,p2; 只有执行了p1,才可以执行p2,此时可以称p1为p2的前驱。通过符号语言表示如下:
p1->p2
程序的执行
下面引进一段代码来理解进程的概念,代码语句编号
编号 | 代码 |
1 | printf("The process id = %d\n", pid); |
2 | printf("Hello from child process: %d\n", getpid()); |
3 | printf("Hello from father process: %d\n", getpid()); |
fork()
Clone the calling process, creating an exact copy.
Return -1 for errors, 0 to the new process,
and the process ID of the new process to the old process.
顺序执行
2/single_process.c
#include "stdio.h"
#include "unistd.h"
void main() {
int pid = getpid();
printf("The process id = %d\n", pid);
if(pid == -1) {
perror("fork error!");
} else if(pid == 0){
printf("Hello from child process: %d\n", getpid());
} else {
printf("Hello from father process: %d\n", getpid());
}
}
The process id = 62148
Hello from father process: 62148
由于是顺序执行,且只有一个进程,进程的执行过程为:
进程前驱图 | p主->p1 |
代码语句前驱图 | A1->A3 |
注:单个进程的代码中,调用或者说进入这个进程的前一个进程成为p主,本进程标记为p1,用A来表示。
并发执行
2/multiple_process.c
#include "stdio.h"
#include "unistd.h"
void main() {
int pid = getpid();
printf("The process id = %d\n", pid);
if(pid == -1) {
perror("fork error!");
} else if(pid == 0){
printf("Hello from child process: %d\n", getpid());
} else {
printf("Hello from father process: %d\n", getpid());
}
}
The process id = 62397
Hello from father process: 62386
The process id = 0
Hello from child process: 62397
进程的执行顺序为:
进程前驱图 | p主->p1->p2->p1->p0->p2 |
代码语句前驱图 | A1->A3->B1->B2 |
进程的定义
程序的一次执行
struct task_struct{
...
unsigned short uid;
int pid;
int processor;
...
volatile long state;
long prority;
unsighed long rt_prority;
long counter;
unsigned long flags;
unsigned long policy;
...
Struct task_struct *next_task, *prev_task;
Struct task_struct *next_run,*prev_run;
Struct task_struct *p_opptr,*p_pptr,*p_cptr,*pysptr,*p_ptr;
...
};
Linux系统的PCB包括很多参数,每个PCB约占1KB多的内存空间。用于表示PCB的结构task_struct简要描述如下:
下面对部分数据成员进行说明:
(1)unsigned short pid 为用户标识
(2)int pid 为进程标识
(3)int processor标识用户正在使用的CPU,以支持对称多处理机方式;
(4)volatile long state 标识进程的状态,可为下列六种状态之一:
可运行状态(TASK-RUNING);
可中断阻塞状态(TASK-UBERRUPTIBLE)
不可中断阻塞状态(TASK-UNINTERRUPTIBLE)
僵死状态(TASK-ZOMBLE)
暂停态(TASK_STOPPED)
交换态(TASK_SWAPPING)
(5)long prority表示进程的优先级
(6)unsigned long rt_prority 表示实时进程的优先级,对于普通进程无效
(7)long counter 为进程动态优先级计数器,用于进程轮转调度算法
(8)unsigned long policy 表示进程调度策略,其值为下列三种情况之一:
SCHED_OTHER(值为0)对应普通进程优先级轮转法(round robin)
SCHED_FIFO(值为1)对应实时进程先来先服务算法;
SCHED_RR(值为2)对应实时进程优先级轮转法
(9)struct task_struct *next_task,*prev_task为进程PCB双向链表的前后项指针
(10)struct task_struct *next_run,*prev_run为就绪队列双向链表的前后项指针
(11)struct task_struct *p_opptr,*p_pptr,*p_cptr,*p_ysptr,*p_ptr指明进程家族间的关系,分别为指向祖父进程、父进程、子进程以及新老进程的指针。
进程的状态
(4)volatile long state
标识进程的状态,可为下列六种状态之一:
可运行状态 | TASK-RUNING | 执行 |
可中断阻塞状态 | TASK-UBERRUPTIBLE | 中断 |
不可中断阻塞状态 | TASK-UNINTERRUPTIBLE | 中断 |
僵死状态 | TASK-ZOMBLE | 终止 |
暂停态 | TASK_STOPPED | 就绪 |
交换态 | TASK_SWAPPING | 创建 |
2/single_process.c
#include "stdio.h"
#include "unistd.h"
void main() {
int pid = getpid();
printf("The process id = %d\n", pid);
if(pid == -1) {
perror("fork error!");
} else if(pid == 0){
printf("Hello from child process: %d\n", getpid());
} else {
printf("Hello from father process: %d\n", getpid());
}
return;
}
以以上代码为例,printf一次可以看作一次I/O请求。
那这段程序执行的过程的进程状态改变如下:
编号 | 代码 |
创建->就绪 | |
执行 | int pid = getpid(); |
阻塞 | printf("The process id = %d\n", pid); |
就绪 | |
执行 | if(pid == -1) { |
终止 | return; |
总结
本文从进程的执行,进程的定义和进程的状态三个方面通过程序来阐述了一些概念。