操作系统那些事(二)

好久没有写blog了,原因是最近身体的种种状况和各种失常。虽然日常工作是做web开发,似乎与与此文毫无关系,但是身在曹营心在汉,出于对系统和网络的兴趣,我更愿意去搞清楚计算机是怎么运行的,网络是怎样去互联的。

本文主要谈及信号,僵尸进程,阻塞,非阻塞,同步io,异步io等操作系统相关概念。

一个进程正常退出或者是因某些因素异常退出时,它在用户空间的数据会被操作系统回收,但是PCB(进程控制块,属于内核部分)里面的数据(包括各种内核相关的东西,比如fd,信号,页表等)。如果此时操作系统不采取任何措施,那么这个进程将成为 僵尸进程,僵尸进程占用系统资源,而且没有半点作用。注意到,僵尸进程是已经死掉的进程,所以假如尝试用kill命令去杀死它,是不会有作用的。

应该怎么样处理才不会产生僵尸进程呢?是这样子的:一般是通过它的父进程把它的相关资源回收了,如果他的父进程都死掉了,那么就由他的祖先进程(可能是init进程)来回收。所以,如果发现僵尸进程,处理办法应该是怎样呢?应该把他的父进程给干掉,这样回收工作就会交由祖先进程来处理。

对应到代码级别,回收资源的处理应该是怎样的呢?一般有2种方式:通过调用wait或者waitpid函数来回收,wait只能是阻塞调用,waitpid可以是非阻塞的。

解释几个重要概念: 阻塞和非阻塞,一般情况是系统调用才会有阻塞非阻塞的说法。阻塞是说进程执行到该系统调用的时候,被暂停执行了,需要等到系统调用返回之后才能继续执行。非阻塞是执行系统调用的时候,如果该调用因为某种原因不能立即执行,那么它会立即返回。举例来说,假如某进程read网络上的数据,如果是阻塞io,那么进程将暂停执行,直到网络上有数据到达;如果是非阻塞io,如果没有数据到达,也会立即返回。一般来说磁盘io操作都不会使进程阻塞,但是终端和磁盘io就没有那么幸运了,终端io需要阻塞到输入换行符;网络需阻塞到有数据到达时。

阻塞和非阻塞都有什么优缺点呢?阻塞的话,优点是阻塞进程不占用cpu资源;缺点是进程暂停在某调用中,不能往下继续执行。非阻塞的话,一般代码是写成轮询的方式,这样优点的话就是进程可以继续往下执行,缺点就是占用太多cpu资源,而且做了太多无用功。

阻塞和非阻塞都有让人很不爽的缺点,如果想要进程运行得爽一点,而又不会太费cpu资源,可以用信号的方式来处理。

什么是 信号呢?信号属于PCB中个一个部分,也就是说它位于内核中,一般是用SIG之类的宏定义或者是相应的数字来标识。可以有如下4种方式产生信号:
 通过ctrl+c,键盘驱动程序向前台进程发送一个信号,对后台进程没有作用。
 硬件异常产生信号,由内核产生信号,并向相关进程发送此信号。比如进程非法内存时,mmu会引发异常,然后内核产生信号,并将此信号发送给当前进程。
 通过kill命令或者kill函数
 当内核检测到某种软件条件发生时,可以通过信号通知进程,比如闹钟超时时产生alarm信号。

进程对于信号可以有3种反应:忽略;按默认的动作处理;注册信号处理函数,当信号发生时,处理函数被执行。这是通过sigaction函数来操作的,通过设置参数,告诉内核,当某信号发生时执行某函数。

有了对信号概念的了解之后,可以将wait和waitpid函数以信号通知的方式来执行,因为信号是异步的,所以当信号发生时(子进程退出后,会产生信号SIGCHLD),进程立即跳转到相应的信号处理函数执行。这样一来,就没有了阻塞操作的不爽(暂停了进程执行),也不会有非阻塞轮询的cpu消耗。

看起来信号是比较爽,确实是比较爽,但是如果要写代码能上台面的代码的话,还是需要注意很多细节的,详情请咨询APUE。

接下来再谈谈几个重要概念。Io是编程里面非常重要的一类操作。上面曾经提到,磁盘的io是非常爽的,一般来说读写都不会阻塞,除非磁盘满了,或者是被破坏了。但是终端io和网络io却不是那么一回事。因此就有了多种的io模型。

上面已经提及了 阻塞io和非阻塞io。这2个对于网络编程都是不爽的,原因也比较明显,上文也提及了,不再赘述。因此就出现了 多路io,进程可以监听在多个fd上面,这样就可以避免因为某个fd阻塞而使进程无法继续其他fd的操作,同时也避免了非阻塞io的轮询。在linux中,此操作对应的系统函数是select,此函数本身是阻塞的,但是它阻塞在多个fd上,只要有一个fd变为非阻塞,即可以进行io,那么它就返回。返回之后进程对该fd进行io操作时,就不会阻塞了,这听起来似乎就比较爽。确实,select函数用得很多,poll函数也差不多,只不过是linux中没有,某些unix系统中可以使用。

信号io也是使用信号的方式来通知进程,是这样子的:首先进程告诉内核,当某个fd可以执行io操作时,就麻烦告诉我一下。这样的话,进程该干嘛就干嘛,想干嘛就干嘛,不会被阻塞,爽!但是只能一个进程中只能有一个fd有此待遇,所以我觉得信号io没有什么大作用。

以上说的各种io模型,包括阻塞io,非阻塞io,多路io,信号io,都算是 同步io。UNP这本书里是这么说的。它是这么解释的,以上各种io都有一个共性,当内核把数据准备好后,接受数据,也就是将数据从内核拷贝到用户进程是一个阻塞的操作。这看起来似乎有点奇怪:从内核到用户进程拷贝数据都算阻塞了,但是是大师说的,我们姑且这么理解着先。虽然概念是这么说,但是我觉得没有必要去纠结这个,理解清楚了各种io操作的过程是怎么样的,就差不多了。

真正的异步io操作是怎么样子的呢?内核里面的数据已经拷贝到用户进程空间,用户进程只是接收到一个数据已经可用的信号,而无需再执行io操作。这就是所谓的异步io。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值