|
|
<div style="margin-top: 0px; margin-bottom: 0px; margin-right: 0px; text-indent: 0px; margin-left: 0px; font-size: 11pt; font-family: Arial; background-color: transparent; font-style: normal; text-decoration: none; vertical-align: baseline;">1、示例及函数入口:
1) 示例代码如下:
int server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
2) 入口:
net/Socket.c:sys_socketcall(),根据子系统调用号,创建socket会执行sys_socket()函数;
2、分配socket结构:
1) 调用链:
net/Socket.c:sys_socket()->sock_create()->__sock_create()->sock_alloc();
2) 在socket文件系统中创建i节点:
inode = new_inode(sock_mnt->mnt_sb);其中,sock_mnt为socket文件系统的根节点,是在内核初始化安装socket文件系统时赋值的,mnt_sb是该文件系统安装点的超级块对象的指针;
这里,new_inode函数是文件系统的通用函数,其作用是在相应的文件系统中创建一个inode;其主要代码如下(fs/Inode.c):
struct inode *new_inode(struct super_block *sb) {struct inode * inode;inode = alloc_inode(sb);…...return inode;}这里调用了alloc_inode函数分配inode结构(fs/Inode.c):
static struct inode *alloc_inode(struct super_block *sb) {struct inode *inode;if (sb->s_op->alloc_inode)inode = sb->s_op->alloc_inode(sb);elseinode = (struct inode *) kmem_cache_alloc(inode_cachep, GFP_KERNEL); …...}上面有个条件判断:if (sb->s_op->alloc_inode),意思是说如果当前文件系统的超级块有自己分配inode的操作函数,则调用它自己的函数分配inode,否则从公用的高速缓存区中分配一块inode;
3) 创建socket专用inode:
在“socket文件系统注册”一文中后面提到,在安装socket文件系统时,会初始化该文件系统的超级块,此时会初始化超级块的操作指针s_op为sockfs_ops结构;因此此时分配inode会调用sock_alloc_inode函数来完成:
static struct inode *sock_alloc_inode(struct super_block *sb) {struct socket_alloc *ei;ei = kmem_cache_alloc(sock_inode_cachep, GFP_KERNEL);…...return &ei->vfs_inode;}从这里可以看到,实际上分配了一个socket_alloc结构体,该结构体包含socket和inode:
struct socket_alloc {struct socket socket;struct inode vfs_inode;};但最终返回的是该结构体中的inode成员;至此,socket结构和inode结构均分配完毕;分配inode后,应用程序便可以通过文件描述符对socket进行read()/write()之类的操作,这个是由虚拟文件系统(VFS)来完成的。
3、根据inode取得socket对象:
由于创建inode是文件系统的通用逻辑,因此其返回值是inode对象的指针;但这里在创建socket的inode后,需要根据inode得到socket对象;内联函数SOCKET_I由此而来:
static inline struct socket *SOCKET_I(struct inode *inode){return &container_of(inode, struct socket_alloc, vfs_inode)->socket;}再看看container_of宏(include/linux/Kernel.h):
#define container_of(ptr, type, member) ({\const typeof( ((type *)0)->member ) *__mptr = (ptr);\(type *)( (char *)__mptr - offsetof(type,member) );})和offsetof宏(include/linux/Stddef.h):
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
1) offerset(TYPE, MEMBER)宏的作用:返回MEMBER成员在结构体TYPE中的偏移量;
先看一下例子,假设有个结构体A如下:
struct struct_A { char a; int b;}其中,成员a相对于结构的偏移量为0,成员b相对于结构体的偏移量为1;结构体struct_A的变量m在内存中地址结构如下: |
|