亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊(cè) 查看新帖 |

Chinaunix

  平臺(tái) 論壇 博客 文庫(kù)
最近訪問板塊 發(fā)新帖
查看: 1064 | 回復(fù): 0
打印 上一主題 下一主題

內(nèi)核中的TCP的追蹤分析-19-TCP(IPV4)的服務(wù)器端數(shù)據(jù)的接收 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報(bào)告]
發(fā)表于 2008-11-25 10:26 |只看該作者 |倒序?yàn)g覽

在unix的socket分析文章
http://blog.chinaunix.net/u2/64681/showart.php?id=1432584
那樣我們也要分析一下服務(wù)器端是如何接收客戶端發(fā)送的數(shù)據(jù)的,同樣我們結(jié)合使用IP地址通訊的練習(xí)
http://blog.chinaunix.net/u2/64681/showart.php?id=1280050
在那節(jié)中我們看到了服務(wù)器端在建立了與客戶端連接后要通過read(client_sockfd, &ch, 1);來接收客戶端的數(shù)據(jù)。按照
http://blog.chinaunix.net/u2/64681/showart.php?id=1333991
那篇文章的過程細(xì)節(jié)我們不講了,因?yàn)橹饕穆窂蕉际桥cunix完全一樣的,只不過在__sock_recvmsg()函數(shù)中與unix執(zhí)行的函數(shù)調(diào)用不同了,所以我們這里直接從__sock_recvmsg()函數(shù)開始分析,這個(gè)函數(shù)最后是進(jìn)入了socket中的鉤子結(jié)構(gòu)struct proto_ops *ops中的掛入的函數(shù)中去了,我們回憶一下在
http://blog.chinaunix.net/u2/64681/showart.php?id=1360583
IPV4的socket創(chuàng)建那節(jié)中我們看到ops掛入的是inet_stream_ops結(jié)構(gòu)變量。而且在第三節(jié)中我們列出了他的詳細(xì)內(nèi)容
http://blog.chinaunix.net/u2/64681/showart.php?id=1362024
,所以在開始之節(jié)這前我們會(huì)很多的結(jié)合以前的文章進(jìn)行分析,所以當(dāng)朋友們讀這篇文章時(shí)感覺鏈接特別多,這樣幫助朋友們有利于結(jié)合以前的內(nèi)容,好了,我們?yōu)榱朔治龇奖阍儋N一下重要的代碼
static inline int __sock_recvmsg(struct kiocb *iocb, struct socket *sock,
                 struct msghdr *msg, size_t size, int flags)
{
。。。。。。
    return sock->ops->recvmsg(iocb, sock, msg, size, flags);
}
const struct proto_ops inet_stream_ops = {
。。。。。。
    .recvmsg     = sock_common_recvmsg,
。。。。。。
}
很顯然這里的要執(zhí)行的鉤子函數(shù)是sock_common_recvmsg,這個(gè)函數(shù)在/net/core/sock.c中的1852行處
int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock,
            struct msghdr *msg, size_t size, int flags)
{
    struct sock *sk = sock->sk;
    int addr_len = 0;
    int err;
    err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT,
                 flags & ~MSG_DONTWAIT, &addr_len);
    if (err >= 0)
        msg->msg_namelen = addr_len;
    return err;
}
同樣我們會(huì)通過socket得到sock結(jié)構(gòu),進(jìn)而執(zhí)行sock中的鉤子結(jié)構(gòu)變量所掛入的函數(shù),這個(gè)sock的鉤子結(jié)構(gòu)是在
http://blog.chinaunix.net/u2/64681/showart.php?id=1360583
那節(jié)中講述了設(shè)置成了tcp_prot結(jié)構(gòu)變量,并且在那里也列出該變量的詳細(xì)內(nèi)容,我們?cè)倭幸才c上面函數(shù)相關(guān)的部分
struct proto tcp_prot = {
。。。。。。
.recvmsg        = tcp_recvmsg,
。。。。。。
}
所以上面的函數(shù)進(jìn)入了tcp_recvmsg(),這個(gè)函數(shù)在/net/ipv4/tcp.c中的1271行處
int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
        size_t len, int nonblock, int flags, int *addr_len)
{
    struct tcp_sock *tp = tcp_sk(sk);
    int copied = 0;
    u32 peek_seq;
    u32 *seq;
    unsigned long used;
    int err;
    int target;        /* Read at least this many bytes */
    long timeo;
    struct task_struct *user_recv = NULL;
    int copied_early = 0;
    struct sk_buff *skb;
    lock_sock(sk);
    TCP_CHECK_TIMER(sk);
    err = -ENOTCONN;
    if (sk->sk_state == TCP_LISTEN)
        goto out;
    timeo = sock_rcvtimeo(sk, nonblock);
    /* Urgent data needs to be handled specially. */
    if (flags & MSG_OOB)
        goto recv_urg;
    seq = &tp->copied_seq;
    if (flags & MSG_PEEK) {
        peek_seq = tp->copied_seq;
        seq = &peek_seq;
    }
    target = sock_rcvlowat(sk, flags & MSG_WAITALL, len);
函數(shù)非常的長(zhǎng),我們看到上面設(shè)置了一下定時(shí)器,并且檢查了一下socket的狀態(tài),如果還是監(jiān)聽狀態(tài)就說明出錯(cuò)了,因?yàn)槲覀兘邮帐且呀?jīng)在監(jiān)聽成功并且已經(jīng)與客戶端建立連接后進(jìn)行的,這些過程我們前邊的章節(jié)都說過了。
#ifdef CONFIG_NET_DMA
    tp->ucopy.dma_chan = NULL;
    preempt_disable();
    skb = skb_peek_tail(&sk->sk_receive_queue);
    {
        int available = 0;
        if (skb)
            available = TCP_SKB_CB(skb)->seq + skb->len - (*seq);
        if ((available  target) &&
         (len > sysctl_tcp_dma_copybreak) && !(flags & MSG_PEEK) &&
         !sysctl_tcp_low_latency &&
         __get_cpu_var(softnet_data).net_dma) {
            preempt_enable_no_resched();
            tp->ucopy.pinned_list =
                    dma_pin_iovec_pages(msg->msg_iov, len);
        } else {
            preempt_enable_no_resched();
        }
    }
