Linux--随笔(一) -- 进程概念 ( 重要 )

冯诺依曼体系结构 

  • 结构决定算法

  • 输入设备 -- 存储器( 内存 ) -- 输出设备

  • 中央处理器 , ( 运算器 , 控制器 )

  • 在数据层面上CPU只能和内存打交道 , 外设不能直接和CPU沟通 , ( 所有设备只能直接和内存打交道 )

操作系统 

  • 操作系统是一个搞管理的软件 ( 提供更好的执行环境 )

  • 操作系统是一个完整的系统 , 要使用其功能必须以接口的形式使用  将操作系统的接口调用称为系统调用

  • 计算机管理硬件 1.描述起来 ,用struct结构体    2.组织起来,用链表或者其他更高效的数据结构

系统调用和库函数

  • 使用shell外壳 ,lib,部分指令对系统调用进行适度封装,从而形成了库,有利于上层用户或开发者进行二次开发

    扫描二维码关注公众号,回复: 3570286 查看本文章

进程基本概念 (先描述后组织)

    描述进程--PCB ( PCB里包含了进程的所有信息 )

  • Linux操作系统下PCB为 : task_struct

  • (重要) 如何查看 PID 查看系统进程状态ps aux、ps axj , ps aux | grep 进程名、ps axj | grep 进程名  加上过滤进程信息查看 ps aux | grap test | grap -v grap

    task_struct 

  1. PID ( 标识符 ) :描述本进程的唯一标识符 通过调用getpid()得到PID;

  2. 状态 : R状态--R状态仅表示该进程允许被放在CPU上运行,不一定被运行,等待运行  CPU将所有的R状态从PCB中拿出来,按照优先级存放在调度队列中  S状态--睡眠状态 : 意味着进程在等待事件完成 ( 比如 Sleep() 函数 )

  3. 优先级

  4. 程序计数器( PC指针 寄存器 ) : 存放即将被执行的下一条指令的地址

  5. 上下文数据 : 将正在执行进程这中的数据保存在PCB中 ( 便于恢复 )

  6. 进程切换必须要保存 / 恢复 硬件上下文数据

  7. 时间片 : 是一个进程,占有CPU资源的一个基本单位,当一个进程在一段时间内没有结束,会将该进程强行剥离出来

  8. 并发 : 在一个时间段内,多个内容同时推进

 组织进程--( 所有运行在系统里的进程都已task_struct链表的形式存在内核中 ) ( 刚好的去管理 )

查看进程

  • 进程信息可以通过 /proc 系统文件进行查看,如果要查看某个文件的进程信息, ls /proc/(文件名)

  • 同样也可以使用top和ps用户技工具获取 ( ps aux | (管道) grep (过滤) test (文件名) | grep -v grep )  top ( 动态查看进程信息 )

系统调用 

  • getpid获取当前进程号,getppid获取当前进程父进程进程号

  • 进程id ( PID ) 每执行依次就会改变

  • 父进程id ( PPID ) 不会改变 

  • 一个父进程可以有多个子进程 ,一个子进程只有一个父进程

创建进程 -- fork   头文件 #include <sys/type.h>

  • fork有两个返回值 ( 为父进程返回子进程PID , 给子进程返回0 , 若失败子进程返回-1 )

            在调用fork之前有一个执行流, fork之后父子进程共享,系统多一个进程,在return之前有两个执行流

            fork创建子进程,父进程代码共享,但是数据私有的, 进程运行时是有独立性的 ( 代码(只读),数据,结构体(PCB) 进程间独立 ) , 所有父子进程创建后,父子进程代码共享, PCB和数据是独立的

  • fork一般情况下要使用if进行分流  ,

  • 分流之后父子进程执行各自的代码块

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main()
{
         int ret=fork();
         if(ret<0){
                 perror("fork");
                 return 1;
         }
         else if(ret==0) {
                 printf("I am child : %d!, ret : %d\n",getpid(),ret);
         }
         else{
                 printf("I am father : %d, ret : %d\n",getpid(),ret);
         }
         sleep(1);
         return 0;
 }
  • 结束进程 1. ctrl c   2. kill -9 PID

进程状态

僵尸进程的危害 : 

 

  • 父进程需要知道子进程任务进行的情况如何,方便进行二次决策

  • S状态浅度睡眠D状态深度睡眠

  • S状态和D状态 S状态是一种可以被中断,可以被杀死的状态  D状态是一种不可以被中断的状态

  • Z状态 僵尸状态 : 在该状态下如果不进行回收就会造成内存泄漏  父进程回收子进程获得子进程的PCB,并且释放掉子进程占有的资源

  • ( 重要 )进程修改   kill -l  //查看系统支持的信号列表    kill -SIGSTOP pid  停止    kill -SIGCONT pid  继续

孤儿进程

  • 1号进程也可以看作系统

  • 开始都是由bash创建子进程,然后子进程再创建子进程的子进程

进程优先级

  • 与权限的区别,权限决定能还是不能,优先级考虑的是先后顺序的问题

  

信息的含义 ( 重要 )

PRI和NI ( 重要 )

  • 优先级存在上下线限,要保证调度器的公平性,要保证CPU雨露均沾

  • 优先级都是从80开始的

修改进程优先级的命令

  • nice

  • renice

   

 重要概念

  • IO ( 输入输出 )密集型

  • 计算密集型

环境变量 

  •   main( int argc , char * argv[] , char * env[] )

通过代码如何获取环境变量

  • 命令行第三个参数

通过系统调用获取或设置环境变量

  • putenv

  • getenv ( 得到环境变量 )

环境变量通常是具有全局属性的

  • 环境变量可以由父进程传给子进程,可以被子进程传递下去 why

程序地址空间 ( 重要 )

为什么子进程能继承父进程的环境变量?

首先考虑进程的虚拟地址空间 ( 用来描述一段空间 ) , 命令行参数和环境变量在栈之上 , 子进程以父进程为模板 ,拷贝PCB、虚拟地址空间 , 所以会被继承下去

内核空间相当于操作系统

每个进程看到得虚拟地址空间有大量准确定义的区(area)构成,每个区都有专门的功能。从最低的地址看起:

  • 程序代码和数据:代码是从同一固定地址开始,紧接着的是和C全局变量相对应的数据区。 (应该就是所谓的静态存储空间)

  • 堆:代码和数据区后紧随着的是运行时堆。作为调用malloc和free这样的C标准库函数,堆可以在运行时动态的扩展和收缩。(应该就是所谓的动态存储区) 

  • 共享库:在地址空间的中间附近是一块用来存放像C标准库和数学库这样共享库的代码和数据的区域。(C标准库函数的指令,连接阶段把他们加入到编译后的程序)

  • 栈:位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数调用。和堆一样每次我们从函数返回时,栈就会收缩。

  • 内核虚拟存储器:内核是操作系统总是驻留在存储器中的部分。地址空间顶部的四分之一部分是为内核预的。

页表是由软件和硬件结合的方式

当进行进程拷贝或者进程替换时就需要一份PCB , 页表 , 虚拟地址空间 , 维护映射关系

猜你喜欢

转载自blog.csdn.net/ds19980228/article/details/82790347