免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1392 | 回复: 0
打印 上一主题 下一主题

读核日记socket篇 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2004-11-15 16:56 |只看该作者 |倒序浏览

今天被一个sock_fd的值的问题折磨了半天
靠,干脆花了1个小时看了一下内核
貌似效果不错,做个笔记
pblog的缩进还挺麻烦的,不管它了
可以直接找我要文件,如果看起来不爽的话
/*
网络编程中要注意描述符的边界问题
比如socket描述符等
描述符等于0的情况也是正常的
if (sock >= 0) //应该按照 sock >= 0的情况来判断
...
如果是
if (sock > 0)
... //可能出现的问题是,tcp连接不能建立,包不能正确传送或者不能传送

值为0属于正常情况
我考,看socket源代码,日
socket也是加入系统标用表中的系统函数,参考 /kernel/sys.c
*/
// /net/core/sock.c
// /net/socket.c
/* 入口函数 sys_socket();
* 原型: asmlinkage long sys_socket(int family, int type, int protocol);
* 调用函数 socket();
* 原型: int socket(int domain, int type, int protocol);
* 两者应该是对应起来的
* 取值范围
* 参考 /include/linux/socket.h address family的两组宏定义 */
asmlinkage long sys_socket(int family, int type, int protocol)
{
int retval;
struct socket *sock;
//创建socket,由此可以看出socket是非负整数值
retval = sock_create(family, type, protocol, &sock);
if (retval
//加入描述符表,呵呵
retval = sock_map_fd(sock);
if (retval
out:
/* It may be already another descriptor 8) Not kernel problem. */
// 正常返回,创建失败返回
return retval;
out_release:
sock_release(sock);
return retval;
}
/* sock_create 最终调用到 函数 __sock_create()
* 函数名字前面加两个dash的表示系统内部函数
*
*
*/
static int __sock_create(int family, int type, int protocol, struct socket **res, int kern)
{
int i;
int err;
struct socket *sock;
/*
  * Check protocol is in range
  */
if (family = NPROTO)
  return -EAFNOSUPPORT;
if (type = SOCK_MAX)
  return -EINVAL;
/* Compatibility.
    // ugly 丑陋的
    // moron 低能,白痴
    // 避免加载模块时死锁
    This uglymoron is moved from INET layer to here to avoid
    deadlock in module load.
  */
// 协议族参考 /include/asm-i386/socket.h
if (family == PF_INET && type == SOCK_PACKET) {//PF_INET == AF_INET --> Internet IP Protocol
  static int warned;
  if (!warned) {
   warned = 1;
   printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)n", current->comm);
  }
  family = PF_PACKET; //packet family
}
        //是否和filter结合在一起的?
err = security_socket_create(family, type, protocol, kern);
if (err)
  return err;
  
#if defined(CONFIG_KMOD)
/* Attempt to load a protocol module if the find failed.
  *
  * 12/09/1996 Marcin: But! this makes REALLY only sense, if the user
  * requested real, full-featured networking support upon configuration.
  * Otherwise module support will break!
  */
if (net_families[family]==NULL)
{
  request_module("net-pf-%d",family);
}
#endif
net_family_read_lock();
if (net_families[family] == NULL) {
  i = -EAFNOSUPPORT;
  goto out;
}
/*
* Allocate the socket and allow the family to set things up. if
* the protocol is 0, the family is instructed to select an appropriate
* default.
*/
        //分配资源,日哦,分配inode
if (!(sock = sock_alloc()))
{
  printk(KERN_WARNING "socket: no more socketsn");
  i = -ENFILE;  /* Not exactly a match, but its the
        closest posix thing */
  goto out;
}
//赋值啦
sock->type  = type;
//refcnt 引用计数器
/*
  * We will call the ->create function, that possibly is in a loadable
  * module, so we have to bump that loadable module refcnt first.
  */
i = -EAFNOSUPPORT;
if (!try_module_get(net_families[family]->owner))
  goto out_release;
if ((i = net_families[family]->create(sock, protocol)) ops->owner)) {
  sock->ops = NULL;
  goto out_module_put;
}
/*
  * Now that we're done with the ->create function, the [loadable]
  * module can have its refcnt decremented
  */
module_put(net_families[family]->owner);
*res = sock;
security_socket_post_create(sock, family, type, protocol, kern);
out:
net_family_read_unlock();
return i;
out_module_put:
module_put(net_families[family]->owner);
out_release:
sock_release(sock);
goto out;
}
/*
* Obtains the first available file descriptor and sets it up for use.
* 取得第一个可用的描述符,并设置给它,它就是我们的返回值
* This function creates file structure and maps it to fd space
* of current process. On success it returns file descriptor
* 为当前进程建立并映射文件描述符,成功返回描述符,值保存在sock->file中
* and file struct implicitly stored in sock->file.
* Note that another thread may close file descriptor before we return
* from this function. We use the fact that now we do not refer
* to socket after mapping. If one day we will need it, this
* function will increment ref. count on file by 1.
* 其他线程在函数返回之前可能关闭描述符,因此映射之后我们并不socket(靠,这是什么意思
* 只建立并映射socket,但不是可用的?,日),在我们需要调用到描述符的时候
* 对引用计数器加1
* In any case returned fd MAY BE not valid!
* 任何情况下返回文件描述符可能都是无效的
* This race condition is unavoidable
* with shared fd spaces, we cannot solve it inside kernel,
* 这种竞争情况无可避免(指不同线程对文件描述符操作的竞争),在内核中这个问题不能解决
* but we take care of internal coherence yet. //这个不好翻译
*/

int sock_map_fd(struct socket *sock)
{
int fd;
/*
   * "quick string" -- eases parameter passing, but more importantly
   * saves "metadata" about the string (ie length and the hash).
   *
   * hash comes first so it snuggles against d_parent and d_bucket in the
   * dentry.
   * struct qstr {
  * unsigned int hash;
  * const unsigned char *name;
  * unsigned int len;
  * };
   */
struct qstr this;
char name[32];
/*
  * Find a file descriptor suitable for return to the user.
  */
//取得第一个可用的文件描述符
fd = get_unused_fd();
if (fd >= 0) {//成功
  struct file *file = get_empty_filp();//取得一个可用的文件结构
  if (!file) {//没有取得
   put_unused_fd(fd); //释放文件描述符
   fd = -ENFILE;
   goto out;
  }
  sprintf(name, "[%lu]", SOCK_INODE(sock)->i_ino);
  this.name = name;
  this.len = strlen(name);
  this.hash = SOCK_INODE(sock)->i_ino;
  //日,这里又分配什么?
  file->f_dentry = d_alloc(sock_mnt->mnt_sb->s_root, &this);
  if (!file->f_dentry) {//失败
   put_filp(file);
   put_unused_fd(fd);
   fd = -ENOMEM;
   goto out;
  }
  file->f_dentry->d_op = &sockfs_dentry_operations;
  d_add(file->f_dentry, SOCK_INODE(sock));
  file->f_vfsmnt = mntget(sock_mnt);//原语操作
  file->f_mapping = file->f_dentry->d_inode->i_mapping;
  sock->file = file;
  file->f_op = SOCK_INODE(sock)->i_fop = &socket_file_ops;
  file->f_mode = FMODE_READ | FMODE_WRITE;
  file->f_flags = O_RDWR;
  file->f_pos = 0;
  fd_install(fd, file);//安装文件描述符
}
out:
return fd;
}


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/652/showart_5553.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP