alloc_skb()

2023-12-05 12:32
文章标签 alloc skb

本文主要是介绍alloc_skb(),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

 

sock_alloc_send_pskb() --> alloc_skb()

    alloc_skb()用于分配缓冲区的函数。由于"数据缓冲区"和"缓冲区的描述结构"(sk_buff结构)是两种不同的实体,这就意味着,在分配一个缓冲区时,需要分配两块内存(一个是缓冲区,一个是缓冲区的描述结构sk_buff)。

/usr/src/linux-2.6.19/include/linux/skbuff.h
static inline struct sk_buff *alloc_skb(unsigned int size,
                                        gfp_t    priority)
{
    return __alloc_skb(size, priority, 0);
}



    __alloc_skb()调用kmem_cache_alloc()从缓存中获取一个sk_buff结构,并调用 kmalloc_track_caller 分配缓冲区

/usr/src/linux-2.6.19/net/core/skbuff.c
struct sk_buff *
__alloc_skb (unsigned int size, gfp_t gfp_mask,
                int fclone)
{
    kmem_cache_t           *cache;
    struct skb_shared_info *shinfo;
    struct sk_buff         *skb;
    u8                     *data;
    cache = fclone ? skbuff_fclone_cache : skbuff_head_cache;
    skb = kmem_cache_alloc(cache, gfp_mask & ~__GFP_DMA);
    if (!skb)
        goto out;
    size = SKB_DATA_ALIGN(size);
    data = kmalloc_track_caller(size + sizeof(struct skb_shared_info),
            gfp_mask);
    if (!data)
        goto nodata;
    memset(skb, 0, offsetof(struct sk_buff, truesize));
    skb->truesize = size + sizeof(struct sk_buff);
    atomic_set(&skb->users, 1);
    skb->head = data;
    skb->data = data;
    skb->tail = data;
    skb->end = data + size;
    shinfo = skb_shinfo(skb);
    atomic_set(&shinfo->dataref, 1);
    shinfo->nr_frags = 0;
    shinfo->gso_size = 0;
    shinfo->gso_segs = 0;
    shinfo->gso_type = 0;
    shinfo->ip6_frag_id = 0;
    shinfo->frag_list = NULL;
    if (fclone) {
        struct sk_buff *child = skb + 1;
        atomic_t *fclone_ref = (atomic_t *) (child + 1);
        skb->fclone = SKB_FCLONE_ORIG;
        atomic_set(fclone_ref, 1);   
        child->fclone = SKB_FCLONE_UNAVAILABLE;
    }
out:
    return skb;
nodata:
    kmem_cache_free(cache, skb);
    skb = NULL;
    goto out;
}


    alloc_skb(size, gpf_mask) allocates memory for a socket buffer structure and the corresponding packet memory. In this case, size specifies the size of the packet data space, where this space will be increased (aligned) to the next 16-bit address

    In the creation of a new socket buffer, no immediate attempt is made to allocate the memory with kmalloc() for the sk_buff structure; rather, an attempt is made to reuse previously consumed sk_buff structures. Note that requesting memory in the kernel's storage management is very expensive and that, because structures of the same type always require the same size, an attempt is first made to reuse an sk_buff structure no longer required.

There are two different structures that manage consumed socket buffer structures:
    First, each CPU manages a so-called skb_head_cache that stores packets no longer needed. This is a simple socket buffer queue, from which alloc_skb() takes socket buffers.
    Second, there is a central stack for consumed sk_buff structures (skbuff_head_cache).

    If there are no more sk_buff structures available for the current CPU, then kmem_cache_alloc() is used to try obtaining a packet from the central socket-buffer cache (skbuff_head_cache). If this attempt fails, then kmalloc() is eventually used. gfp_mask contains flags required to reserve memory.

    Using these two caches can be justified by the fact that many packets are created and released in a system (i.e., the memory of sk_buff structures is frequently released), only to be required again shortly afterwards. The two socket buffer caches were introduced to avoid this expensive releasing and reallocating of memory space by the storage management (similarly to first-level and second-level caches for CPU memory access). This means that the time required to release and reserve sk_buff structures can be shortened. When kmem_cache_alloc() is used to reserve an sk_buff structure, the function skb_header_init() is called to initialize the structure. It will be described further below.

    Naturally, for the sk_buff structure, a socket buffer requires memory for the packet data. Because the size of a packet is usually different from and clearly bigger than that of an sk_buff structure, a method like the socket-buffer cache does not provide any benefit. The packet data space is reserved in the usual way (i.e., by use of kmalloc()).

    The pointers head, data, tail, and end are set once memory has been reserved for the packet data. The counters user and datarefp (number of references to these socket buffer structure) are set to one. The data space for packets begins to grow from the top (data) (i.e., at that point, the socket buffer has no headroom and has tailroom of size bytes).

这篇关于alloc_skb()的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/457573

相关文章

iOS中alloc与init

面向对象的3大特性,封装继承和多态. 我遇到过封装相关的问题,因为初级封装简单,常常暴露出被你封装的接口,进一步进行高级封装隐藏接口的时候才发现,封装是一门学问,而这门学问得从最基础的alloc与init讲起.   FatherModel.h #import <Foundation/Foundation.h>@interface FatherModel : NSObject@en

内存管理篇-07页分配器接口-alloc_page

-----终于到了编码实战阶段了,前面都是在将思想和实现机制,即使看了源代码还是模模糊糊,不够清晰。         本节通过内核接口从伙伴系统进行申请和释放内存。free_page && alloc_page。其实很多缓存机制最终都是通过伙伴系统申请一大片内存,然后内部再进行对这些页处理优化。         伙伴系统提供了free_page和alloc_pages两个函数进行申请和释放内存

register_chrdev_region alloc_chrdev_region

在调用 cdev_add()函数向系统注册字符设备之前,应首先调用 register_chrdev_region()或 alloc_chrdev_region() 函数向系统申请设备号,这两个函数在 <linux/fs.h>中可以找到,其原型是: 引用 int  register_chrdev_region( dev_t  first ,  unsigned int  count ,

Linux内核 -- 内存分配之 page_frag_alloc 函数的作用与用法

page_frag_alloc 函数的作用与用法 page_frag_alloc 函数是 Linux 内核中的一个内存分配函数,主要用于分配小块内存,以减少内存碎片,提高内存使用效率。它在网络子系统中被广泛使用,比如在发送和接收数据包时,需要频繁地分配和释放小块内存。page_frag_alloc 提供了一种高效的方式来处理这种小块内存的需求。 函数原型 void *page_frag_al

#warning mark 去掉tabBar上面的阴影线 //去掉黑色线 [self.tabBar setShadowImage:[[UIImage alloc] init]];

#warning mark 去掉tabBar上面的阴影线    //去掉黑色线    [self.tabBar setShadowImage:[[UIImage alloc] init]];

网络设备中的SKB_BUFF

声明:原文摘抄自潘友华老师。 一. SKB_BUFF的基本概念 1. 一个完整的skb buff组成 (1) struct sk_buff–用于维护socket buffer状态和描述信息 (2) header data–独立于sk_buff结构体的数据缓冲区,用来存放报文分组,使各层协议的header存储在连续的空间中,以方便协议栈对其操作 (3) struct skb_shared_

【linux软件基础知识】-cdev_alloc

struct cdev *cdev_alloc(void){struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL);if <

Logcat 总提示D/dalvikvm : GC_FOR_ALLOC freed

出现这总情况一般是界面不停的加载和释放图片的原因。 若不知道是哪里不停的加载和释放图片,可以用DDMS追踪抓出元凶。 例如我的程序启动后,Logcat里面不停的打印下面的信息: 12-07 08:15:18.514: D/dalvikvm(19719): GC_FOR_ALLOC freed 921K (22), 34% free 4222K/6332K, paused 20

skb_dst_set - struct dst_entry dst 路由子系统使用。

现在有一个需求,使用netfilter框架,在NF_IP_FORWARD点做钩子。 把钩到的包从指定的物理接口发出去,这个怎么实现?哪个大侠能举个例子,谢谢 1、偿试修改skb_buff->dev,死机 2、偿试修改skb_buff->mac_header,死机 在NF_IP_FORWARD点,已经决定了路由,也就说决定了从哪个物理网口出了。要想实现从指定的物理接口出来,需要

alloc、init你弄懂50%了吗?

转载链接:http://www.cocoachina.com/ios/20160627/16823.html 作者: 伯乐在线 - 码了戈壁 作者真的很用心,真心感谢! 前言 这是一篇我记录对alloc、init分析思考的笔记。如果读者想看懂我的第二个思考,可能需要您至少了解内存的分段分页管理,如果您对其一点都不知道,可以先看这篇软文简单了解一下。另外很重要的一点是,请先思考。