进程的概念基础

进程

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配(cpu时间,内存)和调度的基本单位,是操作系统结构的基础。

描述进程-PCB

为了描述控制进程的运行,系统中存放进程的管理和控制信息的数据结构称为进程控制块(PCB Process Control Block),它是进程实体的一部分,是操作系统中最重要的记录性数据结构。它是进程管理和控制的最重要的数据结构每一个进程均有一个PCB,在创建进程时,建立PCB,伴随进程运行的全过程,直到进程撤消而撤消。

描述数据的结构体,任何pcb包含了进程的所有属性信息


Linux操作系统下的PCB是 task_struct:
在Linux中描述进程的结构体叫task_struct。

task_struct是Linux内核中的一种数据结构,它会被装载在RAM内存里包含着进程的所有信息。

task_struct内容分类

  • 标识符: 描述本进程的唯一标识符,用于区别其他区进程。(PID:进程ID。PPID:父进程的ID)
  • 状态:任务状态,退出代码,退出信号等。
    可能存在多个r状态,但运行的只有一个。 在系统中R状态仅表示该进程允许被放在cpu上

时间片是一个进进程占有CPU资源的基本单位,任何一个进程在CPU上运行超过一定的时间就会被从CPU上剥离下来
调度队列:把r状态的pcb取出来

  • 优先级 :相对于其他程序的优先级。(使用数字表示,优先级越高数字越小)

  • 程序计数器:(pc指针,CPU中的寄存器)程序中将被执行的下一条指令的地址。

  • 内存指针:包括程序代码和相关数据的指针,还有和其他进程共享内存块的指针。

  • 上下文数据:进程执行时处理器的寄存器中所保存的数据。

    把一个进程调度运行时CPU中寄存器中的数据叫做上下文数据,当一个进                      
    程被切换,时上下文数据会被存入PCB中,下次执行该进程时直接获取。
    进程间的切换必须要做保存 / 恢复上下文数据。
    
    当一个进程被切换时,上下文数据会被存入pcb中等待下次调用时,直接恢复 
    
  • I/O状态信息:包括显示的I/O请求,分配给进程的I/o设备和被进程使用的文件列表。

  • 记账信息:可能包括处理器时间总和,使用的时钟数总和,时间限制,及账号的(对于一个人来说,相当于他的年龄)


  • 并发:在一个时间段内,多个任务得以同时推进叫并发

  • 并行:在一个时间段内,多个任务在多个CPU上同时运行


组织进程

所有运行在系统里的进程都以task_struct链表的形式存储在内核里。

查看进程

进程的信息可以通过 ls
/proc 查看 进程目录
如果查看pid为1 的进程,需要通过/proc/1查看

大多数的用户进程信息可以通过topps 查看,top相当于Windows中的任务管理器

通过系统调用获得进程提示符

  • 子进程ID :PID
  • 父进程ID: PPID
  • getpid : 获得系统调用,自己调,返回当前进程的PID
  • getppid: 获得父进程的ID 进程重复运行时父进程的ID保持不变

bash:命令号解释器 系统父进程一般为bash

1 #include <stdio.h>                                                                 
  2 #include <unistd.h>                                                                
  3 #include <sys/types.h>                                                             
  4                                                                                    
  5                                                                                    
  6 int main()                                                                         
  7 {                                                                                  
  8   printf("%d\n",getpid());                                                         
  9   printf("%d\n",getppid());                                                        
 10   return 0;                                                                        
 11 }                                                                                  
 12            


[wens@localhost 10_21]$ make
gcc -o test test.c
[wens@localhost 10_21]$ ./test
3567
2675

在Unix系统中只有一个系统调用可以用用来创建新进程:fork

fork有两个返回值, fork会给父进程返回子进程的pid,给子进程返回0.
一个父进程可能会有多个子进程。子进程还可以生成子进程,一个原始的进程可以生成进程树,包含着子进程,孙子进程和更疏远的后裔进程.

一个子进程只有一个父进程

父子进程代码共享,数据各自开辟空间,私有时采用写时拷贝的方式,进程运行是有独立性的
(代码是只读的)

kill -9 pid 直接杀死进程

多进程 :pcb独立 进程独立 代码和数据独立

进程的状态

-R运行状态(runing):并不意味着进程一定在运行中,它表明进程要么在运行中要么在运行队列中

  • S睡眠状态(sleeping):意味着进程在等待事件的完成(也可叫做中断睡眠)

  • D磁盘休眠状态(disk sleep):有时候也叫不可中断睡眠,这个状态的进程通常会的等待io的结束

  • (D和S的睡眠深度不一样,s浅度睡眠,可被中断,被信号杀死。
    深度睡眠不可被中断,不可被杀掉,不接受中断信号,等待需求完成时才能被唤醒)

  • T停止状态(stopped):可以通过SIGSTOP 19信号给进程来停止(T)进程。这个被暂停的进程可以通过发送SIGOUT 18信号让进程继续运行。
    -** X死亡状态**(dead):这个状态只是一个返回状态,不会在任务列表中看到这个状态。

