Linux内核网络协议栈5-socket地址绑定
<div style="background-color: transparent; margin: 0px;">一、socket绑定入口
<div style="background-color: transparent; margin: 0px;">1、示例代码
struct sockaddr_in server_address;server_address.sin_family = AF_INET;server_address.sin_addr.s_addr = inet_addr("0.0.0.0");server_address.sin_port = htons(9734);server_len = sizeof(server_address);bind(server_sockfd, (struct sockaddr *)&server_address, server_len);
2、绑定入口
前面介绍了socket从库函数到内核的过程,其最终都是通过102号中断进入内核,所不同的是子中断号不同;对于绑定,其子中断号是2;
和创建socket一样,绑定socket的处理函数都是:
asmlinkage long sys_socketcall(int call, unsigned long __user *args){ unsigned long a; unsigned long a0, a1; int err; if (copy_from_user(a, args, nargs)) return -EFAULT; a0 = a; a1 = a; switch (call) { …... case SYS_BIND: err = sys_bind(a0, (struct sockaddr __user *)a1, a); …...}
根据子中断号,内核会执行sys_bind()函数来完成地址的绑定;
二、绑定的具体过程
sys_bind()函数如下,一起来分析一下它的主要过程:
asmlinkage long sys_bind(int fd, struct sockaddr __user *umyaddr, int addrlen){ struct socket *sock; char address; int err, fput_needed; // 1, 根据fd查找相应的socket结构 sock = sockfd_lookup_light(fd, &err, &fput_needed); if (sock) { // 2, 将用户空间的地址结构拷贝到内核空间 err = move_addr_to_kernel(umyaddr, addrlen, address); if (err >= 0) { err = security_socket_bind(sock, (struct sockaddr *)address, addrlen); if (!err) // 3, 根据协议域及socket类型,调用相应的bind函数 err = sock->ops->bind(sock, (struct sockaddr *) address, addrlen); } fput_light(sock->file, fput_needed); } return err;}
上面的过程中:
1、根据fd找到相应的socket结构
在创建socket的最后,会将socket结构与文件系统关联,并返回给应用程序与socket相关的文件描述符;这里是根据应用程序传递过来的文件描述符取得关联的socket结构;
下面看看从fd取得socket结构的代码:
static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed){ struct file *file; struct socket *sock; *err = -EBADF; file = fget_light(fd, fput_needed); if (file) { sock = sock_from_file(file, err); if (sock) return sock; fput_light(file, *fput_needed); } return NULL;}
再到fget_lignt()去看看:
struct file *fget_light(unsigned int fd, int *fput_needed){ struct file *file; struct files_struct *files = current->files; …... file = fcheck_files(files, fd); …... return file;}
这里current宏返回当前运行的进程的描述符,current->files返回当前进程的打开文件表;函数fcheck_files(files, fd)根据fd从打开文件表里取出相应的file结构变量;
在创建socket中提到,file与socket关联,是通过file->private=socket完成的,因为获取到file结构变量后,也可以通过同样的方式取得socket结构变量;sock_from_file()函数就是用来完成此工作的;
页:
[1]