IT评测·应用市场-qidao123.com技术社区

标题: 操作系统 :进程概念 [打印本页]

作者: 渣渣兔    时间: 2025-4-3 08:20
标题: 操作系统 :进程概念
操作系统 :进程概念

弁言

理解进程的概念不但有助于我们掌握操作系统的工作原理,还能为后续学习多任务处置处罚、并发编程、内存管理等高级主题奠定结实的基础。本文将深入探讨进程的方方面面,包括其根本概念、状态管理、优先级调度、地址空间等焦点内容,并联合实际示例和代码分析,帮助读者构建完备的知识体系。


  
1. 冯诺依曼体系布局


关于冯诺依曼必须要强调的几点:


2. 操作系统概念及定位


操作系统是任何计算机系统都包含的根本步伐聚集,操作系统也是一款进行软硬件管理的软件。


对上,为用户步伐提供一个良好的执行环境。

对下,与硬件交互,管理全部的软硬件资源(手段)
小知识:
   
  管理
   管理者和被管理者不见面,管理者是根据有中心层获取的“数据”进行管理。
  管理方式就是“先描述在组织”——描述被管理的对象,组织被管理对象。
  举例:校长管理门生就可以转化为校长对于execl表格中数据的管理。
  

3. 进程

3.1 进程的根本概念与操作




3.2 进程的状态



3.3 进程的优先级



3.4 进程的切换

CPU上下文切换:其实际寄义是任务切换, 或者CPU寄存器切换。当多任务内核决定运行另外的任务时, 它生存正在运行任务的当前状态, 也就是CPU寄存器(CPU内部的临时空间)中的全部内容。这些内容被生存在任务自己的堆栈中, 入栈工作完成后就把下一个将要运行的任务的当前状况从该任务的栈中重新装⼊CPU寄存器,并开始下⼀个任务的运行, 这⼀过程就是context switch。

死循环进程不会使系统瓦解,因为时间片进程不会一直占据CPU去运行。
进程自己的上下文数据是生存在test_struct中的TSS:任务状态段。


4. 环境变量

4.1 根本概念



4.2 常见的环境变量



4.3 关于环境变量的下令



4.4 通过代码获取环境变量


4.5 bash的两张表



5. 步伐地址空间

步伐地址空间并不是真正的内存
5.1 虚拟地址

  1. #include <stdio.h>
  2. #include <unistd.h>
  3. #include <stdlib.h>
  4. int g_val = 0;
  5. int main()
  6. {
  7.         pid_t id = fork();
  8.         if(id < 0){
  9.                 perror("fork");
  10.                 return 0;
  11.         }
  12.         else if(id == 0){ //child,⼦进程肯定先跑完,也就是⼦进程先修改,完成之后,⽗进程再读取
  13.                 g_val=100;
  14.                 printf("child[%d]: %d : %p\n", getpid(), g_val, &g_val);
  15.         }else{ //parent
  16.                 sleep(3);
  17.                 printf("parent[%d]: %d : %p\n", getpid(), g_val, &g_val);
  18.         }
  19.         sleep(1);
  20.         return 0;
  21. }
复制代码
输出结果:
  1. child[3046]: 100 : 0x80497e8
  2. parent[3045]: 0 : 0x80497e8
复制代码
根据上边的代码我们可以看出,父子进程的输出地址是一致的,但是变量内容却不一样。
结论:
   
  
5.2 进程地址空间(紧张)




5.3 虚拟内存管理第一讲

描述Linux下进程的地址空间的全部的信息的布局体是 mm_struct(内存描述符)。每个进程只有⼀个mm_struct布局,在每个进程的task_struct布局中,有⼀个指向该进程的布局。
  1. struct task_struct
  2. {
  3.         /*...*/
  4.         struct mm_struct *mm; //对于普通的⽤⼾进程来说该字段指向他的虚拟地址空间的⽤⼾空间部分,对于内核线程来说这部分为NULL。
  5.         struct mm_struct *active_mm; // 该字段是内核线程使⽤的。当该进程是内核线程时,它的mm字段为NULL,表⽰没有内存地址空间,可也并不是真正的没有,这是因为所有进程关于内核的映射都是⼀样的,内核线程可以使⽤任意进程的地址空间。
  6.         /*...*/
  7. }
复制代码
可以说,mm_struct布局是对整个用户空间的描述。每⼀个进程都会有自己独立的mm_struct,这样每⼀个进程都会有⾃⼰独⽴的地址空间才气互不⼲扰。先来看看由task_struct到mm_struct,进程的地址空间的分布环境:

  1. struct mm_struct
  2. {
  3.         /*...*/
  4.         struct vm_area_struct *mmap; /* 指向虚拟区间(VMA)链表 */
  5.         struct rb_root mm_rb; /* red_black树 */
  6.         unsigned long task_size; /*具有该结构体的进程的虚拟地址空间的⼤⼩*/
  7.         /*...*/
  8.         // 代码段、数据段、堆栈段、参数段及环境段的起始和结束地址。
  9.         unsigned long start_code, end_code, start_data, end_data;
  10.         unsigned long start_brk, brk, start_stack;
  11.         unsigned long arg_start, arg_end, env_start, env_end;
  12.         /*...*/
  13. }
