m_pullup 观后感

来源:互联网 发布:深度 linux 编辑:程序博客网 时间:2024/05/02 04:47

uipc_mbuf.c

/*
 * Rearange an mbuf chain so that len bytes are contiguous
 * and in the data area of an mbuf (so that mtod and dtom
 * will work for a structure of size len).  Returns the resulting
 * mbuf chain on success, frees it and returns null on failure.
 * If there is room, it will add up to max_protohdr-len extra bytes to the
 * contiguous region in an attempt to avoid being called next time.
 */
int MPFail;

struct mbuf *
m_pullup(n, len)
    register struct mbuf *n;
    int len;
{//n 要处理的m_buf; len 首个mbuf需保存的数据量
    register struct mbuf *m;
    register int count;
    int space;

    /*
     * If first mbuf has no cluster, and has room for len bytes
     * without shifting current data, pullup into it,
     * otherwise allocate a new mbuf to prepend to the chain.
     */

   //m_buf没有使用簇,并且可以拥有len长度的数据,有后续的m_buf
    if ((n->m_flags & M_EXT) == 0 &&
        n->m_data + len < &n->m_dat[MLEN] && n->m_next) {

        //如果已有数据的长度达到len,直接返回
        if (n->m_len >= len)
            return (n);

        //设置len为将要从后续m_buf中拷贝的数据量
        m = n;
        n = n->m_next;
        len -= m->m_len;
    } else {

       //m_buf使用了簇或者现有m_buf无法保存len长度数据
        if (len > MHLEN)
            goto bad;

        //创建m_buf,拷贝M_PKTHDR,并且将原m_buf的M_PKTHDR标志清除
        MGET(m, M_DONTWAIT, n->m_type);
        if (m == 0)
            goto bad;
        m->m_len = 0;
        if (n->m_flags & M_PKTHDR) {
            M_COPY_PKTHDR(m, n);
            n->m_flags &= ~M_PKTHDR;
        }
    }

    //现有可以拷贝的空间
    space = &m->m_dat[MLEN] - (m->m_data + m->m_len);
    do {

        //计算合理的count值:)
        count = min(min(max(len, max_protohdr), space), n->m_len);

        //拷贝,修改变量值
        bcopy(mtod(n, caddr_t), mtod(m, caddr_t) + m->m_len,
          (unsigned)count);
        len -= count;
        m->m_len += count;
        n->m_len -= count;
        space -= count;
        if (n->m_len)
            n->m_data += count;
        else

        //如果n数据都拷完了,free
            n = m_free(n);

        //检查是否已copylen长度的数据或者n数据已考完
    } while (len > 0 && n);
    if (len > 0) {
        (void) m_free(m);
        goto bad;
    }
    m->m_next = n;
    return (m);
bad:
    m_freem(n);
    MPFail++;
    return (0);
}