系统调用过程
用户区无法直接调用内核区的函数,但内核区提供了一系列接口来让用户区访问内核区的一些函数,对于这些函数的调用称为系统调用。
系统调用在用户区和硬件设备间添加了一个中间层,该层的作用主要有三个:
1)为用户区提供了抽象的硬件接口,使得应用程序可以不用管磁盘类型和介质而直接对文件进行读写;
2)保证系统的稳定和安全,避免用户程序不正确地使用硬件设备,窃取其他进程资源;
在Linux系统中,系统调用是用户区进入内核的唯一合法入口。
系统调用与内核函数的映射
#include <sys/socket.h>
int socket(int family, int type, int protocol);```
上面是socket函数的原型,该函数建立一个协议族为family、协议类型为type、协议编号为protocol的套接字文件描述符。如果函数调用成功,会返回一个标识这个套接字的文件描述符,失败的时候返回-1。然后,当我们想深入了解socket函数时,却发现搜索遍了用户区和内核区都找不到它的定义。原来,当用户区使用系统调用时,内核通过查找syscall.tbl来找到希望调用的内核函数地址,以socket函数为例:
从内核中的syscall.tbl中可以发现在用户区调用的socket()函数到了用户区就变成了对sys_socket()函数的调用。在unistd.h中我们发现sys_socket函数位与内核中的socket.c文件中:
在socket.c中找到该函数,就能找到socket()函数在内核区的实现了:
socket()函数实现原理
平时我们调用socket()函数大部分是为了实现TCP/IP协议,网上也大部分是这类的socket调用,这里就讲讲蓝牙协议吧。假设我们在用户区调用socket函数:
fd = socket(PF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC