当前位置: 首页 > 科技观察

内核系统调用与互斥机制的实现

时间:2023-03-17 11:19:41 科技观察

本文转载自微信公众号《编程杂技》,作者theanarkh。转载本文请联系编程杂技公众号。感觉最近在知乎看到两个问题,分享下我对内核系统调用和互斥机制实现的理解。下面是两个问题:https://www.zhihu.com/question/462048846/answer/1919407185https://www.zhihu.com/question/460985657/answer/1912146181系统调用的实现两个问题分别问在TCP/IP协议和epoll的实现中,内核是否使用了多线程。这个问题的角度很有意思。虽然内核内部使用进程/线程来实现某些功能(如pdflush线程定时回写硬盘,kswapd进程周期性回收内存,处理工作队列的线程)。但是系统调用的实现并不涉及多线程的概念。操作系统本质上是对底层资源进行管理,封装底层能力向上层提供服务。这种服务就像实现了一个排序算法,但是是否使用多线程是由上层决定的,内核本身不会在底层实现多线程排序的能力。互斥机制但是因为在多核的情况下,多个线程会在多个CPU上执行,如果多个线程同时请求内核访问同一个内核数据结构,就会造成racecondition。所以内核需要实现访问资源的互斥机制。只有这样才能保证多个CPU中只有一个会同时操作共享的数据结构。例如,自旋锁确保多个CPU中只有一个获得锁,然后操作共享数据。另外,内核还实现了原子操作,比如内核中提供的atomic原子操作,可以对整型变量进行原子操作。具体实现原理根据CPU架构不同而不同。例如i386CPU提供了Lock指令来保证同时只有一个CPU。您可以锁定总线并执行对内存的独占访问。下面是i386原子操作的实现。static__inline__voidatomic_add(inti,atomic_t*v){__asm____volatile__(LOCK"addl%1,%0"//输出到v->counter所在内存:"=m"(v->counter)//%1和0%对应以下两个值,i为整数,存放在随机寄存器中,m表示从v->counter的内存中读取:"ir"(i),"m"(v->counter));}如果是单核的话,非抢占式就不需要这个机制了,因为进程调度器在执行系统调用的时候不会调度其他进程去执行,保证了系统调用的原子性。如果是抢占模式,支持在执行系统调用时被抢占,那么还是需要互斥和原子机制。总之,如果存在竞争条件,则需要保证对共享数据的互斥访问。内核实现的功能虽然没有使用多线程,但通常底层是多核,上层使用多进程/多线程。因此,为了保证共享数据的互斥访问,内核需要实现一些原子操作和互斥机制。