标题:进程控制
1什么是进程:进程是可并发执行的程序,是一个在数据集合上运行的过程
当一个程序开始执行后,在开始执行结束的这段时间里,它内存中的部分被称为进程。
通俗讲:程序:在硬盘上可执行的文件
进程:在执行中程序
2.什么是并发
3.多进程同时执行,多个任务同时执行。
Linux虚拟内存管理技术
物理内存:实际在处理器中的内存模块 几百M
将硬盘中的一部分存储单元拿来当内存用 4g(受操纵系统的寻址范围影响)0x00000000-0-ffffffff
操纵系统:内核空间:高地址 1g
用户空间:低地址:3g
好处:1,有效防止内核空间被破坏 2 防止被恶意窥探 3拓展内存空间。
4进程的分类
1,守护进程
2,批处理进程
3,交互进程
5进程的属性
进程ID(PID):是唯一的数值,用来区分进程
父进程的ID(PPID)
启动进程的用户ID(UID)
进程的状态:运行R 休眠S 僵尸进程Z
进程优先级
进程占用资源大小(内存,cpu)
6进程控制模块PCB:数据结构
进程号:ps命令查看Linux系统的进程
1,长格式输出
u:按用户名和启动时间的顺序来显示进程 ps -u
f:用树状格式来显示进程
a:显示所有用户的所有进程
x:显示无控制终端进程
ps -aux | grep +可执行文件名 查询
MEM 占用内存的百分比
Cpu 占用内存的百分比
VSZ 进程的虚拟大小
Stat 进程状态
START 启动进程的时间
Time 进程消耗cpu的时间
+位于后台的进程组
kill 杀死命令 kill+进程号 kill -9 进程号 强制终止
pkill:pkill +程序名
xkill:在桌面上杀死图像化界面
renice:改变进程的优先级,通过改变进程ID(PID)来改变谦让度,进而达到进程的优先级。
renice 谦让度 PID
7进程的状态转换
(1)就绪:当进程已分配到除cpu以外的所有必要资源,只要获得处理器就可以执行
(2)执行:已经获取处理器,其程序正在处理器上执行
(3)阻塞:正在执行的进程,由于等待某个事件而无法执行时,便放弃处理机会而处于阻塞状态。
并发的本质:时间片的轮巡。
8、linux进程调度
1FCFS也叫FIFO。先来先处理
2时间片轮巡法:周期性的切换总体时常比FIFO短,
3 STCF:短任务优先算法
抢占式和非抢占式:
4、银行家算法
9创建一个进程
fork()函数:它是有两个返回值 0 :子进程 - 1:失败 父进程:>0
getpid():获取当前进程号
getppid(); 获取当前父进程号
父进程与子进程跑在不同的内存空间中:父进程与子进程有自己独立的内存空间;
早期:fork函数运行之后,子进程会复制父进程的堆栈数据空间。
优化:读时不管,写时复制。
fork函数创建的父子进程关系时竞争关系,不能判断是谁先动
Vfork():创建一个进程
1保证子进程先动
2当子进程调用exit();函数后,父进程往下执行
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<stdlib.h>
int main()
{
pid_t pid = fork();
if(-1==pid)
{
perror("fork error");
exit(1);
}
if(0 == pid)
{
printf("this is child:pid:%d ppid=%d\n",getpid(),getppid());
}
else
{
printf("this is father pid:%d\n",getpid());
}
return 0;
}
Eg:创建两条进度,一条输出A,一条输出B,交替输出ABABABABABABA
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
int i=0;
for ( i = 0; i < 10; i++)
{
pid_t pid = vfork();
if(-1==pid)
{
perror("error");
exit(1);
}
if (pid == 0)
{
printf("A\n");
exit(1);
}
else
{
printf("B\n");
}
}
}
Eg:创建三条线程交替输出ABC
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
int i=0;
for ( i = 0; i < 4; i++)
{
pid_t pid1 = vfork();
if(-1==pid1)
{
perror("error");
exit(1);
}
if (pid1 == 0)
{
pid_t pid2=vfork();
if(-1==pid2)
{
perror("error");
}
if(pid2==0)
{
printf("A\n");
}
else
{
printf("B\n");
}
exit(1);
}
else
{
printf("C\n");
}
}
}
Eg:创建三条线程交替答应ABC
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
int main()
{
int i=0;
for ( i = 0; i < 4; i++)
{
pid_t pid1 = vfork();
if(-1==pid1)
{
perror("error");
exit(1);
}
if (pid1 == 0)
{
pid_t pid2=vfork();
if(-1==pid2)
{
perror("error");
}
if(pid2==0)
{
printf("child pid A=%d\n",getpid());
}
else
{
printf("child's ppid B=%d\n",getppid());
}
exit(1);
}
else
{
printf("father ppid C=%d\n",getppid());
}
}
}
多进程优点:
对用户来说:每个进程互相独立,不影响主程序的稳定性,子进程崩溃没关系;
通过增加CPU,就可以容易扩充性能;
对开发者来说:更容易进行内存的读取和写入。
缺点:
多任务实现开销较大
编写能够与其他进程通信或者能够对其它进程操作的应用程序将要困难很多。
wait函数
1、wait函数:将当前进程挂起,等待信号来临,再继续运行,
用来等待子进程结束。
pid_t wait(int *wststus);
WEXITSTATUS:宏定义:返回子进程的特殊状态
#include<stdio.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
int main()
{
int i = 0;
int status;
pid_t pid = fork();
if(-1 == pid)
{
perror("error");
exit(1);
}
if(0==pid)
{
printf("child\n");
exit(5);
}
else
{
pid=wait(&status);
int c=WEXITSTATUS(status);
printf("father pid = %d %d\n",pid,c);
}
}
2、waitpid:它可以指定等待的进程号
pid_t waitpid(pid_t pid, int *wstatus, int options);
else
{
pid=waitpid(pid,&status,0);
int c=WEXITSTATUS(status);
printf(“father pid = %d %d\n”,pid,c);
}
}
僵尸进程
产生原因:当进程走完自己的生命周期之后,会执行自己的系统调用exit(9)函数,然后内存被释放,没有执行代码。但是在进程表里仍留下信息(pid退出信息),直到父进程将他们回收。
避免:wait函数