#endif
    do {
        u32 offset;
        /* Are we at urgent data? Stop if we have read anything or have SIGURG pending. */
        if (tp->urg_data && tp->urg_seq == *seq) {
            if (copied)
                break;
            if (signal_pending(current)) {
                copied = timeo ? sock_intr_errno(timeo) : -EAGAIN;
                break;
            }
        }
        /* Next get a buffer. */
        skb = skb_peek(&sk->sk_receive_queue);
        do {
            if (!skb)
                break;
            /* Now that we have two receive queues this
             * shouldn't happen.
             */
            if (before(*seq, TCP_SKB_CB(skb)->seq)) {
                printk(KERN_INFO "recvmsg bug: copied %X "
                 "seq %X\n", *seq, TCP_SKB_CB(skb)->seq);
                break;
            }
            offset = *seq - TCP_SKB_CB(skb)->seq;
            if (tcp_hdr(skb)->syn)
                offset--;
            if (offset  skb->len)
                goto found_ok_skb;
            if (tcp_hdr(skb)->fin)
                goto found_fin_ok;
            BUG_TRAP(flags & MSG_PEEK);
            skb = skb->next;
        } while (skb != (struct sk_buff *)&sk->sk_receive_queue);
如果內(nèi)核打開了網(wǎng)絡(luò)的DMA功能則會(huì)直接從sock結(jié)構(gòu)中的sk_receive_queue接受隊(duì)列中摘取數(shù)據(jù)了,我們將在后邊的客戶端的數(shù)據(jù)發(fā)送中看到如何鏈入到這個(gè)隊(duì)列的,這里我們看到如果支持網(wǎng)絡(luò)的DMA的話就會(huì)直接從接受隊(duì)列中摘取sk_buff數(shù)據(jù)包,如果不支持DMA的話就會(huì)執(zhí)行代碼中的do-while循環(huán)從接受隊(duì)列中計(jì)算數(shù)據(jù)包的序列號(hào)直到挑選符合順序的數(shù)據(jù)包。時(shí)間關(guān)系,明天繼續(xù)。


本文來自ChinaUnix博客,如果查看原文請(qǐng)點(diǎn):http://blog.chinaunix.net/u2/64681/showart_1664386.html
您需要登錄后才可以回帖 登錄 | 注冊(cè)

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號(hào)-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號(hào):11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報(bào)專區(qū)
中國(guó)互聯(lián)網(wǎng)協(xié)會(huì)會(huì)員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請(qǐng)注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP