通过Linux理解操作系统(二):进程管理(上)

通过Linux理解操作系统(二):进程管理(上)

在前文完成了概述之后,网站空间,本文就要开始进入戏肉了,之前我们将操作系统的内核结构分成了三个模块,现在就先从进程管理模块来开始深入探讨一下。

1、进程间的关系

我们知道一个Linux系统里同时运行着大量的进程,当你在shell终端里输入ps -ef命令时,你会看到像下面这样一长串的东西,有很多我就截了一部分。

这些进程之间是什么关系呢?

首先,我们从最基本的父子关系说起,我们知道在一个程序里只要调用fork函数就可以创建一个新的进程,在这种情况下,调用fork函数的就是父进程,新创建的进程就是子进程,而子进程又可以创建子进程,这样层层往下延伸,就构成了一棵进程树。然后看上图,每个进程都对应了一个PID和一个PPID,在我们的程序里可以通过getpid和getppid函数获取,PID标识了进程本身,而PPID标识了父进程,所有进程的PPID一层层往上推最终都会汇集到0。然后这里又有一个概念叫做进程组,需要注意的是不能把进程组和前面提到的进程树等同,进程组只包括了一个进程的父进程(还有父进程往上的祖先进程),兄弟进程,以及子进程(还有子进程往下的子孙进程),它只是整个进程树的部分而已(可以自己画个图就明白了)。为什么要区分这个概念呢,是因为在进程通信中一个进程只能发送信号给同一个进程组的进程,如果混淆了的话就会以为能够发信号给所有进程了。进程组以外又有一个概念叫会话,一个会话由多个进程组组成,一个会话对应一个控制终端,也就是tty1-tty7。

关于父子进程又有另外两个概念,一个叫作僵尸进程,在父进程程序中,通常会调用waitpid函数等待子进程终止,香港服务器租用,而如果在父进程调用waitpid之前,子进程就先终止了,那么子进程就会成为僵尸进程(因为还是要等到父进程调用waitpid它才能真正终止,要死不死的所以叫僵尸),而相应的如果父进程在子进程终止之前自己先终止了,那么子进程就变成了孤儿进程,这样该进程以下的进程组就和整个系统的进程树隔离开了,这时候有一种机制叫做“收养”,就是把这个孤儿进程的父进程设为init进程(就是PID为1的那个)。

2、进程间通信

进程间通信是一个很常见的问题,有很多种方式,网上资料也是大把,所以我也不讲怎么实现,只是提一下方式还有稍微解释一下。

首先,关于进程通信不能只是狭隘地理解为交换数据,虽然基本上是这样,但是其实发送信号通知另外一个进程要干什么事,这也是一种通信。一个进程可以在程序里使用函数kill(pid,sig)发送信号给另一个进程(kill不只是杀死,也能发信号的),然后在接收信号的进程程序里可以定义处理相应的信号函数,虚拟主机,这实际上是通过软中断实现的,指一个进程在运行的过程中,收到信号后,停止当前运行的指令,并保存进程状态,然后跳转到信号处理过程,处理完成后又回到原先停止的位置继续执行。

进程通信的另一种方式是管道,它通过阻塞的方式实现了同步,管道分为匿名管道和命名管道两种,匿名管道存在与内存中,只能用于父子进程间,熟悉shell的应该对这样的命令不陌生:

sort <f | head,它实际上创建了一个进程sort从文件f中都入数据进行排序,而sort进程又创建了一个子进程head,并构建了一个匿名管道,把sort的结果传到head,然后head输出前n行数据,当管道满了的时候,sort会停止输出等到head将管道的数据取出后再继续输出。

命名管道则存在与文件系统中,可以用于任意进程之间,因为这只是相当于一个进程创建一个文件并写如数据,然后另一个进程只要知道那个文件的路径,然后打开它读取就行了。

进程间通信还有其他的方式如使用socket监听本机的端口,或者使用IPC对象如共享内存,信号量(信号量不同于信号),消息队列等,这些就等到之后谈到I/O,和内存管理的时候再详细介绍。

3、Linux用于进程管理的系统调用

在了解Linux系统内核是怎么实现进程管理之前,我们先来了解我们的程序如何通过系统调用进行进程管理。

黄色蓝色或者砖红色,犹如童话世界。

通过Linux理解操作系统(二):进程管理(上)

相关文章:

你感兴趣的文章:

标签云: