irqbalance

article/2025/11/7 6:55:16

http://www.bubuko.com/infodetail-1129360.html

irqbalance 理论上:
启用 irqbalance 服务,既可以提升性能,又可以降低能耗。
irqbalance 用于优化中断分配,它会自动收集系统数据以分析使用模式,并依据系统负载状况将工作状态置于 Performance mode 或 Power-save mode。
处于 Performance mode 时,irqbalance 会将中断尽可能均匀地分发给各个 CPU core,以充分利用 CPU 多核,提升性能。
处于 Power-save mode 时,irqbalance 会将中断集中分配给第一个 CPU,以保证其它空闲 CPU 的睡眠时间,降低能耗。
但实际中往往影响cpu的使用均衡,建议服务器环境中关闭。


http://www.it165.net/os/html/201301/4427.html

irqbalance项目的主页在这里

irqbalance用于优化中断分配,它会自动收集系统数据以分析使用模式,并依据系统负载状况将工作状态置于 Performance mode 或 Power-save mode。处于Performance mode 时,irqbalance 会将中断尽可能均匀地分发给各个 CPU core,以充分利用 CPU 多核,提升性能。
处于Power-save mode 时,irqbalance 会将中断集中分配给第一个 CPU,以保证其它空闲 CPU 的睡眠时间,降低能耗。

在RHEL发行版里这个守护程序默认是开机启用的,那如何确认它的状态呢?


view source print ?
1. # service irqbalance status
2. irqbalance (pid PID) is running…


 

然后在实践中,我们的专用的应用程序通常是绑定在特定的CPU上的,所以其实不可不需要它。如果已经被打开了,我们可以用下面的命令关闭它:


view source print ?
1. # service irqbalance stop
2. Stopping irqbalance: [ OK ]

或者干脆取消开机启动:


view source print ?
1. # chkconfig irqbalance off

下面我们来分析下这个irqbalance的工作原理,好准确的知道什么时候该用它,什么时候不用它。

既然irqbalance用于优化中断分配,首先我们从中断讲起,文章很长,深吸一口气,来吧!


摘抄重点:

SMP affinity is controlled by manipulating files in the /proc/irq/ directory.
In /proc/irq/ are directories that correspond to the IRQs present on your
system (not all IRQs may be available). In each of these directories is
the “smp_affinity” file, and this is where we will work our magic.


说白了就是往/proc/irq/N/smp_affinity文件写入你希望的亲缘的CPU的mask码! 关于如何手工设置中断亲缘性

接着普及下概念,我们再来看下CPU的拓扑结构,首先看下Intel CPU的各个部件之间的关系:

 

cpu-term0

一个NUMA node包括一个或者多个Socket,以及与之相连的local memory。一个多核的Socket有多个Core。如果CPU支持HT,OS还会把这个Core看成 2个Logical Processor。

可以看拓扑的工具很多lscpu或者intel的cpu_topology64工具都可以

这次用之前我们新介绍的Likwid工具箱里面的likwid-topology我们可以看到:

./likwid-topology

cpu-topology

CPU的拓扑结构是各种高性能服务器CPU亲缘性绑定必须理解的东西,有感觉了吗?

有了前面的各种基础知识和名词的铺垫,我们就可以来调查irqbalance的工作原理:


view source print ?
01. //irqbalance.c
02. int main(int argc, char** argv)
03. {
04. /* ... */
05. while (keep_going) {
06. sleep_approx(SLEEP_INTERVAL); //#define SLEEP_INTERVAL 10
07. /* ... */
08. clear_work_stats();
09. parse_proc_interrupts();
10. parse_proc_stat();
11. /* ... */
12. calculate_placement();
13. activate_mappings();
14. /* ... */
15. }
16. /* ... */
17. }

从程序的主循环可以很清楚的看到它的逻辑,在退出之前每隔10秒它做了以下的几个事情:
1. 清除统计
2. 分析中断的情况
3. 分析中断的负载情况
4. 根据负载情况计算如何平衡中断
5. 实施中断亲缘性变跟

好吧,稍微看下irqbalance如何使用的:

man irqbalance

–oneshot
Causes irqbalance to be run once, after which the daemon exits
–debug
Causes irqbalance to run in the foreground and extra debug information to be printed

在诊断模型下运行irqbalance可以给我们很多详细的信息:

#./irqbalance –oneshot –debug

喝口水,我们接着来分析下各个步骤的详细情况:

先了解下中断在CPU上的分布情况:


view source print ?
01. $cat /proc/interrupts|tr -s ' ' '\t'|cut -f 1-3
02. CPU0    CPU1
03. 0:      2622846291
04. 1:      7
05. 4:      234
06. 8:      1
07. 9:      0
08. 12:     4
09. 50:     6753
10. 66:     228
11. 90:     497
12. 98:     31
13. 209:    2       0
14. 217:    0       0
15. 225:    29      556
16. 233:    0       0
17. NMI:    7395302 4915439
18. LOC:    2622846035      2622833187
19. ERR:    0
20. MIS:    0

输出的第一列是中断号,后面的2列是在CPU0,CPU1的中断次数。

但是我们如何知道比如中断是98那个类型的设备呢?不废话,上代码!


view source print ?
01. //classify.c
02. char *classes[] = {
03. "other",
04. "legacy",
05. "storage",
06. "timer",
07. "ethernet",
08. "gbit-ethernet",
09. "10gbit-ethernet",
10. 0
11. };
12.  
13. #define MAX_CLASS 0x12
14. /*                                                                                                                       
15. * Class codes lifted from pci spec, appendix D.                                                                         
16. * and mapped to irqbalance types here                                                                                   
17. */
18. static short class_codes[MAX_CLASS] = {
19. IRQ_OTHER,
20. IRQ_SCSI,
21. IRQ_ETH,
22. IRQ_OTHER,
23. IRQ_OTHER,
24. IRQ_OTHER,
25. IRQ_LEGACY,
26. IRQ_OTHER,
27. IRQ_OTHER,
28. IRQ_LEGACY,
29. IRQ_OTHER,
30. IRQ_OTHER,
31. IRQ_LEGACY,
32. IRQ_ETH,
33. IRQ_SCSI,
34. IRQ_OTHER,
35. IRQ_OTHER,
36. IRQ_OTHER,
37. };
38. int map_class_to_level[7] =
39. { BALANCE_PACKAGE, BALANCE_CACHE, BALANCE_CACHE, BALANCE_NONE, BALANCE_CORE, BALANCE_CORE, BALANCE_CORE };

irqbalance把中断分成7个类型,不同类型的中断平衡的时候作用域不同,有的在PACKAGE,有的在CACHE,有的在CORE。
那么类型信息在那里获取呢?不废话,上代码!


view source print ?
01. //#define SYSDEV_DIR "/sys/bus/pci/devices"
02. static struct irq_info *add_one_irq_to_db(const char *devpath, int irq, structuser_irq_policy *pol)
03. {
04. ...
05. sprintf(path, "%s/class", devpath);
06.  
07. fd = fopen(path, "r");
08.  
09. if (!fd) {
10. perror("Can't open class file: ");
11. goto get_numa_node;
12. }
13.  
14. rc = fscanf(fd, "%x", &class);
15. fclose(fd);
16.  
17. if (!rc)
18. goto get_numa_node;
19.  
20. /*                                                                                                               
21. * Restrict search to major class code                                                                           
22. */
23. class >>= 16;
24.  
25. if (class >= MAX_CLASS)
26. goto get_numa_node;
27.  
28. new->class = class_codes[class];
29. if (pol->level >= 0)
30. new->level = pol->level;
31. else
32. new->level = map_class_to_level[class_codes[class]];
33. get_numa_node:
34. numa_node = -1;
35. sprintf(path, "%s/numa_node", devpath);
36. fd = fopen(path, "r");
37. if (!fd)
38. goto assign_node;
39.  
40. rc = fscanf(fd, "%d", &numa_node);
41. fclose(fd);
42.  
43. assign_node:
44. new->numa_node = get_numa_node(numa_node);
45.  
46. sprintf(path, "%s/local_cpus", devpath);
47. fd = fopen(path, "r");
48. if (!fd) {
49. cpus_setall(new->cpumask);
50. goto assign_affinity_hint;
51. }
52. lcpu_mask = NULL;
53. ret = getline(&lcpu_mask, &blen, fd);
54. fclose(fd);
55. if (ret <= 0) {
56. cpus_setall(new->cpumask);
57. else {
58. cpumask_parse_user(lcpu_mask, ret, new->cpumask);
59. }
60. free(lcpu_mask);
61.  
62. assign_affinity_hint:
63. cpus_clear(new->affinity_hint);
64. sprintf(path, "/proc/irq/%d/affinity_hint", irq);
65. fd = fopen(path, "r");
66. if (!fd)
67. goto out;
68. lcpu_mask = NULL;
69. ret = getline(&lcpu_mask, &blen, fd);
70. fclose(fd);
71. if (ret <= 0)
72. goto out;
73. cpumask_parse_user(lcpu_mask, ret, new->affinity_hint);
74. free(lcpu_mask);
75. out:
76. ...
77. }

#上面的c代码翻译成下面的脚本就是:


view source print ?
01. $cat>x.sh
02. SYSDEV_DIR="/sys/bus/pci/devices/"
03. for dev in `ls $SYSDEV_DIR`
04. do
05. IRQ=`cat $SYSDEV_DIR$dev/irq`
06. CLASS=$(((`cat $SYSDEV_DIR$dev/class`)>>16))
07. printf "irq %s: class[%s] " $IRQ $CLASS
08. if [ -f "/proc/irq/$IRQ/affinity_hint" ]; then
09. printf "affinity_hint[%s] " `cat /proc/irq/$IRQ/affinity_hint`
10. fi
11. if [ -f "$SYSDEV_DIR$dev/local_cpus" ]; then
12. printf "local_cpus[%s] " `cat $SYSDEV_DIR$dev/local_cpus`
13. fi
14. if [ -f "$SYSDEV_DIR$dev/numa_node" ]; then
15. printf "numa_node[%s]" `cat $SYSDEV_DIR$dev/numa_node`
16. fi
17. echo
18. done
19. CTRL+D
20. $ tree /sys/bus/pci/devices
21. /sys/bus/pci/devices
22. |-- 0000:00:00.0 -> ../../../devices/pci0000:00/0000:00:00.0
23. |-- 0000:00:01.0 -> ../../../devices/pci0000:00/0000:00:01.0
24. |-- 0000:00:03.0 -> ../../../devices/pci0000:00/0000:00:03.0
25. |-- 0000:00:07.0 -> ../../../devices/pci0000:00/0000:00:07.0
26. |-- 0000:00:09.0 -> ../../../devices/pci0000:00/0000:00:09.0
27. |-- 0000:00:13.0 -> ../../../devices/pci0000:00/0000:00:13.0
28. |-- 0000:00:14.0 -> ../../../devices/pci0000:00/0000:00:14.0
29. |-- 0000:00:14.1 -> ../../../devices/pci0000:00/0000:00:14.1
30. |-- 0000:00:14.2 -> ../../../devices/pci0000:00/0000:00:14.2
31. |-- 0000:00:14.3 -> ../../../devices/pci0000:00/0000:00:14.3
32. |-- 0000:00:1a.0 -> ../../../devices/pci0000:00/0000:00:1a.0
33. |-- 0000:00:1a.7 -> ../../../devices/pci0000:00/0000:00:1a.7
34. |-- 0000:00:1d.0 -> ../../../devices/pci0000:00/0000:00:1d.0
35. |-- 0000:00:1d.1 -> ../../../devices/pci0000:00/0000:00:1d.1
36. |-- 0000:00:1d.2 -> ../../../devices/pci0000:00/0000:00:1d.2
37. |-- 0000:00:1d.7 -> ../../../devices/pci0000:00/0000:00:1d.7
38. |-- 0000:00:1e.0 -> ../../../devices/pci0000:00/0000:00:1e.0
39. |-- 0000:00:1f.0 -> ../../../devices/pci0000:00/0000:00:1f.0
40. |-- 0000:00:1f.2 -> ../../../devices/pci0000:00/0000:00:1f.2
41. |-- 0000:00:1f.3 -> ../../../devices/pci0000:00/0000:00:1f.3
42. |-- 0000:00:1f.5 -> ../../../devices/pci0000:00/0000:00:1f.5
43. |-- 0000:01:00.0 -> ../../../devices/pci0000:00/0000:00:01.0/0000:01:00.0
44. |-- 0000:01:00.1 -> ../../../devices/pci0000:00/0000:00:01.0/0000:01:00.1
45. |-- 0000:04:00.0 -> ../../../devices/pci0000:00/0000:00:09.0/0000:04:00.0
46. `-- 0000:05:00.0 -> ../../../devices/pci0000:00/0000:00:1e.0/0000:05:00.0
47.  
48. $chmod +x x.sh
49. $./x.sh|grep 98
50. irq 98: class[2] local_cpus[00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000]

简单的分析下数字:class_codes[2]=IRQ_ETH 也就是说这个中断是块网卡。

那中断的负载是怎么算出来的呢?继续看代码!


view source print ?
01. //procinterrupts.c
02. void parse_proc_stat(void)
03. {
04. ...
05. file = fopen("/proc/stat""r");
06. if (!file) {
07. log(TO_ALL, LOG_WARNING, "WARNING cant open /proc/stat.  balacing is broken\n");
08. return;
09. }
10.  
11. /* first line is the header we don't need; nuke it */
12. if (getline(&line, &size, file)==0) {
13. free(line);
14. log(TO_ALL, LOG_WARNING, "WARNING read /proc/stat. balancing is broken\n");
15. fclose(file);
16. return;
17. }
18. cpucount = 0;
19. while (!feof(file)) {
20. if (getline(&line, &size, file)==0)
21. break;
22.  
23. if (!strstr(line, "cpu"))
24. break;
25.  
26. cpunr = strtoul(&line[3], NULL, 10);
27.  
28. if (cpu_isset(cpunr, banned_cpus))
29. continue;
30.  
31. rc = sscanf(line, "%*s %*d %*d %*d %*d %*d %d %d", &irq_load, &softirq_load);
32. if (rc < 2)
33. break;
34.  
35. cpu = find_cpu_core(cpunr);
36.  
37. if (!cpu)
38. break;
39.  
40. cpucount++;
41. /*                                                                                                       
42. * For each cpu add the irq and softirq load and propagate that                                          
43. * all the way up the device tree                                                                        
44. */
45. if (cycle_count) {
46. cpu->load = (irq_load + softirq_load) - (cpu->last_load);
47. /*                                                                                               
48. * the [soft]irq_load values are in jiffies, which are                                           
49. * units of 10ms, multiply by 1000 to convert that to                                            
50. * 1/10 milliseconds.  This give us a better integer                                             
51. * distribution of load between irqs                                                             
52. */
53. cpu->load *= 1000;
54. }
55. cpu->last_load = (irq_load + softirq_load);
56. }
57. ...
58. }

相当于以下的命令:

$grep cpu015/proc/stat
cpu15 30068830 85841 22995655 3212064899 536154 91145 2789328 0

我们学习下 /proc/stat 的文件格式!

关于CPU这行摘抄如下:

cpu — Measures the number of jiffies (1/100 of a second for x86 systems) that the system has been in user mode, user mode with low priority (nice), system mode, idle task, I/O wait, IRQ (hardirq), and softirq respectively. The IRQ (hardirq) is the direct response to a hardware event. The IRQ takes minimal work for queuing the “heavy” work up for the softirq to execute. The softirq runs at a lower priority than the IRQ and therefore may be interrupted more frequently. The total for all CPUs is given at the top, while each individual CPU is listed below with its own statistics. The following example is a 4-way Intel Pentium Xeon configuration with multi-threading enabled, therefore showing four physical processors and four virtual processors totaling eight processors.

可以知道这行的第7,8项分别对应着中断和软中断的次数,二者加起来就是我们所谓的CPU负载。
这个和结果和irqbalance报告的中断的情况是吻合的,见图:

ib_irq_type_workload

是不是有点晕了,喝口水!
我们继续来看下整个Package层面irqbalance是如何计算负载的,从下面的图结合前面的那个CPU拓扑很清楚的看到:

irqbalance_package

每个CORE的负载是附在上面的中断的负载的总和,每个DOMAIN是包含的CORE的总和,每个PACKAGE包含的DOMAIN的总和,就像树层次一样的计算。
知道了每个CORE, DOMAIN,PACKAGE的负载的情况,那么剩下的就是找个这个中断类型所在作用域范围内最轻的对象把中断迁移过去。

迁移的依据正是之前看过的这个东西:

int map_class_to_level[7] =
{ BALANCE_PACKAGE, BALANCE_CACHE, BALANCE_CACHE, BALANCE_NONE, BALANCE_CORE, BALANCE_CORE, BALANCE_CORE };

水喝多了,等等放下水先,回来继续!

最后那irqbalance系统是如何实施中断亲缘性变跟的呢,继续上代码:


view source print ?
01. // activate.c
02. static void activate_mapping(struct irq_info *info, void *data __attribute__((unused)))
03. {
04. ...
05. if ((hint_policy == HINT_POLICY_EXACT) &&
06. (!cpus_empty(info->affinity_hint))) {
07. applied_mask = info->affinity_hint;
08. valid_mask = 1;
09. else if (info->assigned_obj) {
10. applied_mask = info->assigned_obj->mask;
11. valid_mask = 1;
12. if ((hint_policy == HINT_POLICY_SUBSET) &&
13. (!cpus_empty(info->affinity_hint)))
14. cpus_and(applied_mask, applied_maskapplied_mask, info->affinity_hint);
15. }
16.  
17. /*                                                                                                               
18. * only activate mappings for irqs that have moved                                                               
19. */
20. if (!info->moved && (!valid_mask || check_affinity(info, applied_mask)))
21. return;
22.  
23. if (!info->assigned_obj)
24. return;
25.  
26. sprintf(buf, "/proc/irq/%i/smp_affinity", info->irq);
27. file = fopen(buf, "w");
28. if (!file)
29. return;
30.  
31. cpumask_scnprintf(buf, PATH_MAX, applied_mask);
32. fprintf(file, "%s", buf);
33. fclose(file);
34. info->moved = 0; /*migration is done*/
35. }
36.  
37. void activate_mappings(void)
38. {
39. for_each_irq(NULL, activate_mapping, NULL);
40. }

上面的代码简单的翻译成shell就是:

#echo MASK > /proc/irq/N/smp_affinity

当然如果用户设置的策略如果是HINT_POLICY_EXACT,那么我们会参照/proc/irq/N/affinity_hint设置
策略如果是HINT_POLICY_SUBSET, 那么我们会参照/proc/irq/N/affinity_hint | applied_mask 设置。

好吧,总算分析完成了! www.it165.net

总结:
irqbalance根据系统中断负载的情况,自动迁移中断保持中断的平衡,同时会考虑到省电因素等等。 但是在实时系统中会导致中断自动漂移,对性能造成不稳定因素,在高性能的场合建议关闭。





http://chatgpt.dhexx.cn/article/JK2E00YY.shtml

相关文章

linux irq 接口,Linux内核API irq_set_irq_type

irq_set_irq_type函数功能描述&#xff1a;此函数用于设置中断处理函数触发的类型&#xff0c;被操作的中断描述符保存在数组irq_desc中&#xff0c;对应的下标为参数irq的值&#xff0c;设置的中断触发类型为参数type所代表的类型。 irq_set_irq_type文件包含 irq_set_irq_typ…

Linux Irq domain

本节学习下什么是irq domain, 以及irq domain的作用。可以参考内核文档IRQ-domain.txt 为什么引入IRQ-Domain 当早期的系统只存在一个interrupt-controller的时候&#xff0c;而且中断数目也不多的时候&#xff0c;一个很简单的做法就是一个中断号对应到interrupt-contoller的…

linux IRQ Management(四)- IRQ Domain

了解IRQ Domain(中断控制器) 1.如何理解中断号&#xff1f; 每个IRQ同时有"irq"和"hwirq"两个编号。 "hwirq"是硬件中断号&#xff08;物理中断号&#xff09;&#xff0c;即芯片手册上写的号码&#xff0c;Interrupt controller用hwirq来标识…

linux设备驱动:中断处理中的hardirq与softirq详细流程

中断处理的整体框架&#xff1a; 内核用于标识中断上下文(in_interrupt())的变量preempt_count的布局&#xff1a; 按照x86处理器在外部中断发生时的硬件逻辑&#xff0c;在do_IRQ被调用时&#xff0c;处理器已经屏蔽了对外部中断的响应。在图中我们看 到中断的处理大体上被…

Java 字段封装快捷键

快捷键:shift alt s 选择&#xff1a;

Java封装阿里云对象存储OSS

Java封装阿里云对象存储OSS 阿里云对象存储OSS官网 本篇博客简单封装了阿里云的OSS存储中的建立连接&#xff1b;本地文件&#xff0c;输入流和URL三种方式上传文件&#xff0c;获取文件的输入流&#xff0c;删除文件&#xff0c;获取所有文件列表等功能。 OSS官方Api OSSp…

java 枚举 封装操作方法

前言&#xff1a; 由于刚转java项目&#xff0c;所以对于java语言比较陌生&#xff0c;尤其是lambda和一些诸如&#xff08;一个java文件只能有一个public class&#xff09;等等的零散知识点之类。。。 使我觉得就语言的层级来说。.net真的超越java不是一星半点。奈何.net跨…

Java封装和封装的案例

Java封装和封装的案例 目录 一、Java封装知识点简介 二、Java程序中的包 三、static关键字、代码块 四、封装的综合应用案例&#xff1a; 一、Java封装知识点简介 1、面向对象三大特性之封装的概念&#xff1a; 隐藏类的某些内部细节&#xff0c;不允许外部程序直接访问…

Java的封装方法

在面向对象程式设计方法中&#xff0c;封装&#xff08;英文名称&#xff1a;Encapsulation&#xff09;是指一种将抽象性函式接口的实现细节部份包装、隐藏起来的方法。封装可以被认为是一个保护屏障&#xff0c;防止该类的代码和数据被外部类定义的代码随机访问。要访问该类的…

Java封装如何封装 封装的好处是什么?

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、封装的作用是什么&#xff1f;二、封装的好处三、封装的步骤 1.引入库2.private的应用总结 前言 我要看电视&#xff0c;只需要按一下开关和换台就可以了。…

15、JAVA入门——封装

目录 一、封装 1、封装概述 2、封装的步骤 二、Java里的包 1、包的概述 2、包的定义 3、包的使用 4、注意事项 三、Java访问修饰符 1、类和类成员的访问控制 2、类的访问修饰符 3、类成员的访问修饰符 四、static关键字 1、static特点 2、static修饰属性 3、static修饰方法 4、…

初学java封装

封装 初识java封装 封装的用处&#xff1a; 1.提高程序的安全性&#xff0c;保护数据 2.隐藏代码的实现细节 3.统一接口 4.增加系统可维护性 这里创建一个类 public class Package {//属性私有private String name;//名字private int age; //年龄private int sex;//性别//1.…

java如何实现封装_java如何实现封装

Java中类的封装是如何实现的封装是将对象的信息隐藏在对象内部,禁止外部程序直接访问对象内部的属性和方法。 java封装类通过三个步骤实现: (1)修改属性的可见性,限制访问。 (2)设置属性的读取方法。 (3)在读取属性的方法中,添加对属性读取的限制。 Java中什么叫封装呢? 继…

java封装dll文件_java类封装成dll

1&#xff0c;建立测试类&#xff0c;注意英文注释部分&#xff0c;用汉语直接编译会乱码 public classHello {//native method is used for call other language procedure//if use chinese here then Compile would be gibberish public native voidprintHello();static{ Sys…

java之封装

1.封装 1. 封装 1.1 private关键字 private是一个修饰符&#xff0c;可以用来修饰成员&#xff08;成员变量&#xff0c;成员方法&#xff09; 被private修饰的成员&#xff0c;只能在本类进行访问&#xff0c;针对private修饰的成员变量&#xff0c;如果需要被其他类使用&…

【JavaScript】js中非常常见的面试题

文章目录 1、手动实现防抖和节流2、let、const、var 的区别3、箭头函数与普通函数区别4、Promise5、数据类型6、检测数据类型的常用方法1 .typeof2 . instanceof3 .constructor4 . 使用 Object.prototype.toString.call()检测对象类型⭐5 . 自己封装函数6、isArray 7、数组的常…

JS的100道经典面试题(一)只看这四篇就够了,收藏起来以后偷偷看

年轻人你不讲武德&#xff0c;耗子尾汁~~~ 总结就是为了形成自己的js知识网&#xff0c;提升自己&#xff0c;加油&#xff01; 开始干 1、介绍js的基本数据类型   答&#xff1a; Undefined、Null、Boolean、Number、String 2、js有哪些内置对象&#xff1f;  答&…

大前端JS部分基础面试题(含答案)

1.几种基本数据类型?复杂数据类型?值类型和引用数据类型?堆栈数据结构? 基本数据类型&#xff1a;Undefined、Null、Boolean、Number、String 值类型&#xff1a;数值、布尔值、null、undefined。 引用类型&#xff1a;对象、数组、函数。 堆栈数据结构&#xff1a;是一种支…

Js面试题__附答案

1、什么是JavaScript&#xff1f;&#xff08;这是基本题&#xff0c;对很多程序员来说也是送分题&#xff01;&#xff09; JavaScript是客户端和服务器端脚本语言&#xff0c;可以插入到HTML页面中&#xff0c;并且是目前较热门的Web开发语言。同时&#xff0c;JavaScript也…

js 变量及作用域经典面试题

function Foo() {getName function () { alert (1); };return this; } Foo.getName function () { alert (2);}; Foo.prototype.getName function () { alert (3);}; var getName function () { alert (4);}; function getName() { alert (5);}//请写出以下输出结果&#x…