Socket的实现(Linux内核部分)
在Linux内核中,提供了一个统一的接口sys_socketcall,用于处理socket所有动作.
下面就是它的代码片段:
1. asmlinkage long sys_socketcall(int call, unsigned long __user *args)
2. {
3. unsigned long a[6];
4. unsigned long a0, a1;
5. int err;
6. ..........................................
7.
8. a0 = a[0];
9. a1 = a[1];
10.
11. switch (call) {
12. case SYS_SOCKET:
13. err = sys_socket(a0, a1, a[2]);
14. break;
15. case SYS_BIND:
16. err = sys_bind(a0, (struct sockaddr __user *)a1, a[2]);
17. break;
18. case SYS_CONNECT:
19. err = sys_connect(a0, (struct sockaddr __user *)a1, a[2]);
20. break;
21. case SYS_LISTEN:
22. err = sys_listen(a0, a1);
23. break;
24. case SYS_ACCEPT:
25. err =
26. do_accept(a0, (struct sockaddr __user *)a1,
27. (int __user *)a[2], 0);
28. break;
29. case SYS_GETSOCKNAME:
30. err =
31. sys_getsockname(a0, (struct sockaddr __user *)a1,
32. (int __user *)a[2]);
33. break;
34. .....................................
35. return err;
36. }
可以看到代码比较简单,就是通过传递进来的call类型,来调用相应的socket相关的函数.
这里你可能注意到了,那就是一般文件句柄相关的操作,比如write,read,aio,poll这些并没有看到(也就是 file_operations).这是因为socket上面其实还有一层vfs层,内核把socket当做一个文件系统来处理,并实现了相应的vfs方法.因此下面我们先来了解下vfs.然后会描述下进程如何通过vfs存取句柄.
vfs其实就相当于对下层的文件系统和上层应用之间的粘合层,它定义了文件系统需要实现的相关的操作,然后下层的文件系统只需要实现这些方法就可以了,也就是说在内核其他部分和上层应用看来,所有的文件系统没有任何区别.
下面的这张图就是从用户空间调用write的大体流程: