linux系统中出现大量不可中断进程和僵尸进程怎么办?

进程状态

当iowait升高时,进程很可能因为得不到硬件的响应,而长时间处于不可中断的状态,从ps或者top命令的输出中,可以发现它们都处于D状态,也就是不可中断状态。

通过top和ps可以查看进程的状态,S列表示进程的状态。

$ topPID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
28961 root      20   0   43816   3148   4040 R   3.2  0.0   0:00.01 top620 root      20   0   37280  33676    908 D   0.3  0.4   0:00.01 app1 root      20   0  160072   9416   6752 S   0.0  0.1   0:37.64 systemd1896 root      20   0       0      0      0 Z   0.0  0.0   0:00.00 devapp2 root      20   0       0      0      0 S   0.0  0.0   0:00.10 kthreadd4 root       0 -20       0      0      0 I   0.0  0.0   0:00.00 kworker/0:0H6 root       0 -20       0      0      0 I   0.0  0.0   0:00.00 mm_percpu_wq7 root      20   0       0      0      0 S   0.0  0.0   0:06.37 ksoftirqd/0

R(Running或Runnable):进程在CPU的就绪队列中,正在运行或者正在等待运行。

D(Disk Sleep ):不可中断状态睡眠,一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断

Z(Zombie):僵尸进程,进程实际上已经结束了,但是父进程还没有回收它的资源

S(Interruptible Sleep):可中断状态睡眠,表示进程因为等待某个时间而被系统挂起,当进程等待的时间发生时,会被唤醒并进入R状态

I(Idle):空闲的状态,用在不可中断睡眠的内核线程上,硬件交互导致的不可中断进程用D表示,但对某些内核线程来说,有可能实际上并没有任何负载,用Idle正式为了区分这种情况,D状态的进程会导致平均负载升高,I状态的进程却不会。

T(Stopped或Traced):表示进程处于暂停或者跟踪状态

  • 向一个进程发送 SIGSTOP 信号,它就会因响应这个信号变成暂停状态(Stopped);再向它发送 SIGCONT 信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要你用 fg 命令,恢复到前台运行)。
  • 用调试器(如 gdb)调试一个进程时,在使用断点中断进程后,进程就会变成跟踪状态,这其实也是一种特殊的暂停状态,只不过你可以用调试器来跟踪并按需要控制进程的运行。

X(Dead),进程已经消亡,不会在 top 或者 ps 命令中看到它。

不可中断状态,为了保证进程数据与硬件状态一致

  • 正常情况下,不可中断状态在很短时间内就会结束,短时的不可中断状态进程,一般可以忽略。
  • 如果系统或硬件发生了故障,进程可能会在不可中断状态保持很久,甚至导致系统中出现大量不可中断进程。这时就得看下系统是不是出现了 I/O 等性能问题。

僵尸进程,这是多进程应用很容易碰到的问题。

  • 正常情况下一个进程创建子进程后,通过系统调用 wait() 或者 waitpid() 等待子进程结束,回收子进程的资源;子进程在结束时,会向它的父进程发送 SIGCHLD 信号,所以,父进程还可以注册 SIGCHLD 信号的处理函数,异步回收资源。
  • 如果父进程没这么做,或是子进程执行太快,父进程还没来得及处理子进程状态,子进程就已经提前退出,那这时的子进程就会变成僵尸进程。
  • 通常僵尸进程持续的时间都比较短,在父进程回收它的资源后就会消亡;或者在父进程退出后,由 init 进程回收后也会消亡。
  • 一旦父进程没有处理子进程的终止,还一直保持运行状态,那么子进程就会一直处于僵尸状态。大量的僵尸进程会用尽 PID 进程号,导致新进程不能创建,所以这种情况一定要避免。

案例分析

一个多进程应用的案例分析大量不可中断状态和僵尸状态进程的问题。

dstat 是一个新的性能工具,它吸收了 vmstat、iostat、ifstat 等几种工具的优点,可以同时观察系统的 CPU、磁盘 I/O、网络以及内存使用情况。

首先执行下面的命令运行案例应用:

$ docker run --privileged --name=app -itd feisky/app:iowait

输入 ps 命令,确认案例应用已正常启动。如果一切正常,你应该可以看到如下所示的输出:

$ ps aux | grep /app
root      4009  0.0  0.0   4376  1008 pts/0    Ss+  05:51   0:00 /app
root      4287  0.6  0.4  37280 33660 pts/0    D+   05:54   0:00 /app
root      4288  0.6  0.4  37280 33668 pts/0    D+   05:54   0:00 /app

从这个界面,我们可以发现多个 app 进程已经启动,并且它们的状态分别是 Ss+ 和 D+。

  • S 表示可中断睡眠状态,D 表示不可中断睡眠状态
  • s 表示这个进程是一个会话的领导进程,而 + 表示前台进程组。

进程组和会话,它们用来管理一组相互关联的进程

  • 进程组表示一组相互关联的进程,比如每个子进程都是父进程所在组的成员;
  • 会话是指共享同一个控制终端的一个或多个进程组。

比如,我们通过 SSH 登录服务器,就会打开一个控制终端(TTY),这个控制终端就对应一个会话。

而我们在终端中运行的命令以及它们的子进程,就构成了一个个的进程组,其中,在后台运行的命令,构成后台进程组;在前台运行的命令,构成前台进程组。

用 top 看一下系统的资源使用情况:

# 按下数字 1 切换到所有 CPU 的使用情况,观察一会儿按 Ctrl+C 结束
$ top
top - 05:56:23 up 17 days, 16:45,  2 users,  load average: 2.00, 1.68, 1.39
Tasks: 247 total,   1 running,  79 sleeping,   0 stopped, 115 zombie
%Cpu0  :  0.0 us,  0.7 sy,  0.0 ni, 38.9 id, 60.5 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  :  0.0 us,  0.7 sy,  0.0 ni,  4.7 id, 94.6 wa,  0.0 hi,  0.0 si,  0.0 st
...PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND4340 root      20   0   44676   4048   3432 R   0.3  0.0   0:00.05 top4345 root      20   0   37280  33624    860 D   0.3  0.0   0:00.01 app4344 root      20   0   37280  33624    860 D   0.3  0.4   0:00.01 app1 root      20   0  160072   9416   6752 S   0.0  0.1   0:38.59 systemd
...
  • 平均负载( Load Average),过去 1 分钟、5 分钟和 15 分钟内的平均负载在依次减小,说明平均负载正在升高;而 1 分钟内的平均负载已经达到系统的 CPU 个数,说明系统很可能已经有了性能瓶颈。
  • Tasks,有 1 个正在运行的进程,但僵尸进程比较多,而且还在不停增加,说明有子进程在退出时没被清理。
  • 两个 CPU 的使用率情况,用户 CPU 和系统 CPU 都不高,但 iowait 分别是 60.5% 和 94.6%,好像有点儿不正常。
  • 每个进程的情况, CPU 使用率最高的进程只有 0.3%,看起来并不高;但有两个进程处于 D 状态,它们可能在等待 I/O,但光凭这里并不能确定是它们导致了 iowait 升高。

四个问题再汇总一下,就可以得到很明确的两点:

  • 第一点,iowait 太高了,导致系统的平均负载升高,甚至达到了系统 CPU 的个数。
  • 第二点,僵尸进程在不断增多,说明有程序没能正确清理子进程的资源。

相关视频推荐

初识Linux内核,进程通信能这么玩

360度无死角讲解进程管理,调度器的5种实现

90分钟搞定协程、线程、进程大厂面试

学习地址:c/c++ linux服务器开发/后台架构师

需要C/C++ Linux服务器架构师学习资料加qun812855908获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

iowait 分析

iowait 升高首先会想要查询系统的 I/O 情况,使用dstat 可以同时查看 CPU 和 I/O 这两种资源的使用情况,便于对比分析。

# 间隔 1 秒输出 10 组数据
$ dstat 1 10
You did not select any stats, using -cdngy by default.
--total-cpu-usage-- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai stl| read  writ| recv  send|  in   out | int   csw0   0  96   4   0|1219k  408k|   0     0 |   0     0 |  42   8850   0   2  98   0|  34M    0 | 198B  790B|   0     0 |  42   1380   0   0 100   0|  34M    0 |  66B  342B|   0     0 |  42   1350   0  84  16   0|5633k    0 |  66B  342B|   0     0 |  52   1770   3  39  58   0|  22M    0 |  66B  342B|   0     0 |  43   1440   0   0 100   0|  34M    0 | 200B  450B|   0     0 |  46   1470   0   2  98   0|  34M    0 |  66B  342B|   0     0 |  45   1340   0   0 100   0|  34M    0 |  66B  342B|   0     0 |  39   1310   0  83  17   0|5633k    0 |  66B  342B|   0     0 |  46   1680   3  39  59   0|  22M    0 |  66B  342B|   0     0 |  37   134

从 dstat 的输出,可以看到每当 iowait 升高(wai)时,磁盘的读请求(read)都会很大。

这说明 iowait 的升高跟磁盘的读请求有关,很可能就是磁盘读导致的。

运行 top 命令,观察 D 状态的进程:

# 观察一会儿按 Ctrl+C 结束
$ top
...PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND4340 root      20   0   44676   4048   3432 R   0.3  0.0   0:00.05 top4345 root      20   0   37280  33624    860 D   0.3  0.0   0:00.01 app4344 root      20   0   37280  33624    860 D   0.3  0.4   0:00.01 app
...

从 top 的输出找到 D 状态进程的 PID,你可以发现,这个界面里有两个 D 状态的进程,PID 分别是 4344 和 4345。

接着,我们查看这些进程的磁盘读写情况。查看某一个进程的资源使用情况,都可以用我们的 pidstat,不过这次记得加上 -d 参数,以便输出 I/O 使用情况。

以 4344 为例,运行下面的 pidstat 命令,并用 -p 4344 参数指定进程号:

# -d 展示 I/O 统计数据,-p 指定进程号,间隔 1 秒输出 3 组数据
$ pidstat -d -p 4344 1 3
06:38:50      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
06:38:51        0      4344      0.00      0.00      0.00       0  app
06:38:52        0      4344      0.00      0.00      0.00       0  app
06:38:53        0      4344      0.00      0.00      0.00       0  app
  • kB_rd 表示每秒读的 KB 数
  • kB_wr 表示每秒写的 KB 数
  • iodelay 表示 I/O 的延迟(单位是时钟周期)

它们都是 0,那就表示此时没有任何的读写,说明问题不是 4344 进程导致的。

可是,用同样的方法分析进程 4345,你会发现,它也没有任何磁盘读写。

继续使用 pidstat,但这次去掉进程号,干脆就来观察所有进程的 I/O 使用情况。

在终端中运行下面的 pidstat 命令:

# 间隔 1 秒输出多组数据 (这里是 20 组)
$ pidstat -d 1 20
...
06:48:46      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
06:48:47        0      4615      0.00      0.00      0.00       1  kworker/u4:1
06:48:47        0      6080  32768.00      0.00      0.00     170  app
06:48:47        0      6081  32768.00      0.00      0.00     184  app06:48:47      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
06:48:48        0      6080      0.00      0.00      0.00     110  app06:48:48      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
06:48:49        0      6081      0.00      0.00      0.00     191  app06:48:49      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command06:48:50      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
06:48:51        0      6082  32768.00      0.00      0.00       0  app
06:48:51        0      6083  32768.00      0.00      0.00       0  app06:48:51      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
06:48:52        0      6082  32768.00      0.00      0.00     184  app
06:48:52        0      6083  32768.00      0.00      0.00     175  app06:48:52      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
06:48:53        0      6083      0.00      0.00      0.00     105  app
...

观察一会儿可以发现,的确是 app 进程在进行磁盘读,并且每秒读的数据有 32 MB,看来就是 app 的问题。

不过,app 进程到底在执行啥 I/O 操作呢?

进程想要访问磁盘,就必须使用系统调用,所以接下来,重点就是找出 app 进程的系统调用了。

strace 正是最常用的跟踪进程系统调用的工具,从 pidstat 的输出中拿到进程的 PID 号,比如 6082,然后在终端中运行 strace 命令,并用 -p 参数指定 PID 号:

$ strace -p 6082
strace: attach: ptrace(PTRACE_SEIZE, 6082): Operation not permitted

这儿出现了一个奇怪的错误,strace 命令居然失败了,并且命令报出的错误是没有权限。

一般遇到这种问题时,我会先检查一下进程的状态是否正常。比如,继续在终端中运行 ps 命令,并使用 grep 找出刚才的 6082 号进程:

$ ps aux | grep 6082
root      6082  0.0  0.0      0     0 pts/0    Z+   13:43   0:00 [app] <defunct>

进程 6082 已经变成了 Z 状态,也就是僵尸进程。僵尸进程都是已经退出的进程,所以就没法儿继续分析它的系统调用。

到这一步,你应该注意到了,系统 iowait 的问题还在继续,但是 top、pidstat 这类工具已经不能给出更多的信息了。

基于事件记录的动态追踪工具用 perf top ,看看有没有新发现。或者在终端中运行 perf record,持续一会儿(例如 15 秒),然后按 Ctrl+C 退出,再运行 perf report 查看报告:

$ perf record -g
$ perf report

找到我们关注的 app 进程,按回车键展开调用栈,你就会得到下面这张调用关系图:

app 的确在通过系统调用 sys_read() 读取数据。

从 new_sync_read 和 blkdev_direct_IO 能看出,进程正在对磁盘进行直接读,也就是绕过了系统缓存,每个读请求都会从磁盘直接读,这就可以解释我们观察到的 iowait 升高了,罪魁祸首是 app 内部进行了磁盘的直接 I/O 啊!

下来应该从代码层面分析,究竟是哪里出现了直接读请求。查看源码文件 app.c,你会发现它果然使用了 O_DIRECT 选项打开磁盘,于是绕过了系统缓存,直接对磁盘进行读写。

open(disk, O_RDONLY|O_DIRECT|O_LARGEFILE, 0755)

直接读写磁盘,对 I/O 敏感型应用(比如数据库系统)是很友好的,因为你可以在应用中,直接控制磁盘的读写。

大部分情况下,我们最好还是通过系统缓存来优化磁盘 I/O,换句话说,删除 O_DIRECT 这个选项就是了。

app-fix1.c 就是修改后的文件,我也打包成了一个镜像文件,运行下面的命令,你就可以启动它了:

# 首先删除原来的应用
$ docker rm -f app
# 运行新的应用
$ docker run --privileged --name=app -itd feisky/app:iowait-fix1

最后,再用 top 检查一下:

$ top
top - 14:59:32 up 19 min,  1 user,  load average: 0.15, 0.07, 0.05
Tasks: 137 total,   1 running,  72 sleeping,   0 stopped,  12 zombie
%Cpu0  :  0.0 us,  1.7 sy,  0.0 ni, 98.0 id,  0.3 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  :  0.0 us,  1.3 sy,  0.0 ni, 98.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
...PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND3084 root      20   0       0      0      0 Z   1.3  0.0   0:00.04 app3085 root      20   0       0      0      0 Z   1.3  0.0   0:00.04 app1 root      20   0  159848   9120   6724 S   0.0  0.1   0:09.03 systemd2 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kthreadd3 root      20   0       0      0      0 I   0.0  0.0   0:00.40 kworker/0:0
...

iowait 已经非常低了,只有 0.3%,说明刚才的改动已经成功修复了 iowait 高的问题,大功告成!不过,别忘了,僵尸进程还在等着你。仔细观察僵尸进程的数量,你会郁闷地发现,僵尸进程还在不断的增长中。

僵尸进程

接下来,我们就来处理僵尸进程的问题。既然僵尸进程是因为父进程没有回收子进程的资源而出现的,那么,要解决掉它们,就要找到它们的根儿,也就是找出父进程,然后在父进程里解决。

父进程的找法我们前面讲过,最简单的就是运行 pstree 命令:

# -a 表示输出命令行选项
# p 表 PID
# s 表示指定进程的父进程
$ pstree -aps 3084
systemd,1└─dockerd,15006 -H fd://└─docker-containe,15024 --config /var/run/docker/containerd/containerd.toml└─docker-containe,3991 -namespace moby -workdir...└─app,4009└─(app,3084)

运行完,你会发现 3084 号进程的父进程是 4009,也就是 app 应用。

所以,我们接着查看 app 应用程序的代码,看看子进程结束的处理是否正确,比如有没有调用 wait() 或 waitpid() ,抑或是,有没有注册 SIGCHLD 信号的处理函数。

现在我们查看修复 iowait 后的源码文件 app-fix1.c ,找到子进程的创建和清理的地方:

nt status = 0;for (;;) {for (int i = 0; i < 2; i++) {if(fork()== 0) {sub_process();}}sleep(5);}while(wait(&status)>0);

循环语句本来就容易出错,你能找到这里的问题吗?这段代码虽然看起来调用了 wait() 函数等待子进程结束,但却错误地把 wait() 放到了 for 死循环的外面,也就是说,wait() 函数实际上并没被调用到,我们把它挪到 for 循环的里面就可以了。

修改后的文件我放到了 app-fix2.c 中,也打包成了一个 Docker 镜像,运行下面的命令,你就可以启动它:

# 先停止产生僵尸进程的 app
$ docker rm -f app
# 然后启动新的 app
$ docker run --privileged --name=app -itd feisky/app:iowait-fix2

启动后,再用 top 最后来检查一遍:

$ top
top - 15:00:44 up 20 min,  1 user,  load average: 0.05, 0.05, 0.04
Tasks: 125 total,   1 running,  72 sleeping,   0 stopped,   0 zombie
%Cpu0  :  0.0 us,  1.7 sy,  0.0 ni, 98.3 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu1  :  0.0 us,  1.3 sy,  0.0 ni, 98.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
...PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND3198 root      20   0    4376    840    780 S   0.3  0.0   0:00.01 app2 root      20   0       0      0      0 S   0.0  0.0   0:00.00 kthreadd3 root      20   0       0      0      0 I   0.0  0.0   0:00.41 kworker/0:0
...

总结

通过ps或者top可以查看进程的状态,这些进程的状态包括运行 ( R )、空闲(I)、不可中断睡眠(D)、可中断睡眠状态(S)、僵尸(Z)、以及暂停(T)。

  • 不可中断状态:表示正在跟硬件交互,为了保持一致性,系统不允许其他进程或中断打断这个进程,进程长时间处于不可中断状态,通常表示系统有IO问题
  • 僵尸进程:表示进程已经退出,但它的父进程还没有回收子进程占用的资源,短暂的僵尸状态不必理会,如果长时间处于僵尸状态,有可能应用程序没有正常处理子进程的退出。

我用一个多进程的案例,带你分析系统等待 I/O 的 CPU 使用率(也就是 iowait%)升高的情况。

这个案例是磁盘 I/O 导致了 iowait 升高,不过iowait 高不一定代表 I/O 有性能瓶颈。当系统中只有 I/O 类型的进程在运行时,iowait 也会很高,但实际上,磁盘的读写远没有达到性能瓶颈的程度。

碰到 iowait 升高时,需要先用 dstat、pidstat 等工具,确认是不是磁盘 I/O 的问题,然后再找是哪些进程导致了 I/O。

  • 等待 I/O 的进程一般是不可中断状态,所以用 ps 命令找到的 D 状态(即不可中断状态)的进程,多为可疑进程。但这个案例中,在 I/O 操作后,进程又变成了僵尸进程,所以不能用 strace 直接分析这个进程的系统调用。
  • 用了 perf 工具,来分析系统的 CPU 时钟事件,最终发现是直接 I/O 导致的问题。这时,再检查源码中对应位置的问题,就很轻松了。

僵尸进程的问题相对容易排查,使用 pstree 找出父进程后,去查看父进程的代码,检查 wait() / waitpid() 的调用,或是 SIGCHLD 信号处理函数的注册就行了

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/223986.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python学习开发mock接口

#1.测试为什么要开发接口&#xff1f; 1)在别的接口没有开发好的时候, mock接口(模拟接口) 2)查看数据, 避免直接操作数据库 #2.开发接口的顺序 1)安装flask flask是一个轻量级开发框架 pip install flask 2)开发一个接口 开发步骤&#xff1a; 1.实例化一个服务server:f…

普冉(PUYA)单片机开发笔记(9): FLASH 读写

概述 单片机的 ROM 容量虽然不大&#xff0c;PY32F003 有 64K 字节的 ROM&#xff0c;但实际应用中会在 MCU 中存储持久化的数据&#xff0c;例如&#xff1a;在物联网应用中&#xff0c;需要把物模型持久化&#xff0c;作为非易失性数据&#xff0c;掉电了也要保存。这就要用…

1845_emacs中一个中文乱码问题分析解决

Grey 全部学习内容汇总&#xff1a;GitHub - GreyZhang/editors_skills: Summary for some common editor skills I used. 1845_emacs中一个中文乱码问题分析解决 曾经有一次放弃过我自己的emacs配置&#xff0c;一个原因就是中文的支持。感觉我的配置跟其他人的配置显得有些…

深度学习(生成式模型)——ADM:Diffusion Models Beat GANs on Image Synthesis

文章目录 前言基础模型结构UNet结构Timestep Embedding关于为什么需要timestep embedding global attention layer 如何提升diffusion model生成图像的质量Classifier guidance实验结果 前言 在前几篇博文中&#xff0c;我们已经介绍了DDPM、DDIM、Classifier guidance等相关的…

leetcode做题笔记2415. 反转二叉树的奇数层

给你一棵 完美 二叉树的根节点 root &#xff0c;请你反转这棵树中每个 奇数 层的节点值。 例如&#xff0c;假设第 3 层的节点值是 [2,1,3,4,7,11,29,18] &#xff0c;那么反转后它应该变成 [18,29,11,7,4,3,1,2] 。 反转后&#xff0c;返回树的根节点。 完美 二叉树需满足…

【STM32单片机】旋转太空人设计

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用STM32F103C8T6单片机控制器&#xff0c;使IIC OLED液晶等。 主要功能&#xff1a; 系统运行后&#xff0c;OLED显示动画界面。 二、软件设计 /* 作者&#xff1a;嗨小易&#xff08;QQ&#x…

vue中实现PDF文件流预览

代码示例 <template><div class"print"><div v-if"!viewShow" class"opt-box"><div style"height: 700px; overflow: auto;"><el-table :data"tableData" border><el-table-column prop…

HTML基础标签

但实际上无论声明为中文还是英文都可以写&#xff0c;中文/英文 主要是浏览器在进行调用翻译功能的时候&#xff0c;会按照声明的语言来进行翻译。 标签语义&#xff1a; 标签的属性一般都是在第一个标签中定义该标签效果所拥有的属性。 即标签的作用是什么 <>标签功能…

CSS——标准流、浮动、Flex布局

1、标准流 标准流也叫文档流&#xff0c;指的是标签在页面中默认的排布规则&#xff0c;例如&#xff1a;块元素独占一行&#xff0c;行内元素可以一行显示多个。 2、浮动 作用&#xff1a;让块元素水平排列 属性名&#xff1a;float 属性值&#xff1a; left&#xff1a;…

做为一个产品经理带你详细了解--动态面板的使用

&#x1f4da;&#x1f4da; &#x1f3c5;我是bing人&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;在这里&#xff0c;我要推荐给大家我的专栏《Axure》。&#x1f3af;&#x1f3af; &#x1f680;无论你是编程小白&#xff0c;还是有一…

卫星影像5天一更新的地图网站

如果全球影像每5天一更新&#xff0c;并集多种地图数据源于一体的PB级海量地图数据该怎样去管理呢&#xff1f; 这是当我了解到SOAR网站之后&#xff0c;思考过的一个问题。 全球最大的在线地图网站 在SOAR的官方网站&#xff0c;据称它是世界上最大的在线地图网站。 它是集…

如何远程访问Axure RP制作的本地web站点实现协同办公

文章目录 前言1.在AxureRP中生成HTML文件2.配置IIS服务3.添加防火墙安全策略4.使用cpolar内网穿透实现公网访问4.1 登录cpolar web ui管理界面4.2 启动website隧道4.3 获取公网URL地址4.4. 公网远程访问内网web站点4.5 配置固定二级子域名公网访问内网web站点4.5.1创建一条固定…

深入理解Java关键字volatile

前置知识-了解以下CPU结构 如下图所示&#xff0c;每个CPU都会有自己的一二级缓存&#xff0c;其中一级缓存分为数据缓存和指令缓存&#xff0c;这些缓存的数据都是从内存中读取的&#xff0c;而且每次都会加载一个cache line&#xff0c;关于cache line的大小可以使用命令cat…

stm32与Freertos入门(二)移植FreeRTOS到STM32中

简介 注意&#xff1a;FreeRTOS并不是实时操作系统&#xff0c;而是分时复用的&#xff0c;只不过切换频率很快&#xff0c;感觉上是同时在工作。本次使用的单片机型号为STM32F103C8T6,通过CubeMX快速移植。 一、CubeMX快速移植 1、选择芯片 打开CubeMX软件&#xff0c;进行…

(独白)我为什么选择了计算机行业?

为什么可能很简单&#xff0c;但为什么的为什么就有点长了。就当作讲故事吧 在高中毕业后选择专业时&#xff0c;和大多数人一样&#xff0c;我根本不知道要选择什么专业&#xff0c;更不知道哪个专业发展前景好&#xff0c;哪个专业好就业。在当时比较火的专业我记得应该是土…

使用广播星历进行 GPS 卫星位置的计算

目录 1.计算卫星运动的平均角速度 n 2.计算观测瞬间卫星的近地点角 3.计算偏近点角 4.计算真近点角 f 5.计算升交角距 6.计算摄动改正项 7.进行摄动改正 8.计算卫星在轨道面坐标系中的位置 9.计算观测瞬间升交点的经度 L 10.计算卫星在瞬时地球坐标系中的位置 11.…

JDK21+HADOOP3.2.2+Windows安装步骤

哈哈哈 最近转战大数据这块了&#xff0c;分享一下hadoop3.2.2的安装步骤 借鉴了不少大佬的文章&#xff0c;如有雷同&#xff0c;都是大佬们的 1.JDK安装 我选择的是JDK21 以下是下载网址和截图&#xff0c;这个没有太多的&#xff0c;一般下载最新的就可以 JDK: Java Down…

SQL数列

SQL数列 1、数列概述2、SQL数列2.1、简单递增序列2.2、等差数列2.3、等比数列3、SQL数列的应用3.1、连续问题3.2、多维分析1、数列概述 数列是最常见的数据形式之一,实际数据开发场景中遇到的基本都是有限数列。常见的数列例如:简单递增序列、等差数列、等比数列等 SQL如何实…

Helplook VS Salesforce:哪个知识库更好?

对于组织来说&#xff0c;选择一个合适的平台来管理在线知识库可能是一个具有挑战性的任务。而Salesforce的知识管理功能可以帮助组织更好地管理和分享他们的知识&#xff0c;从而更好地为客户提供服务。这是一种将知识管理集成到CRM平台中的方法&#xff0c;可以简化知识共享和…

vue el-cascader组件change失效以及下拉框不消失的问题

文章目录 1.前言2. 碰到的问题3. 如何解决这两个问题 1.前言 最近项目上用到el-cascader这个组件,需要可以选第一级菜单&#xff0c;也需要可以选第二级菜单&#xff0c;点击完成之后需要关闭下拉框。其实功能比较简单&#xff0c;找了很多资料&#xff0c;没有找到合适的方案…