概念
进程与程序的区别
进程:一个正在运行的代码就叫做进程,是动态的,会占用内存
程序:一段封装好的待运行的代码或可执行文件,是静态的,会占用磁盘空间
单道与多道程序
单道:程序一个一个排好队,一个一个执行,若代码A阻塞,则代码B不能立即执行,需等待代码A执行结束代码B才会执行
多道:程序之间相互独立,各个程序之间同时执行,各执行各的,互不影响,它们在系统管理程序控制下,相互穿插执行(并行,并发)
并行与并发的区别
并行:有多个核,一个程序对应一个核,同时执行程序
并发:有一个核,多个程序对应一个核,程序之间按顺序相互交替执行,在宏观上也是并行。
进程控制块(PCB)了解
进程运行时,内核为每一个进程分配一个PCB(进程控制块),维护进程的相关信息,linux中的进程控制块是task_struct控制块
task_struct控制块

进程号
概念:
每一个进程都是由一个进程号来标识,其类型是pid_t,进程号范围是0~32767。进程号是唯一的,但是进程号是可以重复使用的(前提是当前程序1抢得cpu处理权后,执行1的代码,当1代码执行结束后,会释放该进程号,这时其他进程就可以使用该进程号)。
PID 进程号
PPID 父进程号
PGID 进程组号
获取进程id
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
pid_t getpid(void);
功能:获取当前进程号
参数:无
返回值:本进程号 (失败-1)
获取进程的父进程id
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
pid_t getppid(void);
功能:获取调用此函数进程的父进程id(ppid)
参数:无
返回值:调用此函数进程的父进程id(ppid)
获取组进程号
#include <unistd.h>
#include <sys/types.h>
pid_t getpgid(pid_t pid);
功能:获取当前组进程号,也就是同组进程中第一个进程的进程号
参数:pid 进程号
返回值:当前组进程号,也就是同组进程中第一个进程的进程号
创建进程fork
概念:
父子进程
系统允许一个进程创建新进程。此新进程就是子进程,这就是创建的父子进程。
int x = fork();
函数:
#include <unistd.h>
#include <sys/types.h>
pid_t fork(void);
功能:用于进程创建一个新进程,该新进程就是该进程的子进程,原进程被称为父进程。
参数:无
返回值:
成功:子进程返回0,父进程返回子进程id。getpid pid_t为整型。
失败:返回-1
注意:
fork创建失败的两个主要原因:
1.当前进程数已到达了系统规定的最大上限数,这时的errno的值被设为EAGAIN。
2.系统内存不足,这时errno的值被设为ENOM。
注意:
子进程会在fork函数后开始执行
示例一:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char const *argv[])
{
printf("啦啦啦\n");
int id = fork();
if(id < 0)
{
printf("子进程创建失败id:%d\n",id);
}
else if(id > 0)
{
printf("父进程的进程号是:%d\n,子进程的进程号是:%d\n",getpid(),id);
}
else if(id == 0)
{
printf("父进程的进程号是:%d\n,创建的子进程的进程号是:%d\n,创建的id:%d\n",getppid(),getpid(),id);
}
printf("德玛西亚\n");
while(1);
return 0;
}
父子进程关系
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char const *argv[])
{
printf("啦啦啦\n");
int id = fork();
printf("德玛西亚\n");
while(1);
return 0;
}
示例2:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main(int argc, char const *argv[])
{
printf("啦啦啦");//没有\n所以啦啦啦在缓冲区
int x = fork();
printf("德玛西亚\n");
while(1);
return 0;
}
啦啦啦在缓冲区,所以父进程打印不出来“啦啦啦”,当子进程执行时\n才会将父进程中的“啦啦啦”冲刷出来,和“德玛西亚“拼接起来一起打印,打印两遍。
分析:
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
int main(int argc, char *argv[])
{
//printf是库函数有缓冲区 hello world先放入缓冲区 被子进程复制了一份
printf("hello world1");
//write是系统调用 直接将字符串 写入1号文件 没有缓冲区 不被子进程复制
//0,输入
//1,输出
//2,错误输出
write(1,"hello world2",12);
//创建子进程
pid_t pid = fork();
return 0;
}
进程状态
分类:

进程资源回收
概述:
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
int main(int argc, char const *argv[])
{
int x = fork();
if(x < 0)
{
printf("创建失败\n");
}
else if(x == 0)
{
for(int i = 0;i < 10; i++)
{
printf("子进程正在进行第%d次执行",getpid(),i);
sleep(1);
}
}
else if(x > 0)
{
printf("父进程正在等待子进程结束\n");
wait(NULL);
printf("父进程已回收子进程%u\n",x);
}
return 0;
}