当前位置: 首页 > 编程日记 > 正文

linux 保留内核中sas驱动的加载导致crash问题

[root@localhost ~]# uname -a
Linux localhost.localdomain 3.10.0-693.5.2.el7.x86_64 

问题描述,在crash的时候,小内核因为分配中断号失败而触发panic,打印如下:(备注:本文大内核就是指正常运行的内核,小内核是用于kdump收集crash的内核,下同)

[   17.428239] ------------[ cut here ]------------
[   17.433467] kernel BUG at arch/x86/kernel/apic/io_apic.c:1358!
[   17.439916] invalid opcode: 0000 [#1] SMP 
[   17.444670] Modules linked in: mpt3sas(OE+) raid_class scsi_transport_sas i40e(OE) ast i2c_algo_bit ptp drm_kms_helper pps_core syscopyarea sysfillrect sysimgblt fb_sys_fops tta
[   17.465081] CPU: 0 PID: 234 Comm: systemd-udevd Tainted: G           OE  ------------   3.10.0-693.5.2.el7.x86_64 #1
[   17.476265] Hardware name: Insyde Purley/Type2 - Board Product Name1, BIOS 00.1 08/24/2017
[   17.485203] task: ffff880032419fa0 ti: ffff88002bfbc000 task.ti: ffff88002bfbc000
[   17.493359] RIP: 0010:[<ffffffff8105641d>]  [<ffffffff8105641d>] __clear_irq_vector+0x9d/0x100
[   17.502671] RSP: 0000:ffff88002bfbf8a8  EFLAGS: 00010046
[   17.508657] RAX: 0000000000000246 RBX: 00000000000000d6 RCX: 00000000fffffffa
[   17.516473] RDX: 0000000000000001 RSI: ffff880029e1db40 RDI: 00000000000000d6
[   17.524295] RBP: ffff88002bfbf8d0 R08: 0000000000000000 R09: ffff88002e10eb68
[   17.532118] R10: 0000000000000000 R11: ffffea0000ab3b80 R12: ffff880029e1db40
[   17.539943] R13: 0000000000000000 R14: 0000000000000002 R15: ffff880029e1db40
[   17.547761] FS:  00007f749dd4a8c0(0000) GS:ffff880033c00000(0000) knlGS:0000000000000000
[   17.556538] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   17.562961] CR2: 00007f749dd52000 CR3: 0000000032402000 CR4: 00000000003407b0
[   17.570777] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[   17.578593] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[   17.586393] Stack:
[   17.589077]  00000000000000d6 ffff880029e1db40 0000000000000246 0000000000000002
[   17.597247]  0000000000000004 ffff88002bfbf8f8 ffffffff8105803e 0000000000000004
[   17.605413]  00000000000000d6 ffff880029e1db40 ffff88002bfbf938 ffffffff8105902a
[   17.613574] Call Trace:
[   17.616697]  [<ffffffff8105803e>] arch_teardown_hwirq+0x3e/0x70
[   17.623293]  [<ffffffff8105902a>] mp_irqdomain_unmap+0xba/0x100
[   17.629882]  [<ffffffff81136217>] irq_domain_disassociate_many+0xa7/0x130
[   17.637336]  [<ffffffff8113665c>] irq_dispose_mapping+0x3c/0x60
[   17.643922]  [<ffffffff810590f1>] mp_unmap_irq+0x81/0xb0
[   17.649902]  [<ffffffff8104f501>] acpi_unregister_gsi_ioapic+0x31/0x40
[   17.657100]  [<ffffffff8104f407>] acpi_unregister_gsi+0x17/0x20
[   17.663690]  [<ffffffff813af6c3>] acpi_pci_irq_disable+0xb6/0xc6
[   17.670359]  [<ffffffff81564e70>] pcibios_disable_device+0x20/0x30
[   17.677194]  [<ffffffff81369ac6>] do_pci_disable_device+0x56/0x80
[   17.683941]  [<ffffffff81369b38>] pci_disable_device+0x48/0x90
[   17.690421]  [<ffffffffc01979d8>] _base_unmap_resources+0xa8/0xf0 [mpt3sas]
[   17.698028]  [<ffffffffc019f748>] mpt3sas_base_map_resources+0x188/0x710 [mpt3sas]------调用_base_enable_msix--->_base_request_irq失败,注册中断失败。
[   17.706242]  [<ffffffffc01a007c>] mpt3sas_base_attach+0xec/0x9c0 [mpt3sas]
[   17.713763]  [<ffffffffc01a680d>] _scsih_probe+0x6ad/0xb40 [mpt3sas]
[   17.720752]  [<ffffffff8136ca25>] local_pci_probe+0x45/0xa0
[   17.726966]  [<ffffffff8136e0d9>] pci_device_probe+0x109/0x160
[   17.733434]  [<ffffffff81442112>] driver_probe_device+0xc2/0x3e0
[   17.740069]  [<ffffffff81442503>] __driver_attach+0x93/0xa0
[   17.746268]  [<ffffffff81442470>] ? __device_attach+0x40/0x40
[   17.752629]  [<ffffffff8143fce3>] bus_for_each_dev+0x73/0xc0
[   17.758900]  [<ffffffff81441a8e>] driver_attach+0x1e/0x20
[   17.764906]  [<ffffffff81441530>] bus_add_driver+0x200/0x2d0
[   17.771169]  [<ffffffff81442b94>] driver_register+0x64/0xf0
[   17.777345]  [<ffffffff8136d915>] __pci_register_driver+0xa5/0xc0
[   17.784033]  [<ffffffffc01e8000>] ? 0xffffffffc01e7fff
[   17.789757]  [<ffffffffc01e81fa>] _mpt3sas_init+0x1fa/0x1000 [mpt3sas]
[   17.796857]  [<ffffffff810020e8>] do_one_initcall+0xb8/0x230
[   17.803071]  [<ffffffff811019f4>] load_module+0x1f64/0x29e0
[   17.809183]  [<ffffffff8134e0e0>] ? ddebug_proc_write+0xf0/0xf0
[   17.815632]  [<ffffffff810fe093>] ? copy_module_from_fd.isra.42+0x53/0x150
[   17.823029]  [<ffffffff81102626>] SyS_finit_module+0xa6/0xd0
[   17.829209]  [<ffffffff816b78c9>] system_call_fastpath+0x16/0x1b
[   17.835729] Code: 3f 49 8b 7f 08 31 f6 48 c1 fa 03 41 c6 47 18 00 48 83 e2 f8 e8 e5 d9 2d 00 41 f6 47 19 01 75 0d 5b 41 5c 41 5d 41 5e 41 5f 5d c3 <0f> 0b b8 ff ff ff ff 48 c7  
[   17.857031] RIP  [<ffffffff8105641d>] __clear_irq_vector+0x9d/0x100
[   17.863865]  RSP <ffff88002bfbf8a8>
[   17.867900] ---[ end trace 389c806a74c30735 ]---
[   17.999540] Kernel panic - not syncing: Fatal exception
[   18.005310] Kernel Offset: disabled
[   18.135825] Rebooting in 30 seconds..
[   48.141388] ACPI MEMORY or I/O RESET_REG.

串口打印如下:

[   18.291414] mpt3sas version 21.00.00.00 loaded
[   18.306304] mpt3sas_cm0: 32 BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (496792 kB)
[   18.395250] mpt3sas_cm0: IOC Number : 0
[   18.399709] mpt3sas_cm0: CurrentHostPageSize is 0: Setting default host page size to 4k
[   18.419317] mpt3sas0: unable to allocate interrupt 214!

而在大内核中,加载打印如下:

[   11.056440] mpt3sas version 21.00.00.00 loaded
[   11.062317] mpt3sas_cm0: 64 BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (393786508 kB)
[   11.072540] ahci 0000:00:11.5: version 3.0

一开始只注意到分配中断失败,但没有注意到在小内核中是加载的sas驱动是32位模式,在大内核中是64位,所以还以加载驱动有问题。一开始以为是sas驱动的21版本才有这个问题,

回退到系统自带的15版本也有这个问题,所以后面的代码以15版本描述为准,当然修改驱动还是修改的21版本。

走查sas驱动代码,加载的分支在:

static int
_base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev)
{struct sysinfo s;char *desc = NULL;if (sizeof(dma_addr_t) > 4) {const uint64_t required_mask =dma_get_required_mask(&pdev->dev);if ((required_mask > DMA_BIT_MASK(32)) &&!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&!pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {ioc->base_add_sg_single = &_base_add_sg_single_64;ioc->sge_size = sizeof(Mpi2SGESimple64_t);desc = "64";goto out;}}if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))&& !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) {ioc->base_add_sg_single = &_base_add_sg_single_32;ioc->sge_size = sizeof(Mpi2SGESimple32_t);desc = "32";} elsereturn -ENODEV;out:si_meminfo(&s);printk(MPT3SAS_INFO_FMT "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, ""total mem (%ld kB)\n", ioc->name, desc, convert_to_kb(s.totalram));return 0;
}

根据dma_get_required_mask是否大于DMA_BIT_MASK(32)来判断走32位流程还是64位流程。

通过加打印,获取以下大内核中对应的打印是:

 mpt3sas_cm0: required_mask: 0x7fffffffff DMA_BIT_MASK_32: 0xffffffff

而小内核中,对应的打印是:

 mpt3sas_cm0: required_mask: 0x3fffffff DMA_BIT_MASK_32: 0xffffffff

这么说来,小内核中加载32位的驱动是正常的了,是故意为之,取决于保留的内存大小,这个走了弯路。排除了这种可能。

好,那么接下来,继续分析,为什么分配中断失败。先描述调用链:mpt3sas_base_map_resources-->_base_enable_msix-->_base_request_irq-->request_irq-->

我们知道,mpt3sas_driver 和i40e的网卡驱动,都属于pci_dirver.

static struct pci_driver mpt3sas_driver = {
#ifdef MPT2SAS_SCSI.name        = MPT2SAS_DRIVER_NAME,
#else.name        = MPT3SAS_DRIVER_NAME,
#endif /* MPT2SAS_SCSI */.id_table    = mpt3sas_pci_table,.probe        = _scsih_probe,.remove        = scsih_remove,.shutdown    = scsih_shutdown,.err_handler    = &_mpt3sas_err_handler,
#ifdef CONFIG_PM.suspend    = scsih_suspend,.resume        = scsih_resume,
#endif
};static struct pci_driver i40e_driver = {.name     = i40e_driver_name,.id_table = i40e_pci_tbl,.probe    = i40e_probe,.remove   = i40e_remove,
#ifdef CONFIG_PM.suspend  = i40e_suspend,.resume   = i40e_resume,
#endif.shutdown = i40e_shutdown,.err_handler = &i40e_err_handler,.sriov_configure = i40e_pci_sriov_configure,
};

那么,继续推敲中断的注册,看看有没有什么猫腻。

sas的异常,我们修改sas的打印,获取如下:

[   17.397195] mpt3sas0: new add vector: 214, name: mpt3sas0!
[   17.403222] mpt3sas0: unable to allocate interrupt 214, r: -38!--------增加了打印返回值,为-38
[   17.409762] mpt3sas_cm0: _base_unmap_resources

返回值是-38,request_irq调用的是request_threaded_irq---->__setup_irq,这里多说一句,因为这里涉及到中断线程化的一些代码。

一般来说request_irq最终会生成一个irqaction 来调用setup_irq,而setup_irq是__setup_irq的包裹函数,在中断线程化之后,request_threaded_irq调用__setup_irq的上锁过程如下:

    chip_bus_lock(desc);retval = __setup_irq(irq, desc, action);chip_bus_sync_unlock(desc);

而包裹函数setup_irq的上锁过程如下。

int setup_irq(unsigned int irq, struct irqaction *act)
{int retval;struct irq_desc *desc = irq_to_desc(irq);if (WARN_ON(irq_settings_is_per_cpu_devid(desc)))return -EINVAL;chip_bus_lock(desc);retval = __setup_irq(irq, desc, act);chip_bus_sync_unlock(desc);return retval;
}

两者的区别在于使用阶段,在没有slab初始化之前,只能用setup_irq,因为这个时候如果调用kmalloc申请irqaction ,必须是在slab

初始化之后,包括mem_init以及kmem_cache_init。但是对于time_init来说,它位于mem_init代码之前,所以time_init触发的时钟驱动的初始化和注册中断处理函数就没法使用kmalloc来

申请irqaction ,除此之外,并不是所有的中断都可以被线程化,比如时钟中断,主要用来维护系统时间以及定时器等,其中定时器是操作系统的脉搏,一旦被线程化,就有可能被挂起,

有些级联的interrupt controller对应的IRQ也是不能线程化的,所以request_threaded_irq和setup_irq将是一个长期并存的过程,不能线程化的中断具有_IRQ_NOTHREAD标志。

言归正传,下面看__setup_irq 返回出错的地方:

static int
__setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
{struct irqaction *old, **old_ptr;unsigned long flags, thread_mask = 0;int ret, nested, shared = 0;cpumask_var_t mask;if (!desc)return -EINVAL;if (desc->irq_data.chip == &no_irq_chip)return -ENOSYS;--------------返回出错的地方

error.h中
#define ENOSYS 38 /* Function not implemented */

在过去,我们会以IRQ number为index,从irq_desc这个全局数组中直接获取中断描述符。由于我们使能了CONFIG_SPARSE_IRQ,现在则需要从radix tree中搜索使用radix数来存储中断,会减少一些内存占用,所以下面就需要重点分析,为什么这个中断没有初始化chip信息了。

stap -l 'kernel.function("irq_to_desc")'
kernel.function("irq_to_desc@kernel/irq/irqdesc.c:133")

我们来查看调用链,看正常情况下,chip信息在哪初始化的。

_base_enable_msix函数中,既然调用了_base_request_irq,一开始没看到”pci_enable_msix_exact failed“,这个打印,那么在此之上的pci_enable_msix_exact肯定返回正常。

pci_enable_msix_exact-->pci_enable_msix_range-->pci_enable_msix-->msix_capability_init-->arch_setup_msi_irqs-->native_setup_msi_irqs-->setup_msi_irq-->irq_set_chip_and_handler_name就决定了不会返回-38啊

int irq_set_chip(unsigned int irq, struct irq_chip *chip)
{unsigned long flags;struct irq_desc *desc = irq_get_desc_lock(irq, &flags, 0);if (!desc)return -EINVAL;if (!chip)chip = &no_irq_chip;-------------赋值为这个的前提是,传入的chip为NULLdesc->irq_data.chip = chip;irq_put_desc_unlock(desc, flags);/** For !CONFIG_SPARSE_IRQ make the irq show up in* allocated_irqs. For the CONFIG_SPARSE_IRQ case, it is* already marked, and this call is harmless.*/irq_reserve_irq(irq);return 0;
}

而传入给irq_set_chip的chip参数是由setup_msi_irq赋值的,默认为 &msi_chip

int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc,unsigned int irq_base, unsigned int irq_offset)
{struct irq_chip *chip = &msi_chip;---------------chip的默认参数struct msi_msg msg;unsigned int irq = irq_base + irq_offset;int ret;ret = msi_compose_msg(dev, irq, &msg, -1);if (ret < 0)return ret;irq_set_msi_desc_off(irq_base, irq_offset, msidesc);/** MSI-X message is written per-IRQ, the offset is always 0.* MSI message denotes a contiguous group of IRQs, written for 0th IRQ.*/if (!irq_offset)write_msi_msg(irq, &msg);setup_remapped_irq(irq, irq_cfg(irq), chip);irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");-------这个会调用irq_set_chip,见下面。
void
irq_set_chip_and_handler_name(unsigned int irq, struct irq_chip *chip,irq_flow_handler_t handle, const char *name)
{irq_set_chip(irq, chip);----这个chip传入的应该是&msi_chip
__irq_set_handler(irq, handle, 0, name); }

setup_msi_irq传给irq_set_chip_and_handler_name传入的第二个参数,也就是struct irq_chip指针,是&msi_chip,而不是&no_irq_chip,这个就比较奇怪了。

然后跟同事文洋讨论发现,由于打印级别的问题,pci_enable_msix_exact failed不会打印,所以有可能是pci_enable_msix_exact失败了,然后走try_ioapic流程,

然后在try_ioapic流程中,调用_base_request_irq,再次失败,并进入panic流程。

通过加打印,再次修改mpt3sas_base.c文件

#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0))r = pci_enable_msix_exact(ioc->pdev, entries, ioc->reply_queue_count);
#elser = pci_enable_msix(ioc->pdev, entries, ioc->reply_queue_count);
#endif if (r) {dfailprintk(ioc, printk(MPT3SAS_INFO_FMT
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0))"pci_enable_msix_exact "
#else"pci_enable_msix "
#endif"failed (r=%d) !!!\n", ioc->name, r));kfree(entries);flag_caq=5;-----------设置返回标志,看从哪个fail返回的
goto try_ioapic;

获取打印如下,果然是pci_enable_msix 失败了。

[ 18.930924] mpt3sas_cm0: MSI-X vectors supported: 96, no of cores: 1, max_msix_vectors: -1
[ 18.958778] mpt3sas_cm0: pci_enable_msix failed (r=-1)
[ 18.964598] mpt3sas_cm0: caq enter try_ioapic and flag_caq=5

最终一步步加打印,包括修改打印级别,确定是因为中断数不够用了。因为只使能了一个cpu,我们大量的pci设备占用了很多中断。

为了减少中断数量,让保留内核能够生成crash文件,我们做了两个尝试,一个是将大量申请中断的i40e驱动在kdump的配置中屏蔽掉。见《linux 3.10的kdump配置的小坑》描述,

另外一个尝试是使能多个cpu,也能解决这个问题。

转载于:https://www.cnblogs.com/10087622blog/p/7911126.html

相关文章:

四层和七层负载均衡的区别

负载均衡设备也常被称为"四到七层交换机"&#xff0c;那补充&#xff1a;所谓四层就是基于IP端口的负载均衡&#xff1b;七层就是基于URL等应用层信息的负载均衡&#xff1b;同理&#xff0c;还有基于MAC地址的二层负载均衡和基于IP地址的三层负载均衡。换句换说&…

关于数据库,你可能最想知道的几件事

【CSDN 编者按】随着技术不断更新&#xff0c;数据库的发展可谓全面开花&#xff0c;也吸引了越来越多人的关注&#xff0c;但大家真的都足够了解数据库吗&#xff1f;作者 | 易璜珵 责编 | 侯淼淼出品 | 《新程序员》互联网飞速发展的时代里&#xff0c;数据库、中间件和…

Visual C++ 2012/2013的内存溢出检測工具

在过去&#xff0c;每次编写C/C程序的时候&#xff0c;VLD差点儿是我的标配。有了它&#xff0c;就能够放心地敲代码&#xff0c;随时发现内存溢出。 VLD最高可支持到Visual Studio 2012。不知道以后会不会支持Visual Studio 2013&#xff0c;但反正眼下是不支持的。 相关的讨论…

.NetCore Docker

转载于:https://blog.51cto.com/linhongquan/2047736

集生态之力跨城市数字化之难题,英特尔交上了一份完美答卷

随着数字孪生、人工智能、大数据、云计算、区块链等新兴技术的发展成熟&#xff0c;社会正加大步伐向数字化时代迈进。城市&#xff0c;作为社会民生与经济发展的重要载体&#xff0c;自然站在了数字化建设历程的第一线。当然&#xff0c;数字化城市建设并不是搭建“空中楼阁”…

设置Squid Cache_mem大小

squid代理服务器一般的Unix,Linux都自带。我使用的是CentOS 5.3,Squid是自已编译的。 Squid 默认 cache_mem 100 16 256 打开/etc/squid/squid.conf 配置 $vi /etc/squid/squid.conf #http_port ,是代理的端口&#xff0c;如果没有其他的http服务占用80端口或8080&#xf…

centos iptables关于ping

配置iptables策略后&#xff0c;一般来说INPUT都是DROP然后配置需要通过的 当执行&#xff1a; iptables -P INPUT DROP 后&#xff0c;机器就不能被ping通了&#xff01; 因为icmp没有添加到规则中&#xff01; 于是我执行如下代码&#xff1a; iptables -A INPUT -p icmp -j …

禁止蒙层底部页面跟随滚动

场景概述 弹窗是一种常见的交互方式&#xff0c;而蒙层是弹窗必不可少的元素&#xff0c;用于隔断页面与弹窗区块&#xff0c;暂时阻断页面的交互。但是&#xff0c;在蒙层元素中滑动的时候&#xff0c;滑到内容的尽头时&#xff0c;再继续滑动&#xff0c;蒙层底部的页面会开始…

squid日志文件太大,怎样处理?

Squid 默认的&#xff15;天会压缩一次, 在 /etc/logrotate.d/squid中有设置。如果你修改了日志的位置, 请修改 /etc/logrotate.d/squid /home/log/squid/access.log { weekly rotate 5 copytruncate compress notifempty missingok } /home…

安卓系列七(广播机制)

2019独角兽企业重金招聘Python工程师标准>>> 一、什么是广播接收者 广播接收者&#xff08;BroadcastReceiver&#xff09;用于接收广播Intent&#xff0c;广播Intent的发送是通过调用Context.sendBroadcast()、Context.sendOrderedBroadcast()来实现的。通常一个广…

第九代小冰惊喜登场,多端融合且琴棋书画样样精通

谈及智能助手&#xff0c;相信大家都不会漏过小冰这款具有划时代意义的产品。从最初的微软小冰到现在的第九代小冰&#xff0c;AI的技术在不断的演进&#xff0c;而小冰也从最初的贴心助手变成了如今琴棋书画样样精通的人工智能前沿技术载体。 北京时间2021年9月22日&#xff…

C++对象赋值的四种方式

1. 引用作为参数的方式传递. 1 GetObject(Object& obj) 2 { 3 obj.value value1; 4 } 特点: 在外部构造一个对象. 把该对象以引用的方式传递到函数中. 从而实现对该对象的改变, 该参数实质是一个[out]类型的参数, 而非[in]类型的参数. 这里的引用可以称为别名. 点评: …

金九银十,不要跳槽!

前言:又到了求职的金九银十的黄金月份&#xff0c;我相信有不少小伙伴已经摩拳擦掌的准备寻找下一份工作。就目前国内的面试模式来讲&#xff0c;在面试前积极的准备面试&#xff0c;复习整个 Java 知识体系将变得非常重要&#xff0c;可以很负责任地说一句&#xff0c;复习准备…

FreeMarker标签介绍

FreeMarker标签使用 一、FreeMarker模板文件主要有4个部分组成 1、文本&#xff0c;直接输出的部分 2、注释&#xff0c;即<#--...-->格式不会输出 3、插值&#xff08;Interpolation&#xff09;&#xff1a;即${..}或者#{..}格式的部分,将使用数据模型中的部分替代输…

让Squid 显示本地时间

Squid的Error messages 默认的时间显示的GMT时间&#xff0c;而非本地时间&#xff0c;这个有时候看着很别扭。 下面是修改方法&#xff0c;找到Squid的源文件src/errorpage.c 大概在60多行&#xff0c; { ERR_SQUID_SIGNATURE, "\n<BR clear\"all\">\n&…

linux mysql 命令 大全

linux mysql 命令 大全 1.linux下启动mysql的命令&#xff1a; mysqladmin start /ect/init.d/mysql start (前面为mysql的安装路径) 2.linux下重启mysql的命令&#xff1a; mysqladmin restart /ect/init.d/mysql restart (前面为mysql的安装路径) 3.linux下关闭mysql的…

助力5G行业应用扬帆启航,第二届5G毫米波产业高峰论坛圆满召开

当前&#xff0c;5G发展如火如荼&#xff0c;成为引领我国高质量发展的新引擎。5G要想进一步实现向千行百业拓展&#xff0c;离不开全频段的支持&#xff0c;推动5G毫米波发展成为各国共识。为进一步推进5G毫米波产业发展&#xff0c;释放5G全部潜能&#xff0c;助力5G行业应用…

Bootstrap3.x - 源代码分析

参照http://v3.bootcss.com/css/ 文档与源代码colors 比较全面定义总结有意义的颜色。所有uI要用的颜色&#xff0c;都先从已定义的读&#xff0c;这样保证样式的同一性&#xff0c;而且方便以后开发主题库。(建议想自己写css模块的&#xff0c;可以参考一下bootstrap里颜色定义…

清除Squid缓存的小工具

[ 2007-11-2 17:49 | by 张宴 ] 以前我写过一篇《清除指定squid缓存文件的脚本》&#xff0c;但在取URL时存在10%的错误率。如今找到一款老外的程序&#xff0c;可以批量清除某类URL的Squid缓存&#xff0c;支持正则表达式。下载网址&#xff1a;http://www.wa.apana.org.au/~d…

谷歌 AI 编舞师,连张艺兴最喜欢的 Krump 都不在话下

编译 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 舞蹈一直是文化、仪式和庆祝活动的重要组成部分&#xff0c;也是一种自我表达的方式。今天&#xff0c;存在多种形式的舞蹈&#xff0c;从舞厅到迪斯科。然而&#xff0c;舞蹈是一种需要练习的艺术形…

Python 字典(Dictionary)

Python 字典(Dictionary)字典是另一种可变容器模型&#xff0c;且可存储任意类型对象。字典的每个键值(key>value)对用冒号(:)分割&#xff0c;每个对之间用逗号(,)分割&#xff0c;整个字典包括在花括号({})中 ,格式如下所示&#xff1a;d {key1 : value1, key2 : value2 …

Varnish Cache 3.0.0安装

https://www.varnish-cache.org/installation/redhat Installation on RedHat 先按需要的模块 在安装软件包之前首先看看主机上的 automake autoconf libtool ncurses-devel libxslt groff pcre-devel pkgconfig软件包是否已经安装 如果没有那么就要首先安装&#xff…

three.js绘制过程(二)

2019独角兽企业重金招聘Python工程师标准>>> 同一个场景中可以有多个摄像机&#xff0c;同一个屏幕缓冲区可以分块绘制不同的物体。 WeblGLRender 中autoClear 设定为false之后&#xff0c; 每次绘制不会清空缓冲区&#xff1b; setSize 设定canvas的大小 setViewpo…

AI 不可以作为专利认证发明人,“因为它不是人”

编译 | 禾木木 出品 | AI科技大本营&#xff08;ID:rgznai100&#xff09; 英格兰和威尔士上诉法院本周驳回了一名男子的请求&#xff0c;该男子要求法院承认他的人工智能系统为两项专利的发明者。 总部位于美国的 Imagination Engines 的创始人 Stephen Thaler 想要给智能机器…

使用工作集(Working Set)整理项目

Eclipse鼓励将不同的功能模块划分为独立的项目存在&#xff0c;这样不但结构清晰&#xff0c;组织起来还非常灵活&#xff0c;因为我们可以用feature对这些项目进行不同的组合&#xff0c;输出后得到具有不同功能的产品。 不过这样一来Package Explorer里的项目会以更快的速度增…

深入探讨Varnish缓存命中率

也许你还在为刚才动态内容获得7336.76 reqs/s的吞吐率感到振奋&#xff0c;等等&#xff0c;理想和现实是有差距的&#xff0c;你要忍受现实的残酷&#xff0c;别忘了&#xff0c;我们压力测试中的动态内容都处于全缓存情况下&#xff0c;也就是每次请求都命中缓存&#xff0c;…

网易有道词典笔 —— 73 岁“人类高质量”奶奶梅耶马斯克的中文学习之选

继埃隆马斯克发微博称7000年后英语将不复存在后&#xff0c;他的忠实粉丝&#xff0c;同时也是他的母亲——梅耶马斯克也正式开启了学习新语言行动&#xff0c;值得注意的是&#xff0c;梅耶的语种选择是中文。近日&#xff0c;埃隆马斯克的母亲——梅耶马斯克使用有道词典笔学…

Android类库打包方法探究

为什么80%的码农都做不了架构师&#xff1f;>>> 开发Android应用的时候&#xff0c;对于可用于多个应用的公用的部分&#xff0c;或是打算发布给第三方进行应用集成的部分&#xff0c;要把这部分打包成类库怎么做呢? 众所周知&#xff0c;Android应用使用ADT打包成…

大叔也说并行和串行`性能提升N倍(N由操作系统位数和cpu核数决定)

并行是.net4.5主打的技术&#xff0c;同时被封装到了System.Threading.Tasks命名空间下&#xff0c;对外提供了静态类Parallel&#xff0c;我们可以直接使用它的静态方法&#xff0c;它可以并行一个委托数组&#xff0c;或者一个IEnumerable的迭代&#xff0c;而今天主要通过一…

这7个开源技术,支撑起整个互联网时代

转载自 钛媒体 - 这7个开源技术&#xff0c;支撑起整个互联网时代 开源软件现在成为整个互联网时代的支撑技术&#xff0c;你可能已经无法离开由开源软件构建起来的网络世界了。下面我们就来看看一些最重要的开源技术。 为互联网而生的操作系统linux Linux是一款免费的操作系统…