进程状态的修改

  • kill -l :罗列所有的信号
  • kill -SIGSTOP pid
  • kill -SIGCONT pid

僵尸进程

僵死状态(zombies)当进程退出时,父进程没有读取到进程的返回代码时就会产生僵尸进程。
僵死进程会以终止状态保持在进程列表中,并且会一直等待父进程读取退出的状态码。
所以当子进程退出,父进程还在运行,但父进程没有读取子进程的状态,子进程就会进入z状态。

僵尸进程的危害:

如果父进程一直不读取子进程的推出代码,子进程将一直处于僵尸状态,退出状态属于进程的基本信息,保存在task_struct中,所以z状态不退出,pcb将一直进行维护。所以当大量进程处于z状态,不被回收,pcb将一直使用内存空间,所以会造成内存泄漏。

孤儿进程:

如果父进程先退出,子进程后退出,那么子进程将被称为孤儿进程。如果孤儿进程无人回收将造成内存泄漏。
孤儿进程由系统维护,所以会被一号进程init领养,由init进程回收。

进程的优先级

是指cpu资源分配的先后顺序,就是指进程的优先权。优先权高的进程有优先执行权利,还可以把进程运行到指定的cpu上。

  • UID:代表执行者的身份
  • PID:代表这个进程的代号
  • PPID:代表这个进程的父进程代号
  • PRI:代表这个进程可被执行的优先级,值越小越先执行
  • NI:代表这个进程的NICE值

nice值是指进程可被执行的优先级的修正数值

PRI值越小越快被执行,加入nice值后,将会使PRI变为PRI(new)=PRI(old)+nice;

nice值为负的时候,程序的优先级值将会变小,其优先级会变高,表示进程将会越快被执行,所以Linux下调整进程的优先级就是调整nice的值,nice的值的取值范围时-20至19,一共40个级别。

每次优先级的设置都会在原始优先级的基础上设置。
进程优先级的初始值为80,优先级范围的设置确保进程的优先级相差不会太大保持调度均衡。

nice值并不是程序的优先级只是程序优先级的修正数据修改进程优先级的命令

启动进程前调整 nice

开始执行程序前就指定nice值: nice -n -5 ./text

调整已存在进程的nice值:renice
renice -5 -p 5200

//PID为5200的进程的nice值设为-5

用top命令更已存在进程的nice值:
top
进入top 后按r 输入要修改进程的pid 输入要修改的nice 值

  • 竞争性:系统进程数目众多,而cpu资源只有少量,甚至一个,所以进程之间存在竞争性。
  • 独立性:多进程运行,需要独享各中资源,多进程运行期间互不干扰。

计算密集型:计算密集型任务主要是进行大量计算,需要消耗cpu资源,计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力。这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。

计算密集型任务由于主要消耗CPU资源,因此,代码运行效率至关重要。Python这样的脚本语言运行效率很低,完全不适合计算密集型任务。对于计算密集型任务,最好用C语言编写。

IO密集型:第二种任务的类型是IO密集型,涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。

IO密集型任务执行期间,99%的时间都花在IO上,花在CPU上的时间很少,因此,用运行速度极快的C语言替换用Python这样运行速度极低的脚本语言,完全无法提升运行效率。对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言最差。


环境变量:

一般是指定操作系统中用来指定操作系统运行环境的一些参数。

env 查看系统所有的环境变量。

常见的 环境变量

  • PATH*:指定命令的搜索路径
  • HOME*:指定用户的主工作目录
  • HISTSIZE*:指保存历史命令记录的条数
  • SHELL*:当前shell值通常是/bin/bash

查看环境变量的方法:

echo $NAME //NAME你的环境变量的名称

PATH=$PATH:当前路径
用来搜索可执行程序的路径

和环境变量相关的命令:

  • echo:显示某个环境变量的值
  • export:设置一个新的环境变量
  • env:显示所有环境变量
  • unset:清除环境变量
  • set:显示本地定义的shell变量和环境变量

环境变量的组织方式:
每个程序都会收到一张环境表,环境表是一个字符指针数组,每个指针指向一个以’\0’结尾的环境字符串

命令行的第三个参数:
main (argc,argv[ ], env[ ] )
通过第三方变量environ获取:

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

  • putenv:设置环境变量
  • getenv:获取环境变量

常用getenv和putenv函数来访问特定的环境变量。
环境变量通常具有全局属性,可以被子进程继承下去。

猜你喜欢

转载自blog.csdn.net/M_jianjianjiao/article/details/83301821
今日推荐