绑定和分配mmap内核空间(bind_ring)--(七)

本文介绍了PF_RING中套接字绑定的过程,包括bind函数调用的内部实现,以及packet_ring_bind函数的具体操作,如设备查找、旧绑定移除、新绑定添加等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用户态在创建了套接字后,接下来就调用bind函数,绑定套接字,而PF_RING实际做的就是为RING分配相应的空间。也就是说,一个套接字,都有一个与之对应的RING。在前面我们已经提到  sock->ops = &ring_ops;这样当应用空间调用bind函数中,内核调用ring_bind函数;即当系统调用bind触发时,内核ring_bind函数就触发了。下面讲解ring_bind函数;

/* Bind to a device */

static int ring_bind(struct socket*sock, struct sockaddr *sa, int addr_len)

{

 struct sock *sk = sock->sk;

 if(enable_debug)

   printk("[PF_RING] ring_bind() called\n");

  /*

   *     Check legality

  */

 if(addr_len != sizeof(struct sockaddr))

   return -EINVAL;

 if(sa->sa_family != PF_RING)

   return -EINVAL;

 if(sa->sa_data == NULL)

   return -EINVAL;

  /* Safety check: add trailing zero if missing*/

 sa->sa_data[sizeof(sa->sa_data) - 1] = '\0';

  if(enable_debug)

   printk("[PF_RING] searching device %s\n", sa->sa_data);

#if 0

 if(strcmp(sa->sa_data, "any") == 0)

   dev = &any_dev;

 else {

   if((dev = __dev_get_by_name(

#if(LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,24))

                            &init_net,

#endif

                            sa->sa_data))== NULL) {

      if(enable_debug)

       printk("[PF_RING]search failed\n");

      return(-EINVAL);

   }

 }

#endif

 return(packet_ring_bind(sk,sa->sa_data));

}

 

ring_bind 函数前面都是一系列的判断,主要起作用的还是packet_ring_bind函数,函数定义如下:

static int packet_ring_bind(structsock *sk, char *dev_name)

{

 struct pf_ring_socket *pfr = ring_sk(sk);

 struct list_head *ptr, *tmp_ptr;

 ring_device_element *dev = NULL;

 if(dev_name == NULL)

   return(-EINVAL);

 list_for_each_safe(ptr, tmp_ptr, &ring_aware_device_list) {

   ring_device_element *dev_ptr = list_entry(ptr, ring_device_element,device_list);

   if(strcmp(dev_ptr->dev->name, dev_name) == 0) {

      dev = dev_ptr;

      break;

   }

 }

 

 if((dev == NULL) || (dev->dev->type != ARPHRD_ETHER))

   return(-EINVAL);

 if(enable_debug)

   printk("[PF_RING] packet_ring_bind(%s, bucket_len=%d)called\n",

          dev->dev->name, pfr->bucket_len);

 

  /* Remove old binding (by default binding tonone)

     BEFORE binding to a new device

  */

 ring_proc_remove(pfr);

 

  /*

IMPORTANT

Leave this statementhere as last one. In fact when

    the ring_netdev != &none_device_elementthe socket is ready to be used.

  */

 pfr->ring_netdev = dev;

 

  /* Timeto rebind to a new device */

 ring_proc_add(pfr);

  /*As the 'struct net_device' does not containthe number

    of RX queues, we can guess that its numberis the same as the number

    of TX queues. After the first packet hasbeen received by the adapter

    the num of RX queues is updated with thereal value

  */

#if(LINUX_VERSION_CODE >=KERNEL_VERSION(2,6,31))

 pfr->num_rx_channels =pfr->ring_netdev->dev->real_num_tx_queues;

#else

 pfr->num_rx_channels = 1;

#endif

 if(dev == &any_device_element)

   num_any_rings++;

 else {

   if(dev->dev->ifindex < MAX_NUM_IFIDX)

     num_rings_per_device[dev->dev->ifindex]++;

   else

      printk("[PF_RING] INTERNAL ERROR:ifindex %d for %s is > than MAX_NUM_IFIDX\n",

            dev->dev->ifindex, dev->dev->name);

 }

 return(0);

}

 

这个函数的主要作用是创建一个环状缓冲区的socket,然后对socket进行绑定。

<think>好的,我需要帮助用户使用perf工具跟踪malloc相关的系统调用页面错误事件,特别是sys_enter_brksys_enter_mmap。首先,我需要回忆一下perf的基本用法相关的事件类型。 用户提到了引用[2],其中提到可以通过`perf probe --exec=/usr/lib64/libc-2.17.so --add malloc`来添加跟踪函数。这说明用户可能已经尝试过使用perf的probe功能来跟踪malloc。不过,用户现在想通过perf record来跟踪系统调用页面错误事件,而不是仅仅跟踪malloc函数本身。 首先,系统调用的事件在perf中通常属于`raw_syscalls`类别。比如,sys_enter_brksys_enter_mmap属于系统调用的进入点。我需要确认这些事件是否可以被perf record直接监控。根据perf的文档,可以使用`perf list`来列出所有可用的事件。系统调用的事件通常以`syscalls:sys_enter_*`的形式存在,例如`syscalls:sys_enter_brk``syscalls:sys_enter_mmap`。 然后,页面错误的事件是`page-faults`,属于软件事件,可以在`perf list`中找到。因此,用户需要同时监控这三个事件:sys_enter_brk、sys_enter_mmappage-faults。 接下来,我需要构造一个perf record命令,指定这些事件。命令的基本结构应该是: `perf record -e event1,event2,... -- [command]` 不过,需要注意的是,系统调用的事件名称可能需要正确的格式。比如,是否应该使用`syscalls:sys_enter_brk`还是直接使用`sys_enter_brk`。可能需要通过`perf list`确认正确的名称。 另外,用户可能希望跟踪特定进程的调用,因此需要指定要运行的命令,或者附加到正在运行的进程。如果用户想监控整个系统,可能需要使用`-a`选项,但通常更常见的是监控特定命令的执行。 例如,用户要跟踪运行`my_program`时的这些事件,命令可能是: `perf record -e syscalls:sys_enter_brk,syscalls:sys_enter_mmap,page-faults -- ./my_program` 但需要确认事件名称是否正确。比如,在perf list的输出中,系统调用事件可能显示为`syscalls:sys_enter_mmap`,而页面错误是`page-faults`。 另外,用户可能还需要考虑权限问题,执行perf可能需要sudo权限,尤其是在监控系统范围的事件时。因此,可能需要在命令前加上`sudo`。 此外,用户可能希望将这些事件的数据保存到perf.data文件中,以便后续分析。使用`perf record`默认会生成perf.data,之后可以用`perf script`或`perf report`查看结果。 总结步骤: 1. 确认事件名称是否正确,使用`perf list`查找sys_enter_brk、sys_enter_mmappage-faults。 2. 构造perf record命令,包含这些事件。 3. 执行命令,可能需要sudo权限。 4. 分析结果,使用perf script或report。 可能的问题:如果系统调用的事件名称不是syscalls:sys_enter_brk,比如某些系统可能名称不同,需要用户自己确认。另外,mmap可能有多个相关的系统调用,比如mmap2在32位系统中,需要注意。 另外,页面故障的跟踪是否正确,是否需要其他参数。比如,是否还需要跟踪majorminor page faults,但用户可能只需要总的page-faults事件。 最后,用户可能还需要结合引用的资料,比如关于brkmmap的系统调用实现,来理解输出结果。比如引用[4]提到进程地址空间的结构,这可能帮助用户分析内存分配的行为。</think>以下是通过 `perf record` 跟踪 `malloc` 相关系统调用页面故障事件的步骤: --- ### 1. **确认可监控的事件** 首先查看 `perf` 支持的事件,确保系统支持 `sys_enter_brk`、`sys_enter_mmap` `page-faults`: ```bash perf list | grep -E "sys_enter_brk|sys_enter_mmap|page-faults" ``` 输出示例: ``` syscalls:sys_enter_brk [Tracepoint event] syscalls:sys_enter_mmap [Tracepoint event] page-faults [Software event] ``` --- ### 2. **跟踪系统调用页面故障** 使用 `perf record` 同时捕获以下事件: - `sys_enter_brk`:`brk` 系统调用的入口 - `sys_enter_mmap`:`mmap` 系统调用的入口 - `page-faults`:页面故障(缺页中断) **命令示例**: ```bash sudo perf record -e syscalls:sys_enter_brk,syscalls:sys_enter_mmap,page-faults -a -- sleep 10 ``` - `-a`:监控所有 CPU - `sleep 10`:监控 10 秒内的系统活动(替换为实际进程命令,如 `./your_program`) --- ### 3. **分析结果** 生成报告: ```bash sudo perf script ``` 输出会显示事件触发的详细信息,包括进程、调用参数时间戳。例如: ``` mysqld 12345 [001] 1023.456789: syscalls:sys_enter_brk: addr=0x12345000 bash 12346 [002] 1023.456790: page-faults: address=7ffeefbff600 ip=4005f0 ``` --- ### 4. **结合上下文理解输出** - **`brk` 调用**:修改堆顶地址,通常由 `malloc` 触发(小内存分配)[^1] - **`mmap` 调用**:映射匿名内存页,通常由大块内存分配触发[^4] - **页面故障**:内存访问时触发缺页中断,可能涉及物理页分配或页面调入[^3] --- ### 5. **进阶:动态追踪 malloc 调用** 若需直接关联 `malloc` 函数系统调用,可使用 `perf probe` 添加动态探针(需调试符号): ```bash sudo perf probe --add 'malloc' sudo perf record -e probe_libc:malloc -e syscalls:sys_enter_brk -e page-faults -a ``` 此方法可同时捕获 `malloc` 调用后续的 `brk`/`mmap` 行为[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值