1 进程概述
从严格意义上来讲,程序和进程是两个不同的概念,他们的状态,占用的系统资源都是不同的。
- 程序:就是磁盘上的可执行文件文件, 并且只占用磁盘上的空间,是一个静态的概念。
- 进程:被执行之后的程序叫做进程,不占用磁盘空间,需要消耗系统的内存,CPU资源,每个运行的进程的都对应一个属于自己的虚拟地址空间,这是一个动态的概念。
1.1 并行和并发
-
CPU时间片 CPU在某个时间点只能处理一个任务,但是操作系统都支持多任务的,那么在计算机CPU只有一个的情况下是怎么完成多任务处理的呢?每个人分一点,但是又不叫吃饱。 CPU会给每个进程被分配一个时间段,进程得到这个时间片之后才可以运行,使各个程序从表面上看是同时进行的。 如果在时间片结束时进程还在运行,CPU的使用权将被收回,该进程将会被中断挂起等待下一个时间片。 如果进程在时间片结束前阻塞或结束,则CPU当即进行切换,这样就可避免CPU资源的浪费。 因此可以得知,在我们使用的计算机中启动的多个程序,从宏观上看是同时运行的,从微观上看由于CPU一次只能处理一个进程,所有它们是轮流执行的,只不过切换速度太快,感觉不到,因此CPU的核数越多计算机的处理效率越高。
-
并发和并行 这两个概念都可笼统的解释为:多个进程同时运行. 但是他们两个的同时并不是一个概念。Erlang 之父 Joe Armstrong 用一张小孩能看懂的图解释了并发与并行的区别:
并发:第一幅图是并发。
- 并发的同时运行是一个假象,咖啡机也好CPU也好在某一个时间点只能为某一个个体来服务,因此不可能同时处理多任务,这是通过上图的咖啡机/计算机的CPU快速的时间片切换实现的。
- 并发是针对某一个硬件资源而言的,在某个时间段之内处理的任务的总量,量越大效率越高。
- 并发也可以理解为是不断努力自我升华的结果。
并行:第二幅图是并行。
- 并行的多进程同时运行是真实存在的,可以在同一时刻同时运行多个进程
- 并行需要依赖多个硬件资源,单个是无法实现的(图中有两台咖啡机)。
- 并行可以理解为出生就有天然的硬件优势,资源多办事效率就高。
1.2 PCB
PCB - 进程控制块(Processing Control Block),Linux内核的进程控制块本质上是一个叫做
task_struct
的结构体。 在这个结构体中记录了进程运行相关的一些信息,介绍一些常用的信息:
-
进程id:每一个进程都一个唯一的进程ID,类型为
pid_t
, 本质是一个整形数 -
进程的状态:进程有不同的状态, 状态是一直在变化的,有就绪,运行,挂起,停止等状态。
-
进程对应的虚拟地址空间的信息。
-
描述控制终端的信息,进程在哪个终端启动默认就和哪个终端绑定。
-
当前工作目录:默认情况下, 启动进程的目录就是当前的工作目录
-
umask掩码:在创建新文件的时候,通过这个掩码屏蔽某些用于对文件的操作权限。
-
文件描述符表:每个被分配的文件描述符都对应一个已经打开的磁盘文件
-
和信号相关的信息:在Linux中 调用函数, 键盘快捷键, 执行shell命令等操作都会产生信号。
- 阻塞信号集:记录当前进程中阻塞哪些已产生的信号,使其不能被处理
-
未决信号集:记录在当前进程中产生的哪些信号还没有被处理掉。
-
用户id和组id:当前进程属于哪个用户, 属于哪个用户组
-
会话(Session)和进程组:多个进程的集合叫进程组,多个进程组的集合叫会话。
-
进程可以使用的资源上限:可以使用shell命令
ulimit -a
查看详细信息。
1.3 进程状态
进程一共有五种状态分别为:创建态
,就绪态
,运行态
,阻塞态(挂起态)
,退出态(终止态)
其中 创建态 和 退出态 维持的时间是非常 短 的,稍纵即逝。
我们需将就绪态, 运行态, 挂起态,三者之间的状态切换搞明白。
- 就绪态: 等待CPU资源
- 进程被创建出来了,有运行的资格但是还没有运行,需要抢CPU时间片
- 得到CPU时间片,进程开始运行,从就绪态转换为运行态。
- 进程的CPU时间片用完了, 再次失去CPU, 从运行态转换为就绪态。
- 运行态:获取到CPU资源的进程,进程只有在这种状态下才能运行
- 运行态不会一直持续,进程的CPU时间片用完之后, 再次失去CPU,从运行态转换为就绪态
- 只要进程还没有退出,就会在就绪态和运行态之间不停的切换。
- 阻塞态:进程被强制放弃CPU,并且没有抢夺CPU时间片的资格
- 比如: 在程序中调用了某些函数(比如: sleep()),进程又运行态转换为阻塞态(挂起态)
- 当某些条件被满足了(比如:slee() 睡醒了),进程的阻塞状态也就被解除了,进程从阻塞态转换为就绪态。
- 退出态: 进程被销毁, 占用的系统资源被释放了
- 任何状态的进程都可以直接转换为退出态。
1.4 进程命令
在研究如何创建进程之前,先来看一下如何在终端中通过命令完成进程相关的操作。
- 查看进程
$ ps aux - a: 查看所有终端的信息 - u: 查看用户相关的信息 - x: 显示和终端无关的进程信息
如果特别想知道每个参数控制着哪些信息, 可以通过 ps a
, ps u
, ps x
分别查看。
- 杀死进程
kill
命令可以发送某个信号到对应的进程,进程收到某些信号之后默认的处理动作就是退出进程,如果要给进程发送信号,可以先查看一下Linux给我们提供了哪些标准信号。
查看Linux中的标准信号:
$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX
9号信号(SIGKILL)的行为是无条件杀死进程,想要杀死哪个进程就可以把这个信号发送给这个进程,操作如下:
```bash
无条件杀死进程, 进程ID通过 ps aux 可以查看(PID)
$ kill -9 进程ID $ kill -SIGKILL 进程ID