Answers:
实际上,系统调用中有三个等级。
getpid
,gettimeofday
,getuid
或setuid
。根据情况,某些系统调用可以是阻塞的或非阻塞的。例如,read
如果文件是支持非阻塞读取的管道或其他类型并且设置了O_NONBLOCK
标志,则从不阻塞。sleep
。read
在阻塞文件描述符上调用就是阻塞,也是如此wait
。“快速”和“慢速”系统调用之间的区别接近于非阻塞与阻塞,但这是从内核实现者的角度来看。快速的系统调用是已知能够完成而不会阻塞或等待的系统调用。当内核遇到快速系统调用时,它知道可以立即执行系统调用并保持计划相同的进程。(在具有非抢先式多任务处理的某些操作系统中,快速syscall可能是非抢占式的;在普通的unix系统中则不是这种情况。)另一方面,缓慢的syscall可能需要等待其他任务完成,因此内核必须准备暂停调用过程并运行另一个任务。
有些情况下有些灰色区域。例如,read
从常规文件中读取磁盘通常被认为是非阻塞的,因为它不等待其他进程。它只是在等待磁盘,这通常只需要一点时间就可以回答,但是不会永远花费(因此,上面的情况2)。但是从内核的角度来看,该过程必须等待磁盘驱动程序完成,因此这绝对是一个缓慢的系统调用。
O_NONBLOCK
标志的状态。如果设置了该标志,则系统调用可以完成而无需等待任何其他操作,因此它是非阻塞的,内核可以将其视为快速的系统调用。
缓慢的系统调用就像TCP套接字read()一样-如果您没有设置O_ASYNC(或其他设置),它将永远等待。
快速的系统调用类似于gettimeofday()或getpid(),它们都将信息返回给内核立即可用的进程。
磁盘读取属于慢速系统调用的类别。如果进程在真正的磁盘文件描述符上执行read(),则内核可能必须读入一个或多个磁盘块才能满足读取要求。根据基础文件系统的磁盘结构,这可能意味着读取磁盘上的inode以获取“间接块”的磁盘块号,读取间接块以获取数据块,然后读取数据块本身。至少在每个磁盘访问的CPU周期方面,这非常耗时,今天可能比过去的情况更糟。
我已经很久没有见过这种情况了,但是旧的Unix磁盘驱动器设备驱动程序代码的“下半部分”会阻止信号/中断,因此更易于维护磁盘文件系统的完整性。有时,有故障的驱动程序或发生故障的磁盘将永远无法交付进程所要求的磁盘块,并且该进程永远处于休眠状态。即使杀死-9也无济于事。