复制代码
那既然每⼀个进程都会有⾃⼰独⽴的mm_struct,操作系统肯定是要将这么多进程的mm_struct组织起来的!虚拟空间的组织⽅式有两种:
Linux内核利用 vm_area_struct 布局来表示一个独⽴的虚拟内存地区(VMA),由于每个差别质的虚拟内存地区功能和内部机制都差别,因此⼀个进程利用多个vm_area_struct布局来分别表示差别范例的虚拟内存地区。上面提到的两种组织⽅式使⽤的就是vm_area_struct布局来连接各个VMA,方便进程快速访问。
  1. struct vm_area_struct {
  2.         unsigned long vm_start; //虚存区起始
  3.         unsigned long vm_end; //虚存区结束
  4.         struct vm_area_struct *vm_next, *vm_prev; //前后指针
  5.         struct rb_node vm_rb; //红⿊树中的位置
  6.         unsigned long rb_subtree_gap;
  7.         struct mm_struct *vm_mm; //所属的 mm_struct
  8.         pgprot_t vm_page_prot;
  9.         unsigned long vm_flags; //标志位
  10.         struct {
  11.                 struct rb_node rb;
  12.                 unsigned long rb_subtree_last;
  13.         } shared;
  14.         struct list_head anon_vma_chain;
  15.         struct anon_vma *anon_vma;
  16.         const struct vm_operations_struct *vm_ops; //vma对应的实际操作
  17.         unsigned long vm_pgoff; //⽂件映射偏移量
  18.         struct file * vm_file; //映射的⽂件
  19.         void * vm_private_data; //私有数据
  20.         atomic_long_t swap_readahead_info;
  21.         #ifndef CONFIG_MMU
  22.         struct vm_region *vm_region; /* NOMMU mapping region */
  23.         #endif
  24.         #ifdef CONFIG_NUMA
  25.         struct mempolicy *vm_policy; /* NUMA policy for the VMA */
  26.         #endif
  27.         struct vm_userfaultfd_ctx vm_userfaultfd_ctx;
  28. } __randomize_layout;
复制代码



5.4 为什么要有虚拟内存空间

亦或是如果步伐直接可以操作物理内存会造成什么问题?
   在早期的计算机中,要运行⼀个步伐,会把这些步伐全都装⼊内存,步伐都是直接运⾏在内存上的,也就是说步伐中访问的内存地址都是实际的物理内存地址。当计算机同时运行多个步伐时,必须包管这些步伐用到的内存总量要小于计算机实际物理内存的大小。
  那当步伐同时运行多个步伐时,操作系统是怎样为这些步伐分配内存的呢?例如某台计算机总的内存大小是128M,现在同时运⾏两个步伐A和B,A需占⽤内存10M,B需占⽤内存110。计算机在给步伐分配内存时会接纳这样的⽅法:先将内存中的前10M分配给步伐A,接着再从内存中剩余的118M中划分出110M分配给步伐B。
  这种分配方法可以包管步伐A和步伐B都能运行,但是这种简朴的内存分配计谋问题许多。
  比如:
     
    有了虚拟地址空间和分⻚机制就能办理了
   地址空间和⻚表是OS创建并维护的!也就意味着,凡是想利用地址空间和⻚表进⾏映射,也⼀定要在OS的羁系之下来进⾏访问!!也趁便保护了物理内存中的全部的合法数据 ,包括各个进程以及内核的相干有效数据。
  因为有地址空间的存在和⻚表的映射的存在,我们的物理内存中可以对未来的数据进⾏恣意位置的加载!物理内存的分配 和 进程的管理就可以做到没有关系,进程管理模块和内存管理模块就完成相识耦合
  因为有地址空间的存在,以是我们在C、C++语⾔上new, malloc空间的时候,其实是在地址空间上申请的,物理内存甚⾄可以⼀个字节都不给你。而当你真正进⾏对物理地址空间访问的时候,才执⾏内存的相干管理算法,帮你申请内存,构建⻚表映射关系(延迟分配),这是由操作系统⾃动完成,用户包括进程完全零感知!!
  因为页表的映射的存在,步伐在物理内存中理论上就可以恣意位置加载。它可以将地址空间上的虚拟地址和物理地址进⾏映射,在 进程视⻆全部的内存分布都可以是有序 的。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 IT评测·应用市场-qidao123.com技术社区 (https://dis.qidao123.com/) Powered by Discuz! X3.4