进程控制
1,什么是进程
进程是可并发执行的程序,是一个在数据集合上的运行进程
当一个程序开始执行后,在开始执行到执行结束的这段时间里,它内存中的部分被称为进程
通俗讲:程序就是在硬盘上的可执行文件
进程就是在执行中的程序
2,什么是并发
即多个进程同时运行,多个任务同时执行
3,虚拟内存
Linux虚拟内存管理技术:
物理内存:实际在处理器中的内存模块 几百M
将硬盘中的一部分存储单元来当做内存使用 4个G (受操作系统的寻址范围影响)
0x000000——0xffffff
操作系统:用户空间和内核空间
内核空间:高地址 1g
用户空间:低地址 3g
虚拟内存管理技术的好处:
1,有效防止内核空间被破坏
2,防止被恶意窥探(作为对硬盘的映射,)
3,不会因为拿走硬盘被发现数据
虚拟地址的组成:物理地址+偏移量(rel)
4,拓展内存空间
4,进程的分类
1,守护进程
2,批处理进程
3,交互进程
5,进程的属性
进程的ID(PID进程号):是唯一的属性,用来区分进程
父进程的ID(PPID)
启动进程的用户ID:UID
进程的状态:运行R,休眠S,僵尸进程Z,死掉的进程X,暂停状态T
进程优先级
进程占用资源的大小(内存,CPU)
6,进程控制模板PCB:数据结构
进程号:ps命令查看Linux系统中的进程 (ps -命令)
- l:长格式输出
- u:接用户名和启动时间的顺序来显示进程
- f:用树状格式来显示进程
- a:显示所有用户的所有进程
- x:显示无控制终端进程
%CPU是占用CPU的大小
%MEM是占用内存的多少
STAT是进程的状态
TIME:进程消耗时间
杀死命令:kill
kill +进程号(PID)
kill +进程名 -9:强制终止
pkill :pkill +程序名
xkill:在桌面上杀死图像化界面
renice:改变进程的优先级,通过改变进程ID(PID)来改变谦让度,进而达到改变进程的优先级
renice 谦让度 PID
7,进程的状态转换
(1)就绪:当进程已分配到除CPU以外所有必要资源,只要获得处理器就可以立即执行
(2)执行:已经获取处理器,其程序正在处理器上执行
(3)阻塞:正在执行的进程,由于等待某个事件的发生而无法执行时,便放弃处理机会而处于阻塞状态
并发的本质:时间片轮询
8,Linux进程调度
1,FCFS也叫FIFO,先来先处理;缺点:对于短的任务可能变得非常缓慢
2,时间片轮巡算法:周期性的切换总体时长比FIFO短;缺点:过多的短任务会使大量时间耗费在切换任务上
3,STCF:
短任务优先算法
抢占式和非抢占式 缺点:长任务很难拿到CPU资源
4,银行家算法
9,创建一个进程
fork()函数
有两个返回值 0:子进程 -1:失败 >0:父进程
头文件:
#include “unistd.h”
函数原型:
pid_t fork(void);
有两个返回值:
#include "stdio.h"
#include "sys/types.h"
#include "unistd.h"
#include "stdlib.h"
//fork()函数,有两个返回值,分别为子进程与父进程,子进程返回0,父进程返回>0,创建失败返回<0
//使用fork()函数创建进程的过程中,子进程与父进程为竞争关系,没有固定执行顺序
int main()
{
pid_t pid = fork();
if (pid < 0)
{
perror("fork");
exit(1);//退出当前程序,返回括号内值
}
if (0 == pid)
{
printf("this is child process.\n");
}
else
{
printf("this is father process.\n");
}
return 0;
}
getpid:获取当前进程号
getppid:获取当前父进程号
获取进程号和父进程号
#include "stdio.h"
#include "stdlib.h"
#include "unistd.h"
#include "sys/types.h"
int main()
{
pid_t pid = fork();
if (pid < 0)
{
perror("fork");
exit(1);//退出当前程序,返回括号内值
}
if (0 == pid)
{
printf("this is child process.\npid:%d\tppid:%d\n",getpid(),getppid());
}
//getpid() 返回当前进程号
//getppid() 返回当前进程的父进程号
else
{
printf("this is father process.\npid:%d\tppid:%d\n",getpid(),getppid());//正常情况下,子进程的父进程号是父进程获取到的当前进程号
}
return 0;
}
fork函数运行之后,子进程会复制父进程的堆栈数据空间
父进程与子进程跑在不同的内存空间中:父进程与子进程有自己的独立的内存空间
#include "stdio.h"
#include "sys/types.h"
#include "unistd.h"
#include "stdlib.h"
//fork()函数,有两个返回值,分别为子进程与父进程,子进程返回0,父进程返回>0,创建失败返回<0
//使用fork()函数创建进程的过程中,子进程与父进程为竞争关系,没有固定执行顺序
int main()
{
int i = 4;//用作证明子进程与父进程内的数据存储相互独立
pid_t pid = fork();
if (pid < 0)
{
perror("fork");
exit(1);//退出当前程序,返回括号内值
}
if (0 == pid)
{
i -= 1;
printf("this is child process.\n");
printf("i=i-1=%d\n", i);
}
else
{
i *= 5;
printf("this is father process.\n");
printf("i=i*5=%d\n", i);
}
return 0;
}
早期:fork函数运行之后,子进程会复制父进程的堆栈数据空间
优化:读时不管,写时复制
父进程子进程所用参数地址相同:
//输出所用参数的地址
#include"stdio.h"
#include"sys/types.h"
#include"unistd.h"
#include"stdlib.h"
int main()
{
int a=5;
int b=100;
pid_t pid =fork();
if(-1 ==pid)
{
perror("fork error!");
exit(1);
}
if (0 == pid)
{
a=a*2;
printf("this is child: a=%d a addr:%x b=%d b addr:%x \n",a,&a,b,&b);
}
else
{
a =a-1;
printf("this is father: a=%d a addr:%x b=%d b addr:%x \n",a,&a,b,&b);
}
}
fork函数创建的父子进程关系是竞争关系,不能判断是谁先动
#include "stdio.h"
#include "sys/types.h"
#include "unistd.h"
#include "stdlib.h"
//fork()函数,有两个返回值,分别为子进程与父进程,子进程返回0,父进程返回>0,创建失败返回<0
//使用fork()函数创建进程的过程中,子进程与父进程为竞争关系,没有固定执行顺序
int main()
{
int i = 0;//用作证明子进程与父进程的竞争关系
pid_t pid = fork();
if (pid < 0)
{
perror("fork");
exit(1);
}
if (0 == pid)
{
for (i = 0; i < 5;i++)
{
printf("this is child process.\n");
sleep(2);
}
}
else
{
for (i = 0; i < 5;i++)
{
printf("this is father process.\n");
sleep(2);
}
}
return 0;
}
得到的结果就是不能判断谁更快一点。
vfork()函数
创建一个进程
1,保证子进程先执行
//子进程先动
#include"stdio.h"
#include"sys/types.h"
#include"unistd.h"
#include"stdlib.h"
int main()
{
int i=0;
pid_t pid=vfork();
if(-1 == pid)
{
perror("fprk error");
exit(1);
}
if (0 == pid)
{
for(i=0;i<5;i++)
{
printf("child\n");
sleep(2);
}
}
else
{
for(i=0;i<5;i++)
{
printf("father\n");
sleep(2);
}
}
}
2,当子进程调用exit()函数后,父进程往下执行
3,不会继承父进程的页面
eg1:
1,创建两条进程,一条输出A,一条输出B,交替输出ABABABABAB
#include"stdio.h"
#include"sys/types.h"
#include"unistd.h"
#include"stdlib.h"
int main()
{
int i=0;
pid_t pid=vfork();
if(-1 == pid)
{
perror("fprk error");
exit(1);
}
for(i=0;i<5;i++)
{
if (0 == pid)
{
printf("A\n");
pid =1;
}
else
{
printf("B\n");
pid =0;
}
}
exit(0);
}
eg2
三条进程,ABC交替输出
#include"stdio.h"
#include"sys/types.h"
#include"unistd.h"
#include"stdlib.h"
int main()
{
int i=0;
for(i=0;i<5;i++)
{
pid_t pid =vfork();
if(-1 == pid)
{
perror("fprk error");
exit(1);
}
if(0 == pid)
{
printf("A\n");
exit(1);
}
else
{int pit =vfork();
if(-1 ==pit)
{
perror("fork error!");
exit(1);
}
if(0 == pit)
{
printf("B\n");
exit(1);
}
else
{
printf("C\n");
}
}
}
}
eg3
三条进程,ABC交替打印
(我这里认为是输入到文件的意思)
#include"stdio.h"
#include"sys/types.h"
#include"unistd.h"
#include"stdlib.h"
int main()
{
int i=0;
FILE *fp;
fp =fopen("./text.txt","w+");
for(i=0;i<5;i++)
{
pid_t pid =vfork();
if(-1 == pid)
{
perror("fprk error");
exit(1);
}
if(0 == pid)
{
fputs("A",fp);
exit(1);
}
else
{int pit =vfork();
if(-1 ==pit)
{
perror("fork error!");
exit(1);
}
if(0 == pit)
{
fputs("B",fp);
exit(1);
}
else
{
fputs("C",fp);
}
}
}
fclose(fp);
}