Socket通信之Write实现流程

来源:互联网 发布:如何解除8080端口占用 编辑:程序博客网 时间:2024/05/21 19:27

1 分析write在进程间通信的实现过程

       在内核中,socket是与文件指针挂钩的,因此就可以通过open、read、write像操作文件一样对socket进行操作;而write的过程相当于socket数据发送的过程。接下来,我们研究socket的数据发送流程。

1、从socket (AF_UNIX, SOCK_STREAM, 0)入手,经过跟踪会调到unix_create函数

 static int unix_create(struct net *net, struct socket *sock, int protocol){    switch (sock->type) {    case SOCK_STREAM:       sock->ops = &unix_stream_ops;       break;         }    return unix_create1(net, sock) ? 0 : -ENOMEM;}

下面是socket函数的操作集

staticconst struct proto_ops unix_stream_ops = {   .family =   PF_UNIX,   .sendmsg =  unix_stream_sendmsg,   .recvmsg =  unix_stream_recvmsg,};

Write操作是通过调用unix_stream_sendmsg来实现的。

1.2 unix_stream_sendmsg函数

 

图1  函数实现示意图

 

 (1)scm_send(sock,msg, siocb->scm); 将进程的信息写入scm中;

         (2)other= unix_peer(sk); 通过unix_peer得到目标地址的sock,并赋值给other指针;

         (3)skb= sock_alloc_send_skb(sk, size, msg->msg_flags&MSG_DONTWAIT, &err); 函数分配skb即sk_buff缓冲结构了,这个结构是用于底层通讯的缓冲区;

         (4)memcpy(UNIXCREDS(skb),&siocb->scm->creds, sizeof(struct ucred)); 将我们上面准备的身份信息scm拷贝到这个结构skb中;

        (5)memcpy_fromiovec(skb_put(skb,size), msg->msg_iov, size);复制我们应用程序中要发送的数据到缓冲空间;

        (6)如果目标方的sock被关闭,程序将跳到pipe_err_free,然后会发送SIGPIPE信号量,当前进程收到SIGPIPE信号后,默认执行的动作是关闭进程;

if (sock_flag(other, SOCK_DEAD)||(other->sk_shutdown & RCV_SHUTDOWN))     gotopipe_err_free;pipe_err_free:send_sig(SIGPIPE, current, 0);

         否则,执行skb_queue_tail(&other->sk_receive_queue,skb);将缓冲区挂入到目标方的sock的sk_receive_queue队列头中。

        (7)scm_destroy(siocb->scm);       释放scm占用的空间

这样就结束unix_stream_sendmsg函数。


0 0
原创粉丝点击