如何得知socket的缓存大小,这个缓存是不是有

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何得知socket的缓存大小,这个缓存是不是有相关的知识,希望对你有一定的参考价值。

参考技术A

  清空socket缓存区的数据的方法


    由于socket是以数据流的形式发送数据,接收方不知道对方一次性发送了多少数据,也能保证对方一次性发送的数据能在同一刻接收到,所以Receive方法是这么工作的:
    接受一个be[]类型的参数作为缓冲区,在经过一定的时间后把接收到的数据填充到这个缓冲区里面,并且返回实际接收到数据的长度,这个实际接收到的数据长度有可能为0(没有接收到数据)、大于0小于缓冲区的长度(接收到数据,但是没有我们预期的多)、等于缓冲区的长度(说明接收到的数据大于等于我们预期的长度)。
    每次接收缓冲区都用同一个byte[] byteMessage,并且你没有检查接收到的数据长度,所以第一次你接收到的数据是123456,第二次你只接收到了8,但是缓冲区里面还有23456,所以加起来就是823456了。
    socket接收缓冲区的大小有讲究,设置大了接收起来慢,因为它要等尽可能多的数据接收到了再返回;设置小了需要重复多次调用接收方法才能把数据接收完,socket有个属性,标识了系统默认的接收缓冲区大小,可以参考这个!
      还有就是用recv读取,但是由于不知道缓存里有多少数据,如果是阻塞模式,到最后必然等到超时才知道数据已经读取完毕,这是个问题。
      另一个是用fgetc,通过返回判断是否是feof:
      whlie (1) a=fgetc(f);if (feof(f)) break;//…
      b=fgetc(f);if (feof(f)) break;//…    当然,我不知道读取完毕后最后一次调用fgetc会不会堵塞,需要测试。
      在非阻塞模式下,我们用recv就可以轻松搞定了,但是阻塞模式下,由于我们不知道缓冲区有多少数据,不能直接调用recv尝试清除。
      使用一个小小的技巧,利用select函数,我们可以轻松搞定这个问题:
      select函数用于监视一个文件描述符集合,如果集合中的描述符没有变化,则一直阻塞在这里,直到超时时间到达;在超时时间内,一旦某个描述符触发了你所关心的事件,select立即返回,通过检索文件描述符集合处理相应事件;select函数出错则返回小于零的值,如果有事件触发,则返回触发事件的描述符个数;如果超时,返回0,即没有数据可读。
      重点在于:我们可以用select的超时特性,将超时时间设置为0,通过检测select的返回值,就可以判断缓冲是否被清空。通过这个技巧,使一个阻塞的socket成了‘非阻塞’socket.
      现在就可以得出解决方案了:使用select函数来监视要清空的socket描述符,并把超时时间设置为0,每次读取一个字节然后丢弃(或者按照业务需要进行处理,随你便了),一旦select返回0,说明缓冲区没数据了(逗超时地了)。
      struct timeval tmOut;tmOut.tv_sec = 0;tmOut.tv_usec = 0;fd_set fds;FD_ZEROS(&fds);FD_SET(skt, &fds);
      int nRet;
      char tmp[2];
      memset(tmp, 0, sizeof(tmp));
      while(1)
       nRet= select(FD_SETSIZE, &fds, NULL, NULL, &tmOut);if(nRet== 0) break;recv(skt, tmp, 1,0);
      这种方式的好处是,不再需要用recv、recvfrom等阻塞函数直接去读取,而是使用select,利用其超时特性检测缓冲区是否为空来判断是否有数据,有数据时才调用recv进行清除。
      有人说同样可以用recv和超时设置去清空啊,这个没错,但是你需要直接对socket描述符设置超时时间,而为了清空数据而直接修改socket描述符的属性,可能会影响到其他地方的使用,造成系统奇奇怪怪的问题,所以,不推荐使用。socket的

如何在 Linux 中获取 CPU 缓存的大小

【中文标题】如何在 Linux 中获取 CPU 缓存的大小【英文标题】:How to get the size of the CPU cache in Linux 【发布时间】:2015-05-13 06:31:52 【问题描述】:

我已经执行了以下查询:

free -m

这个命令的输出是:

           total       used       free     shared    buffers     cached
Mem:        2048       2018         29          5          0       595

我想获取 CPU 缓存的大小。是否可以获取缓存的大小以及这里的缓存有什么用?

【问题讨论】:

你说的是CPU缓存内存还是页面缓存大小(显示为free输出的最后一列)? 【参考方案1】:

如果你想获取 Linux 中 CPU 缓存的大小,最简单的方法是lscpu

$ lscpu | grep cache
L1d cache:             32K
L1i cache:             32K
L2 cache:              256K
L3 cache:              15360K

如果您想获取每个缓存的详细信息,请查看sysfs 文件系统:

$ SYSNODE=/sys/devices/system/node
$ grep '.*' $SYSNODE/node*/cpu*/cache/index*/* 2>/dev/null | 
    awk '-F[:/]' ' printf "%6s %6s %24s %s\n" $6, $7, $9, $10, $11 ; '
node0  cpu0 index0                    level 1
node0  cpu0 index0           number_of_sets 64
node0  cpu0 index0  physical_line_partition 1
node0  cpu0 index0          shared_cpu_list 0,12
node0  cpu0 index0           shared_cpu_map 0000,00001001
node0  cpu0 index0                     size 32K
node0  cpu0 index0                     type Data
node0  cpu0 index0    ways_of_associativity 8
node0  cpu0 index1      coherency_line_size 64

某些缓存实例会被多次看到(每个硬件线程),但您可以在 shared_cpu_list 字段中查看。

【讨论】:

【参考方案2】:

getconf

getconf -a | grep CACHE

给予:

LEVEL1_ICACHE_SIZE                 32768
LEVEL1_ICACHE_ASSOC                8
LEVEL1_ICACHE_LINESIZE             64
LEVEL1_DCACHE_SIZE                 32768
LEVEL1_DCACHE_ASSOC                8
LEVEL1_DCACHE_LINESIZE             64
LEVEL2_CACHE_SIZE                  262144
LEVEL2_CACHE_ASSOC                 8
LEVEL2_CACHE_LINESIZE              64
LEVEL3_CACHE_SIZE                  20971520
LEVEL3_CACHE_ASSOC                 20
LEVEL3_CACHE_LINESIZE              64
LEVEL4_CACHE_SIZE                  0
LEVEL4_CACHE_ASSOC                 0
LEVEL4_CACHE_LINESIZE              0

或单层:

getconf LEVEL2_CACHE_SIZE

这个接口很酷的地方在于它只是 POSIX sysconf C 函数的包装器(缓存参数是非 POSIX 扩展),因此它也可以在 C 代码中使用:

long l2 = sysconf(_SC_LEVEL2_CACHE_SIZE);

在Ubuntu 16.04(Xenial Xerus)上测试。

x86 CPUID 指令

CPUIDx86 指令还提供缓存信息,用户态可以直接访问。

glibc 似乎将该方法用于 x86。我还没有通过逐步调试/指令跟踪确认,但是 2.28 sysdeps/x86/cacheinfo.c 的源代码是这样做的:

__cpuid (2, eax, ebx, ecx, edx);

TODO:创建一个最小的 C 示例,现在懒惰了,问:How to receive L1, L2 & L3 cache size using CPUID instruction in x86

ARM 还具有架构定义的机制,可通过缓存大小 ID 寄存器 (CCSIDR) 等寄存器查找缓存大小,请参阅ARMv8 Programmers' Manual 11.6“缓存发现”了解概述。

【讨论】:

【参考方案3】:

对于运行 Linux 的 ARM CPU(在带有 Raspbian(32 位)的 Raspberry Pi 3B+ 上测试):

《Arm® Cortex®-A53 MPCore处理器技术参考手册》中有一章,“缓存大小选择寄存器”“缓存大小ID寄存器”,包括汇编指令。

这些汇编指令已经作为函数在 Linux 内核头文件 asm/cachetype.h 中可用:set_csselr(...) 和 read_ccsidr(),但是这些函数不能在用户模式下调用,所以我们需要构建一个内核模块来获取/打印值:

生成文件:

obj-m += cachesize.o

all:

    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:

    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

文件cachesize.c

#include <asm/cachetype.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Abc defg");
MODULE_DESCRIPTION("Find out ARM cache sizes");
MODULE_VERSION("0.01");

static int __init lkm_example_init(void) 
// Must run in kernel mode
// Assumptions: L1 (instructions + data), L2 (check your CPU manual)
 set_csselr(0);
 printk(KERN_INFO "ccsidr L1 data cache = %08x\n", read_ccsidr());
 set_csselr(1);
 printk(KERN_INFO "ccsidr L1 instruction cache = %08x\n", read_ccsidr());
 set_csselr(2);
 printk(KERN_INFO "ccsidr L2 unified = %08x\n", read_ccsidr());
 return 0;


static void __exit lkm_example_exit(void) 
 printk(KERN_INFO "Goodbye, World!\n");


module_init(lkm_example_init);
module_exit(lkm_example_exit);

然后:

make
insmode cachesize.ko
rmmod cachesize
dmesg | tail
# Compare numbers to the table "CCSIDR encodings" in the "ARM ... Technical Reference Manual"

【讨论】:

欢迎来到 Stack Overflow。 Stack Overflow 上不鼓励仅使用代码的答案,因为它们没有解释它是如何解决问题的。请编辑您的答案以解释此代码的作用以及它如何回答问题,以便它对 OP 以及其他有类似问题的用户有用。【参考方案4】:

在我的虚拟机中(Linux dhcppc4 2.6.32-71.el6.i686 #1 SMP Wed Sep 1 01:26:34 EDT 2010 i686 i686 i386 GNU/Linux),我找不到 /sys /devices/system/node,但 lscpu 肯定会给出详细信息。

我在/sys/devices/system/cpu/cpu0/cache/*看到了更多信息:

cat /sys/devices/system/cpu/cpu0/cache/index0/size

输出

32K

【讨论】:

以上是关于如何得知socket的缓存大小,这个缓存是不是有的主要内容,如果未能解决你的问题,请参考以下文章

linux下socket接收缓冲区有多大?如何查看和修改,望高手赐教

如何测量 .NET 内存缓存 4.0 的当前大小?

计算缓存大小和清空缓存

linux c使用socket进行http 通信,并接收任意大小的http响应

如何在 Linux 中获取 CPU 缓存的大小

如何查找文件是不是在 Windows 的文件系统缓存中?