注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

gmd20的个人空间

// 编程和生活

 
 
 

日志

 
 

普通tcp socket和 unix domain socket 的非阻塞(non block) write操作相关实现  

2014-09-05 15:19:53|  分类: 程序设计 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
关键字 O_NONBLOCK, MSG_DONTWAIT

------------普通的tcp socket ------------
sock_aio_write     // socket 的 write 文件操作
  do_sock_write
    msg->msg_flags = (file->f_flags & O_NONBLOCK) ? MSG_DONTWAIT : 0;     // 根据文件non block 标志,设置message标志
    sock_sendmsg
      tcp_sendmsg
          timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT);   // 如果是non blocking,这里就返回0 ,导致下面sk_stream_wait_memory快速返回,不会休眠。
               if ((err = sk_stream_wait_memory(sk, &timeo)) != 0) //如果是non block的这里就快速返回,否则应该会休眠的了


----------unix domain socket ---------
source/net/unix/af_unix.c

unix_stream_sendmsg
      skb = sock_alloc_send_pskb(sk, size - data_len, data_len,
                                 msg->msg_flags & MSG_DONTWAIT, &err, // 这里这检查 non block标志了
                                 get_order(UNIX_SKB_FRAGS_SZ));
      skb_queue_tail(&other->sk_receive_queue, skb);   // 直接放到对端的队列里面
      other->sk_data_ready(other);   // 通知对端有新的skb到了
        sock_def_readable



source/net/core/sock.c
void sock_init_data(struct socket *sock, struct sock *sk)
    sk->sk_data_ready       =       sock_def_readable


-----------------------------
syscall  sendmsg 的实现
http://linux.die.net/man/2/sendmsg

source/net/socket.c
SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
                unsigned int, vlen, unsigned int, flags)
{
        if (flags & MSG_CMSG_COMPAT)
                return -EINVAL;
        return __sys_sendmmsg(fd, mmsg, vlen, flags);
}
 ___sys_sendmsg  ()
        if (sock->file->f_flags & O_NONBLOCK)
                msg_sys->msg_flags |= MSG_DONTWAIT;

对一个no block的file/socket 直接调用sendmmsg 函数,底层自动设置MSG_DONTWAIT 的非阻塞方式

--------------------------


看上去整个unix domain socket的 non block发送的操作是不会有休眠的。

-----------------
写个简单的程序验证一下系统实际使用的是阻塞还是非阻塞操作

#! /usr/bin/env stap

probe begin
{
  printf("Start unix domain socket  Probing.....\n\n")
}

probe kernel.function("unix_stream_sendmsg")
{
  /* if  (tid() == ) { */
  if  (pid() == target()) {
    flags = $msg->msg_flags;
    /* #define MSG_DONTWAIT    0x40   Nonblocking io */
    if (flags & 0x40) {
      printf(" non block \n")
    } else {
      printf(" block \n")
      exit()
    }
  }
}
-------------------------

stap -x 15948 unix_domain_socket.stp
打印出来的确实都是non block 操作了


  评论这张
 
阅读(755)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017