程序、进程、线程

我不是女神ヾ 2022-11-03 00:44 205阅读 0赞

目录

  • 程序空间分配
  • 进程
    • 进程内存分配
    • PCB和进程
      • PCB包括
      • 进程状态
    • 程序和进程的区别
    • 程序运行成为进程的过程
  • 线程
    • 进程和线程的区别
  • 参考材料

程序空间分配

站在高级语言的角度,根据APUE(Advanced Programming in the UNIX Environment UNIX环境高级编程),一个程序分为如下段:

  1. text:代码段,可执行指令的集合,在内存中被映射为只读,存放代码和常量
  2. data:初始化后数据的集合,存放在memory的可写空间内,存放已初始化的全局变量、静态变量、局部静态变量。
  3. bss:全局未初始化变量、静态未初始化变量的集合,不占用可执行文件的大小,只记载 需要多少空间 来 存储 未初始化数据,不分配实际的空间。

进程

进程内存分配

当程序被加载到内存单元时,需要另外两个域:堆域和栈域。一个正在运行的程序占用的内存区域被分为以下五部分:

  • 代码段
  • 初始化数据段:data段属于静态内存分配。
  • 未初始化数据段:BSS段属于静态内存分配。
  • 堆(heap):程序员通过 malloc或new 开辟 。保存函数内部动态分配内存,是一种用来保存程序信息的函数结构,更准确的说是保存程序的动态变量。堆是“先进先出”数据结构(管型)。只允许在堆的一端插入数据,在另一端移走数据。堆的地址空间“向上增加”,地址向上生长。
  • 栈(stack):存放函数的局部变量(但不包括静态变量,静态变量存放在 数据段中)、参数以及返回值。是一种后进先出的数据结构(桶型)。栈的地址空间“向下减少”,地址向下生长。





























名称 内容
代码段 可执行代码、字符串常量
数据段 已初始化全局变量、已初始化全局静态变量、已初始化局部静态变量(以上若初始化为0 则在BSS段)、常量数据
BSS/ZI段 未初始化全局变量、未初始化全局静态变量、未初始化局部静态变量
局部变量、函数参数(烫烫烫)
动态内存分配(屯屯屯)

操作系统负责代码段、数据段和BSS段的加载,并将在内存中为这些段分配空间,栈也由操作系统分配和管理,不需要程序员管理,堆有程序员自己管理,申请和释放空间。
动态
栈

  1. #include <stdio h="">
  2. const int g_A = 10; //代码段
  3. int g_B = 20; //数据段
  4. static int g_C = 30; //数据段
  5. static int g_D; //BSS段
  6. int g_E; //BSS段
  7. char *p1; //BSS段
  8. void main( )
  9. {
  10. int local_A; //栈
  11. int local_B; //栈
  12. static int local_C = 0; //静态局部变量 BSS段
  13. static int local_D; //静态局部变量 BSS段
  14. char *p3 = "123456"; //123456在代码段,p3在栈上
  15. p1 = (char *)malloc( 10 ); //堆,分配得来得10字节的区域在堆区
  16. strcpy( p1, "123456" ); //123456{post.content}放在常量区,编译器可能会将它与p3所指向 的"123456"优化成一块
  17. printf("hight address\n");
  18. printf("-------------栈--------------\n");
  19. printf( "栈, 局部变量, local_A, addr:0x%08x\n", &local_A );
  20. printf( "栈, 局部变量,(后进栈地址相对local_A低) local_B, addr:0x%08x\n", &local_B );
  21. printf("-------------堆--------------\n");
  22. printf( "堆, malloc分配内存, p1, addr:0x%08x\n", p1 );
  23. printf("------------BSS段------------\n");
  24. printf( "BSS段, 全局变量, 未初始化 g_E, addr:0x%08x\n", &g_E, g_E );
  25. printf( "BSS段, 静态全局变量, 未初始化, g_D, addr:0x%08x\n", &g_D );
  26. printf( "BSS段, 静态局部变量, 初始化, local_C, addr:0x%08x\n", &local_C);
  27. printf( "BSS段, 静态局部变量, 未初始化, local_D, addr:0x%08x\n", &local_D);
  28. printf("-----------数据段------------\n");
  29. printf( "数据段,全局变量, 初始化 g_B, addr:0x%08x\n", &g_B);
  30. printf( "数据段,静态全局变量, 初始化, g_C, addr:0x%08x\n", &g_C);
  31. printf("-----------代码段------------\n");
  32. printf( "代码段,全局初始化变量, 只读const, g_A, addr:0x%08x\n\n", &g_A);
  33. printf("low address\n");
  34. return;
  35. }

PCB和进程

进程与进程控制块(PCB process control block)是一一对应的。系统为了管理进程设置的一个专门的数据结构,用它来记录进程的外部特征,描述进程的运动变化过程。系统利用PCB来控制和管理进程,PCB是系统感知进程存在的唯一标志。
Linux系统启动的时候,最先启动的进程 init进程,进程编号是1
init进程是所有进程的祖先。基于init进程才能运行其他进程

PCB包括

  1. 进程标识符 name :PID
  2. 进程当前的状态 status:为了管理方便,系统设计时将 状态相同 的进程组成一个队列,如 就绪进程队列、
  3. 进程对应的程序和数据地址,以便把PCB与其程序和数据联系起来。
  4. 进程资源清单:列出进程拥有的除CPU外的资源记录。如 I/O设备
  5. 进程优先级 priorty:反应进程的急迫程度,由用户和系统设置
  6. CPU现场保护区 cpustatus:
  7. 进程同步与通信机制:用于实现进程间 互斥、同步和通信所需的信号量等
  8. 进程所在队列PCB的链接字
  9. 与进程相关的其他信息

进程状态

  1. 运行状态R
  2. 可中断睡眠状态S
  3. 不可中断睡眠状态D
  4. 暂停状态T
  5. 僵尸状态Z
  6. 退出状态X

程序和进程的区别

  1. 程序时静态的,以文件的形式存在,是存放在磁盘中的可执行文件。
  2. 进程是动态的,有生命周期,在内存中运行。
  3. 操作系统由很多个进程组成
  4. 每个进程要想运行起来,都要被操作系统管理,每个进程都有自己的进程编号PID

程序运行成为进程的过程

双击运行一个可执行文件时

  1. 创建一个进程。
    向操作系统申请一个进程,对32位系统来说 一个进程内存最大占 4G 2^32
  2. 把数据从硬盘 “拷贝/加载” 到进程的空间。
    数据从一个存储器/硬盘(慢) 到 另外一个存储器/内存 DMA控制器模块做拷贝。DMA拷贝完向CPU发出DMA中断,通知CPU已经拷贝完成
  3. 由操作系统接管这个进程。
    操作系统会进行 进程调度

线程

  1. 一个进程的多个执行线路叫线程。线程是“一个进程内部的控制序列”
  2. 一切进程至少都有一个执行线程
  3. 进程分配线程的时间。CPU的一个核心执行一个线程。
  4. 进程抢夺到时间片后,进程把时间分配给线程
  5. 一个进程执行一个fork调用的时候,会创建出进程的一个新拷贝,新进程拥有它自己的变量和PID
  6. 在进程中创建一个新线程的时候,新的执行线程会拥有自己的堆栈、局部变量,但与它的创建者共享全局变量、文件描述符、信号处理器和当前的子目录状态

进程和线程的区别

  1. 进程是资源分配的基本单位,线程是CPU调度的基本单位
  2. CPU就像一座工厂,时刻在运行。
  3. 假设工厂电力有限,一次只能供给给一个车间使用。也就是说,一个车间开工时,其他车间都必须停工。(单个CPU一次只能运行一个任务)
  4. 一个车间里,可以有很多工人,他们协同完成一个任务(一个进程可以包括多个线程)
  5. 车间的空间工人是共享的(一个进程的内存空间是共享的,每个线程都可以使用这些共享内存)
  6. 每个车间的大小不同,有些车间只能容纳一个人(一个线程使用某些共享内存时,其他线程必须等待它结束才能使用)
  7. 防止他人进入的简单方法,就是在门口上锁(互斥锁、防止多个线程同时读写某个内存区域)
  8. 还有些房间,可以同时容纳N个人,人数大于N时,多出来的人只能在外面等待(某些内存区域,只能供给固定数目的线程使用)
  9. 解决方法是,在门口挂N把钥匙。进去的人取一把钥匙,出来再把钥匙挂回原处,后面的人发现钥匙空了,就必须在门口等待。(信号量,保证多个线程不会互相冲突)

参考材料

C程序内存分配

发表评论

表情:
评论列表 (有 0 条评论,205人围观)

还没有评论,来说两句吧...

相关阅读

    相关 程序线进程

    01. 程序(programm) 概念:是为完成特定任务、用某种语言编写的一组指令的集合。即指 一段静态的代码。 02. 进程(process) 概念:程序的一次执行过程

    相关 程序-进程-线

    一 程序与线程      1)程序是一个静态概念,是一组指令的集合,是一种静态概念。而进程是程序及其数据执行的过程是一个动态的概念。       2)进程是一个执行过

    相关 程序进程线

    简述:一个程序至少有一个进程,一个进程至少有一个线程. 一.单位 进程是系统进行资源分配和调度的一个独立单位. 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比