Chinaunix首页 | 论坛 | 博客
  • 博客访问: 302019
  • 博文数量: 47
  • 博客积分: 1411
  • 博客等级: 上尉
  • 技术积分: 500
  • 用 户 组: 普通用户
  • 注册时间: 2006-02-23 09:10
文章分类

全部博文(47)

文章存档

2009年(3)

2008年(4)

2007年(14)

2006年(26)

我的朋友

分类: LINUX

2006-02-27 18:52:09

      之所以我会提及这个古怪的技术点(似乎很少有书及文章涉及),是因为在kernel里写网络通讯module时碰到了一个问题。
      参考khttpd的代码,很多kernel里建立使用socket的问题很容易解决,担khttpd并没有将socket和VFS联系起来,因为它压根不需要将socket暴露给userspace。Otherwise,我需要。socket挂载到VFS的代码都在sock_map_fd() 函数里边。它负责将创建的file结构安装到进程files数组中,当然创建file结构还包括创建inode,dentry等等。创建是没问题了,但在内核里释放这个socket就会有点麻烦,当然由应用层去调用sys_close是最好,但内核释放时没那么简单。既然file在socket之后创建,那么我们先释放file,然后是socket,于是我这么写: fput(sock); sock_release(sock); 逻辑关系很好,但一debug就panic。仔细研究一下kernel发现sock_release是多余的。请看下面分析:
       网络层在linux下和普通的块/字符设备层由很大区别,首先来看在VFS上创建一个socket file:
  
  sprintf(name, "[%lu]", sock->inode->i_ino); /* 晕,原来目录项的名字就是inode号 */
  this.name = name;
  this.len = strlen(name);
  this.hash = sock->inode->i_ino;
  file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this); /* 创建目录项 */
  file->f_dentry->d_op = &sockfs_dentry_operations; /* 目录项操作,基本都是空函数 */
  d_add(file->f_dentry, sock->inode); /* 链接inode于dentry */
  file->f_vfsmnt = mntget(sock_mnt); /* socket 层自己的mnt结构,就像是挂载一个hdd一样 */
  sock->file = file;
  file->f_op = sock->inode->i_fop = &socket_file_ops; /* 文件操作集,用户可以用write/read 来代替send/recv */
  file->f_mode = 3;
  file->f_flags = O_RDWR;
  file->f_pos = 0;
  
很显然用户就可以想操作普通文件那样操作socket,当然包括release操作。release操作里边真正的动作就是上面我们提到的sock_release()。再来看fput做什么:
 
  if (file->f_op && file->f_op->release)
   file->f_op->release(inode, file);

呵呵,很清楚它call了release,所以只要一个fput就可以即释放file又释放socket了。
所以socket层的行为很古怪,它可以用socket原语操作又可以用file原语操作,本质上它不应该需要VFS,但linux让VFS变的如此强大,就连socket也被拉过来了。
阅读(1886) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~