思维导图:
一.进程
1.进程可以做什么
1.进程就是正在执行的程序,起到多个程序同时执行(cpu以ms级别的速度来回切换)
2.qq的多个聊天框
3.可以使用一个程序中的多个死循环同时执行
2.进程的概念
进程:指程序的运行过程,是资源分配和调度的独立单元
3.程序和进程的区别
进程:指程序的运行过程,是资源分配和调度的独立单元
进程:指程序的运行过程,是资源分配和调度的独立单元
4.进程的调度机制
进程的调用: CPU时间片轮询机制。CPU以ms级别的速度在多个进程或线程之间来回切换
5.进程是资源分配的最小单位
进程的资源包含:
1.CPU资源
2.内存资源
管理虚拟内存,映射到物理内存
分配文件描述符表
3.pcb资源(记录进程的一些信息)
6.进程的五态图
7.虚拟内存和物理内存
物理内存:真实的内存条上物理内存,存储运行的数据
虚拟内存:管理虚拟内存时,会应映射在物理内存上 (因为物理内存大小不一,不方便管理,所以使用虚拟内存规划)
1.每个进程创建时,都会申请4G 的虚拟内存地址
2.0G-3G是用户空间,这个空间每个进程相互独立
3.3G-4G之间是内核空间,多个进程共享
5.虚拟内存空间大小由操作系统决定
如果指针是4字节,则操作系统32位操作系统,虚拟内存大小4G
如果指针是8字节,则操作系统64位操作系统,一般取48位 2^48----->256TB
8.虚拟内存划分
9.进程的标识
pid:process id当前进程号,是进程的唯一标识,本质上就是一个大于等于0的数,当创建进程时,系统自动分配。
ppid:父进程id
pgid:进程组号 , 一个进程组是由多个进程组成的,当创建一个进程时,默认继承父进程的进程组号。
sid:会话id,一个会话是由多个进程组组成的,当创建一个新进程组时,默认继承父进程的会话id
10.特殊进程
pid 0 idel进程,引导进程,当操作做系统启动后,启动0号进程,创建1号 2号进程
pid 1 init进程,用于内核初始化,用户回收孤儿进程(没有父进程)
pid 2 kthread进程,用于进程调度,称为调度器进程
练习
使用父子进程实现一个图片的拷贝
要求父进程拷贝前一部分
子进程拷贝后一部分
#include <head1.h>
int main(int argc, const char *argv[])
{
// 打开源文件和目标文件
FILE *src = fopen("xiaoxin.bpm", "rb");
if (src == NULL) {
perror("打开源文件失败");
return -1;
}
FILE *dest = fopen("xiaoxin.bpm", "wb");
if (dest == NULL) {
perror("打开目标文件失败");
fclose(src);
return -1;
}
// 获取文件总大小
fseek(src, 0, SEEK_END);
long file_size = ftell(src);
rewind(src); // 将指针重置到文件开头
// 计算父子进程各自拷贝的区域
long half_size = file_size / 2;
// 创建子进程
pid_t pid = fork();
if (pid < 0)
{
perror("fork失败");
fclose(src);
fclose(dest);
return -1;
}
if (pid == 0) {
// 子进程:拷贝文件的后半部分
FILE *src_child = fopen("xiaoxin.bpm", "rb");
FILE *dest_child = fopen("xiaoxin.bpm", "rb+"); // 打开目标文件以读写模式
if (src_child == NULL || dest_child == NULL) {
perror("子进程文件打开失败");
exit(-1);
}
fseek(src_child, half_size, SEEK_SET); // 定位到文件的后半部分
fseek(dest_child, half_size, SEEK_SET); // 定位目标文件的后半部分
char buf[128] = {0};
size_t n;
while ((n = fread(buf, 1, sizeof(buf), src_child)) > 0) {
if (fwrite(buf, 1, n, dest_child) != n) {
perror("子进程写入失败");
fclose(src_child);
fclose(dest_child);
exit(-1);
}
}
printf("子进程完成文件后半部分的拷贝。\n");
fclose(src_child);
fclose(dest_child);
exit(0);
}
else
{
// 父进程:拷贝文件的前半部分
char buf[128]={0};
while (fread(buf,sizeof(buf),1, src)!=0)
{
if (fwrite(buf, sizeof(buf), 1, dest) ==0)
{
perror("父进程写入失败");
fclose(src);
fclose(dest);
return -1;
}
if(ftell(src)>half_size)
{
break;
}
}
printf("父进程完成文件前半部分的拷贝。\n");
// 等待子进程完成
waitpid(pid, NULL, 0);
// 关闭文件
fclose(src);
fclose(dest);
}
return 0;
}