Android Tombstone 与Debuggerd 原理浅谈

一、前言

Android系统类问题主要有stabilityperformancepowersecurityAndroid集成一个守护进程tombstonedandroid平台的一个守护进程,它注册成3socket服务端,客户端封装在crash_dumpdebuggerd_client crash_dump用于跟踪定位C++ crash debuggerd_client用于在某些场景(发生ANRwatchdogshell执行debuggerd -bdump指定进程 backtrace

二、tombstone原理

1,ELF程序加载过程

在进入execve()系统调用之后,Linux内核就开始进行真正的装配工作。在内核中,execve()系统调用相应的入口是sys_execve()sys_execve()进行一些参数的检查复制之后,调用do_execve()do_execve()会首先查找被执行的文件,如果找到文件,则读取文件的前128个字节。文件的前128个字节保存着可执行文件的格式信息,特别是前四个字节(魔数)。这样可以根据不同的可执行文件信息,来调用不同的装载模块。当do_execve()读取了这128个字节的文件头部之后,然后调用search_binary_handle()去搜索和匹配合适的可执行文件装载处理。linux中所有被支持的可执行文件格式都有相应的装载处理过程。search_binary_handle()会通过判断文件头部的魔数确定文件的格式,并且调用相应的过程。ELF可执行文件的装载处理过程叫做load_elf_binary()load_elf_binary()被定义在fs/Binfmt_elf.c。它的主要步骤是:

1. 检查ELF可执行文件格式的有效性,比如魔数,程序头表中段(Segment)的数量

2. 寻找动态链接的“.interp段,设置动态连接器路径(与动态链接有关)

3. 根据ELF可执行文件的程序头表的描述,对ELF文件进行映射,比如代码、数据、只读数据。

4. 初始化ELF进程环境,比如进程启动时EDX寄存器的地址应该是DT_FINI的地址。

5. 将系统调用的返回地址修改成ELF可执行文件的入口点,这个入口点取决于程序的链接方式,对于静态链接的ELF可执行文件,这个程序入口就是ELF文件的文件头中e_entry所指的地址;对于动态链接的ELF可执行文件,程序入口点是动态连接器。

当load_elf_binary()执行完毕,返回至do_execve()再返回到sys_execve(),上面的第5步中已经把系统调用的返回地址改成了被装载的ELF程序的入口地址了。所以当sys_execve()系统调用从内核态返回到用户态时,EIP寄存器存放下一个机器指令的地址, 直接跳转到了ELF程序的入口地址了,于是新的程序开始执行,ELF可执行文件装载完成。

execve() 执行过程中,系统会清掉 fork() 复制的原程序的页目录和页表项,并释放对应页面。系统仅为新加载的程序代码重新设置进程数据结构中的信息,申请和映射了命令行参数和环境参数块所占的内存页面,以及设置了执行代码执行点。此时内核并不从执行文件所在块设备上加载程序的代码和数据。当该过程返回时即开始执行新的程序,但一开始执行肯定会引起缺页异常中断发生。因为代码和数据还未被从块设备上读入内存。此时缺页异常处理程序会根据引起异常的线性地址在主内存区为新程序申请内存页面(内存帧),并从块设备上读入引起异常的指定页面。同时还为该线性地址设置对应的页目录项和页表项。这种加载执行文件的方法称为需求加载(Load on demand)。

2,Android Linker

--dynamic-linker编译参数的ELF文件会加载为静态可执行程序,如init进程:

Android大部分可执行程序使用linker做动态连接器,编译时候加上参数 --dynamic-linker

除了init进程,recoveryadbd进程也没有配置--dynamic-linker链接器。他们在Android.mk里面声明LOCAL_FORCE_STATIC_EXECUTABLE := true或者在Android.bp声明static_executable: true。静态可执行程序不能加载libc等动态库,只能导入static_libs。以上都是针对ELF格式的程序。

当然,/system/bin/linker也是静态连接的。他自己不能配置为动态链接器。LinkerAndroid.bp里面配置static_executable: true。同时根据arch编译汇编代码 begin.S来配置程序入口。Arm64汇编指令 bl:跳转指令,但是在跳转之前,会将下一条指令保存到返回地址(链接寄存器)LR寄存器中。Brbl类似,只是后面参数需要特定的寄存器。

3,Android Linker 拦截信号

应用程序注册信号处理hanlder,当信号事件发生后,内核将信号置为pending状态,在中断返回或者系统调用返回时,查看pending的信号,内核在应用程序的栈上构建一个信号处理栈帧,然后通过中断返回或者系统调用返回到用户态,执行信号处理函数。执行信号处理函数之后,再次通过sigreturn系统调用返回到内核,在内核中再次返回到应用程序被中断打断的地方或者系统调用返回的地方接着运行。 

debuggerd_signal_handler()函数最开始使用互斥锁 pthread_mutex_lock() 来保护线程,方式同一时间多个线程处理信号而导致冲突。接着,调用 log_signal_summary() 来输出一些log 信息信息,例如fault addrsignosignamepidtid、线程名、主线程名等。

接着,调用clone() 函数创建伪线程,并在伪线程中调用 debuggerd_dispatch_pseudothread() 函数,原来的线程原地等待子线程的开始和结束。

如果应用程序没有注册对应的信号处理函数,那么信号发生后,内核按照内核默认的信号处理方式处理该信号。

debuggerd_dispatch_pseudothread() 线程中会 fork 一个子进程,并通过 execle() 系统调用去执行 crash_dump64 程序,父进程等待 crash_dump64 进程退出。

4,LINUX信号

当程序运行出现异常时候,CPU会发出指令异常信号。非可靠信号,由linker注册。Linker加载的动态可执行程序,即使被加载程序调用了注册函数函数,也不能正常收到,因为这些信号已经提前被被linker截断。

中断信号的产生有以下4个来源:1,外设(来自中断控制器); 2,IPI(处理器间中断); 3, CPU异常(比如前一条指令存在除零错误、缺页错误等); 4,中断指令。前两种中断都可以叫做硬件中断,都是异步的;后两种中断都可以叫做软件中断,都是同步的。在arm64架构加,将上述中断分类为异步异常(Physical interruptsVirtual interrupts)和同步异常(同步异常与当前指令的执行直接相关)。其实大同小异。以上是CPU层面的,对于LINUX来说,以上描述的异常或者中断,都代表一次hardirq。当然hardirq可能产生一个softirq到软中断pending列表,或者直接被处理返回。Linux的软中断是进程调度层面的,由内核线程softirqd去读取软中断pending列表,再转化为信号分发。当一个进程收到一个信号的时候,进程会被挂起,开始执行中断处理函数。Linux操作系统当中有62个信号,前31个(1-31):不可靠信号,非实时信号,信号有可能丢失,后31个(34-64):可靠信号,信号不会丢失。非可靠信号注册多次,只会处理第一次注册的,可靠信号注册多次,会处理多次。Linux处理软中断处于程序上下文。处理硬中断处于中断上下文。

5,crash dump流程

crash_dump64 进程中,再fork 一个新进程,父进程通过 fork_exit_read 去等待子进程,子进程继续执行 crash_dump 的任务。

crash_dump64 中,通过 /proc/PID/cmdline 获取进程的名字,通过 /proc/PID/fd 获取此进程打开多少文件,每个文件都有一个描述符。

crash_dump64 中循环遍历这个进程中所有的线程,对进程中的每一个线程进行 ptrace 操作,对目标线程读取器 crashinfocrashinfo 读取完毕后 detech 当前的线程。

之后,在 crash_dump64 中调用 tombstoned_connect() 通过 socket 连接到 tombstoned 进程。根据 signal si_val 的值做不同的判断,为0dump tombstone,为1dump backtrace

如果是 dump tombstone,最终 tombstone 通过 engrave_tombstone() 函数生成,engrave_tombstone() 函数的第二个参数 unwinder 是输出 backtrace 等信息的关键函数。unwinder 初始化过程中获取了当前进程的内存和 memory map,这些信息会在后面帮助 debuggerd 生成 tombstone 文件。

dump_memory_and_code()

打印寄存器附近的memory 信息。

dump_signal_info() 

函数打印引发这次 tombstone 的信号信息摘要。

dump_probable_cause()

通过分析 signal_info 打印可能的原因信息。如果没有分析出可能的原因就不会打印出任何信息。

dump_abort_message()

通过内存信息,确定 abort message

dump_registers()

打印出错时寄存器的值,thread_info 中记录了错误发生时的寄存器信息。

log_backtrace()

调用栈。

dump_memory_and_code()

打印寄存器附近的memory 信息。

 dump_all_maps()

map 信息记录了进程对应的内存映射,包括开始地址,长度,访问权限,文件描述符,offset 等信息。

6,debug dump trace 流程

Debug dump的触发场景一般是system_server发生watch dog,或者系统执行“debuggerd –b [pid]”命令产生。分别是调用进程加载组件debuggerd_client的接口:
dump_backtrace_to_file(), 
或者JNI接口:
android_os_Debug_dumpJavaBacktraceToFileTimeout(), android_os_Debug_dumpNativeBacktraceToFileTimeout()。
信号会对系统调用产生影响,触发系统调用的自动重启动。

debuggerd_trigger_dump向“tombstoned_intercept”发送InterceptRequest 请求,tombstone中的intercept_manager 处理该请求,并返回intercept的状态,如register/started/failed等。

然后向目标进程发送信号signal = (dump_type == kDebuggerdJavaBacktrace) ? SIGQUIT : DEBUGGER_SIGNAL;  --- #define DEBUGGER_SIGNAL (__SIGRTMIN + 3)。

之后等待tombstoned的信息返回。

7,Crash dump与debug dump整体流程

异常发生时, ARM 处理器会跳转到对应该异常的 固定地址 去执行异常处理程序, 这个 固定的地址 就是异常向量。对于tombstone类异常,会产生一个Software interrupt (SWI)。每个cpu会有一个内核线程softirqd轮询读取软中断,并把信号转发给对应的应用。除了SWIARM还会产生ResetUndefined instructionsPrefetch Abort (instruction fetch memory abort) Data Abort (data access memory abort)IRQ (interrupt)以及FIQ (fast interrupt)Arm64会产生:Synchronous exceptionSerrorIRQ FIQ四个类型的同步异常。不同架构中断与异常代码流程底层差异比较大。除了底层上报,还有各个应用程序可以给其他应用发送信号,由操作系统调度。

三、LOG解析

1,debugdump

一般问题不会是libc.so或者libhwbinder.so这种经过多年检验的公共库。找到与问题版本对应的符号产物。本地复现的在符号在out/ 目录里 symbols/ 目录下(或者在编译后的工程先source lunch之后再用addr2line 

addr2line -f –a -C -e

./symbols/vendor/bin/hw/android.hardware.audio@2.0-service  00001771

2,crashdump

四、示例

1,权限问题导致SIGABRT

检查main log,有如下selinux打印:

07-18 17:48:44.679  6105  6105 W Binder:6105_2: type=1400 audit(0.0:3532): avc: denied { read write } for name="hab" dev="tmpfs" ino=15391 scontext=u:r:shell:s0 tcontext=u:object_r:hab_device:s0 tclass=chr_file permissive=0
07-18 17:48:44.691  6105  6114 I Adreno-GSL_RPC: <gsl_rpc_connect:1211>: connecting using conn_id 0
07-18 17:48:44.692  6105  6114 I uhab    : habmm_socket_open: hab: open failed, error code 13 Permission denied
07-18 17:48:44.692  6105  6114 E Adreno-GSL_RPC: <gsl_hab_open:51>: Unable to habmm_socket_open err -13

后来修改:

allow shell hab_device:chr_file_rw_file_perms;

2,线程时序导致空指针异常

pid: 1082, tid: 1534, name: HwBinder:1082_1  >>> /system/vendor/bin/ipacm <<<
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x8
Cause: null pointer dereference
    x0  0000000000000000  x1  0000000000000000  x2  6c206b636172746e  x3  0a2e646165726874
    x4  2072656e65747369  x5  000000719b41d399  x6  20746f4720202928  x7  7364662068746f62
    x8  edf87d25729f7502  x9  edf87d25729f7502  x10 0000000000004001  x11 0000000000000000
    x12 656e657473696c20  x13 000000000000009a  x14 0000000000000000  x15 000000719b98e3f8
    x16 000000719beb11e0  x17 000000719be44950  x18 0000000000000001  x19 0000000000000000
    x20 000000719b98f588  x21 0000000000000006  x22 000000719b98f588  x23 000000719b4327a8
    x24 000000719b48f000  x25 0000005fcc052680  x26 0000000000000000  x27 000000719b98f588
    x28 0000000000000000  x29 000000719b98e440
    sp  000000719b98e410  lr  0000005fcc052908  pc  0000005fcc0500c4

backtrace:
    #00 pc 00000000000330c4  /vendor/bin/ipacm (IPACM_ConntrackListener::CreateConnTrackThreads()+36)
    #01 pc 0000000000035904  /vendor/bin/ipacm (IPACM_OffloadManager::provideFd(int, unsigned int)+644)
    #02 pc 000000000000a1d8  /vendor/lib64/liboffloadhal.so (HAL::setHandles(android::hardware::hidl_handle const&, android::hardware::hidl_handle const&, std::__1::function<void (bool, android::hardware::hidl_string const&)>)+420)
    #03 pc 000000000000ceec  /system/lib64/vndk-28/android.hardware.tetheroffload.config@1.0.so (android::hardware::tetheroffload::config::V1_0::BnHwOffloadConfig::_hidl_setHandles(android::hidl::base::V1_0::BnHwBase*, android::hardware::Parcel const&, android::hardware::Parcel*, std::__1::function<void (android::hardware::Parcel&)>)+316)
    #04 pc 000000000000d1a0  /system/lib64/vndk-28/android.hardware.tetheroffload.config@1.0.so (android::hardware::tetheroffload::config::V1_0::BnHwOffloadConfig::onTransact(unsigned int, android::hardware::Parcel const&, android::hardware::Parcel*, unsigned int, std::__1::function<void (android::hardware::Parcel&)>)+320)
    #05 pc 000000000001d334  /system/lib64/vndk-sp-28/libhwbinder.so (android::hardware::IPCThreadState::executeCommand(int)+640)
    #06 pc 000000000001430c  /system/lib64/vndk-sp-28/libhwbinder.so (android::hardware::IPCThreadState::getAndExecuteCommand()+196)
    #07 pc 0000000000014588  /system/lib64/vndk-sp-28/libhwbinder.so (android::hardware::IPCThreadState::joinThreadPool(bool)+268)
    #08 pc 000000000001c1ac  /system/lib64/vndk-sp-28/libhwbinder.so (android::hardware::PoolThread::threadLoop()+24)
    #09 pc 000000000000fa08  /system/lib64/vndk-sp-28/libutils.so (android::Thread::_threadLoop(void*)+280)
    #10 pc 00000000000819b4  /system/lib64/libc.so (__pthread_start(void*)+36)
    #11 pc 0000000000023478  /system/lib64/libc.so (__start_thread+68)

具体代码就不多贴了,直接贴修改,就懂了。 

3,libart 出现BUS_ADRALN

pid: 2147, tid: 2147, name: m.app.animation  >>> com.app.animation <<<
signal 7 (SIGBUS), code 1 (BUS_ADRALN), fault addr 0x656c62
    x0  0000006f90ee8648  x1  0000000041504e4d  x2  0000007ff0cf5be8  x3  0000006f90668ed8
    x4  0000000012c12da6  x5  0000007ff0cf5c46  x6  6f00630015000000  x7  770067002e006d00
    x8  0000000000656c62  x9  0000006f90e4b700  x10 0000000000000032  x11 69006e0061002e00
    x12 6900740061006d00  x13 000000006e006f00  x14 0000000070ca1348  x15 0000000000003eba
    x16 0000006f90714140  x17 000000701265db30  x18 0000000000000000  x19 0000007ff0cf5be8
    x20 0000000041504e4d  x21 0000006f90e2b6f8  x22 0000006f90e2b6f8  x23 0000007ff0cf6088
    x24 0000007ff0cf5c14  x25 00000070168895e0  x26 000000007090b600  x27 0000000071178cb0
    x28 0000000012c12c20  x29 0000007ff0cf5bd0
    sp  0000007ff0cf5bb0  lr  0000006f90558a30  pc  0000000000656c62

backtrace:
    #00 pc 0000000000656c62  <unknown>
    #01 pc 0000000000473a2c  /system/lib64/libart.so (art::RuntimeCallbacks::DdmPublishChunk(unsigned int, art::ArrayRef<unsigned char const> const&)+56)
    #02 pc 00000000003f0f14  /system/lib64/libart.so (art::DdmServer_nativeSendChunk(_JNIEnv*, _jclass*, int, _jbyteArray*, int, int)+356)
    #03 pc 000000000007fb74  /system/framework/arm64/boot-core-libart.oat (offset 0x79000) (org.apache.harmony.dalvik.ddmc.DdmServer.nativeSendChunk+196)
    #04 pc 000000000013e9bc  /system/framework/arm64/boot-core-libart.oat (offset 0x79000) (org.apache.harmony.dalvik.ddmc.DdmServer.sendChunk+76)
    #05 pc 00000000007e92ac  /system/framework/arm64/boot-framework.oat (offset 0x3d2000) (android.ddm.DdmHandleAppName.sendAPNM+284)
    #06 pc 0000000000879a78  /system/framework/arm64/boot-framework.oat (offset 0x3d2000) (android.app.ActivityThread.handleBindApplication+952)
    #07 pc 0000000000876034  /system/framework/arm64/boot-framework.oat (offset 0x3d2000) (android.app.ActivityThread$H.handleMessage+6916)
    #08 pc 0000000000ab7724  /system/framework/arm64/boot-framework.oat (offset 0x3d2000) (android.os.Handler.dispatchMessage+180)
    #09 pc 0000000000aba820  /system/framework/arm64/boot-framework.oat (offset 0x3d2000) (android.os.Looper.loop+1264)
    #10 pc 0000000000882e28  /system/framework/arm64/boot-framework.oat (offset 0x3d2000) (android.app.ActivityThread.main+664)
    #11 pc 0000000000554c4c  /system/lib64/libart.so (art_quick_invoke_static_stub+604)
    #12 pc 00000000000cf6e8  /system/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+232)
    #13 pc 000000000045c840  /system/lib64/libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*)+104)
    #14 pc 000000000045e294  /system/lib64/libart.so (art::InvokeMethod(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jobject*, _jobject*, unsigned long)+1440)
    #15 pc 00000000003ee1d4  /system/lib64/libart.so (art::Method_invoke(_JNIEnv*, _jobject*, _jobject*, _jobjectArray*)+52)
    #16 pc 000000000011e6d4  /system/framework/arm64/boot-core-oj.oat (offset 0x114000) (java.lang.Class.getDeclaredMethodInternal [DEDUPED]+180)
    #17 pc 0000000000bf1bd8  /system/framework/arm64/boot-framework.oat (offset 0x3d2000) (com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run+136)
    #18 pc 0000000000bf8dc0  /system/framework/arm64/boot-framework.oat (offset 0x3d2000) (com.android.internal.os.ZygoteInit.main+3088)
    #19 pc 0000000000554c4c  /system/lib64/libart.so (art_quick_invoke_static_stub+604)
    #20 pc 00000000000cf6e8  /system/lib64/libart.so (art::ArtMethod::Invoke(art::Thread*, unsigned int*, unsigned int, art::JValue*, char const*)+232)
    #21 pc 000000000045c840  /system/lib64/libart.so (art::(anonymous namespace)::InvokeWithArgArray(art::ScopedObjectAccessAlreadyRunnable const&, art::ArtMethod*, art::(anonymous namespace)::ArgArray*, art::JValue*, char const*)+104)
    #22 pc 000000000045c4a0  /system/lib64/libart.so (art::InvokeWithVarArgs(art::ScopedObjectAccessAlreadyRunnable const&, _jobject*, _jmethodID*, std::__va_list)+424)
    #23 pc 0000000000361b60  /system/lib64/libart.so (art::JNI::CallStaticVoidMethodV(_JNIEnv*, _jclass*, _jmethodID*, std::__va_list)+652)
    #24 pc 00000000000b2374  /system/lib64/libandroid_runtime.so (_JNIEnv::CallStaticVoidMethod(_jclass*, _jmethodID*, ...)+120)
    #25 pc 00000000000b4cf8  /system/lib64/libandroid_runtime.so (android::AndroidRuntime::start(char const*, android::Vector<android::String8> const&, bool)+756)
    #26 pc 000000000000219c  /system/bin/app_process64 (main+1200)
    #27 pc 00000000000acac8  /system/lib64/libc.so (__libc_init+88)

由于每次异常打印的异常地址都是 fault addr 0x656c62,且多个应用都有打印,说明该问题是libart.so强相关,而不是com.app.animation的内存问题。地址0x656c62固定,有可能两种情况,一种是代码中存在字节不对齐情况,一种是这个地址是相对于对象首地址的偏移地址,这是对象被释放后的解引用。

出现的原因是adbd守护进程会因为开机阶段多次重新配置usb模式而被多次杀掉重新启动。如果杀掉重新启动adbd的时候正好碰上zygote孵化进程,某些进程就有概率报告这个错误。

解决方法:

Android12没有该问题。Android12上面gStatethis_指针没有delete, 他们使用C++17std::optional<>模板,无newdelete

4,system_server 调用 debug dump导致audio crash

 

五、其他

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

echarts设置容器宽度设置为100%只显示100px宽度

在使用echarts时&#xff0c;写在tab页中的图表宽度明明设成了100%&#xff0c;但是在页面上实际却只有100px宽 原因很简单&#xff0c;在tab页中&#xff0c;图表的父容器div是隐藏的&#xff08;display&#xff1a;none&#xff09;&#xff0c;图表在执行js初始化的时候找…

井盖位移传感器生产厂家推荐,时刻感知井盖

马路上的井盖虽然看似微不足道&#xff0c;但实际上对于行人的“脚下安全”起着至关重要的作用。这些井盖下连接着供排水、燃气、电力、供热、通信等功能的管路和线路&#xff0c;是城市生命线运行的重要保障。因此保持井盖状态正常、明确管理责任是确保车辆和行人安全通行的重…

【GCC】1:chatgpt:NetworkControllerInterface、GoogCcNetworkController

代码基于 mediasoup-sfu-cpp 中的m77版本。使用chatgpt辅助学习。网络状态估计器:开发中 D:\XTRANS\soup\mediasoup-sfu-cpp\deps\libwebrtc\libwebrtc\api\transport\network_control.h NetworkControllerInterface 网络控制器 此类,使用 网络状态和 通信状态 以 估计网络参…

SQL常见函数整理 _ LAG() 向上偏移

1. 用法 窗口函数&#xff0c;用于访问窗口中当前行之前的行的数据。该函数可以根据需要计算当前行之前的值&#xff0c;使我们能够轻松地比较不同行之间的差异和变化。 2. 基本语法 LAG(column, offset, default_value) OVER (ORDER BY column)column&#xff1a;代表在返回…

Ubuntu 安装 JMeter:轻松上手

Apache JMeter 是一个开源的负载测试工具&#xff0c;可以用于测试静态和动态资源&#xff0c;确定服务器的性能和稳定性。在本文中&#xff0c;我们将讨论如何下载和安装 JMeter。 安装 Java&#xff08;已安装 Java 的此步骤可跳过&#xff09; 要下载 Java&#xff0c;请遵…

pytorch训练模型内存溢出

1、训练模型命令命令 如下所示是训练命名实体识别的命令&#xff0c;在win10系统下执行 activate pytorch cd F:\Python\github\ultralytics-main\submain\pytorch_bert_bilstm_crf_ner-main f: python main.py --bert_dir"../model_hub/chinese-bert-wwm-ext/" --…

Linux 排查必看文件

目录 1. 登录日志 1.1 /var/log/wtmp 1.2 /var/log/btmp.* 1.3 /var/log/lastlog 1.4 /var/log/faillog 1.5 /var/log/secure 1.6 /var/log/auth.log 2. 系统日志 2.1 /var/log/cron.* 2.2 /var/log/syslog 2.3 /var/log/audit/audit.*log 3. 历史命令 3.1 ~/…

Linux基本命令操作 —— 文件夹/文件的创建,删除,查看,重命名......(简单理解 快速上手)

目录 1. 基础命令 1.1 显示当前目录&#xff1a;pwd 1.2 改变当前目录&#xff1a;cd 2. 文件夹的操作命令 2.1 创建文件夹&#xff1a;mkdir 2.2 查看文件夹&#xff1a;ls 2.3 删除文件夹&#xff1a;rmdir &#xff08;不推荐&#xff09; 2.4 复制文件夹&#xff1…

数据分析基础之《matplotlib(2)—折线图》

一、折线图绘制与保存图片 1、matplotlib.pyplot模块 matplotlib.pyplot包含了一系列类似于matlab的画图函数。它的函数作用于当前图形&#xff08;figure&#xff09;的当前坐标系&#xff08;axes&#xff09; import matplotlib.pyplot as plt 2、折线图绘制与显示 展示城…

科普:多领域分布式协同仿真

分布式协同仿真是一种在分布式计算环境中进行协同工作的仿真方法。使用该方法进行协同仿真时&#xff0c;仿真任务将被分发到多个计算节点上&#xff0c;并且这些节点可以同时工作以模拟完整的系统行为。分布式协同仿真已被广泛应用于工程、科学和军事领域&#xff0c;以便更好…

交叉导轨在光学工作台起什么重要作用?

光学工作台常常需要承载和移动各种光学元件和仪器&#xff0c;如望远镜、显微镜、光谱仪等&#xff0c;这些设备需要在空间中进行精确的定位和稳定支撑&#xff0c;而交叉导轨作为一种高精度、高刚度的直线传动元件&#xff0c;为光学工作台提供了重要的支撑和导向。 1>交叉…

Python开源项目之人工智能老照片修复算法学习

文章目录 前言项目环境搭建conda虚拟环境创建激活环境Pytorch安装Synchronized-BatchNorm-PyTorch repository安装Global目录Synchronized-BatchNorm-PyTorch项目部署检测预处理模型下载下载脸部增强模型文件下载依赖完整部署后项目结构 项目使用验证一下总结关于Python技术储备…

万宾科技可燃气体监测仪的功能有哪些?

随着城市人口的持续增长和智慧城市不断发展&#xff0c;燃气作为一种重要的能源供应方式&#xff0c;已经广泛地应用于居民生活和工业生产的各个领域。然而燃气泄漏和安全事故的风险也随之增加&#xff0c;对城市的安全和社会的稳定构成了潜在的威胁。我国燃气管道安全事故的频…

喜讯!云起无垠成为国家信息安全漏洞库(CNNVD)技术支撑单位

近日&#xff0c;云起无垠凭借其在漏洞挖掘、漏洞检测以及漏洞修复等领域的卓越表现&#xff0c;荣获“国家信息安全漏洞库&#xff08;CNNVD&#xff09;技术支撑单位等级证书&#xff08;三级&#xff09;”&#xff0c;正式成为CNNVD技术支撑单位。 中国国家信息安全漏洞库&…

Doris中的物化视图-查询(十九)

物化视图创建完成后&#xff0c;用户的查询会根据规则自动匹配到最优的物化视图。 比如我们有一张销售记录明细表&#xff0c;并且在这个明细表上创建了三张物化视图。一个存储了不同时间不同销售员的售卖量&#xff0c;一个存储了不同时间不同门店的销售量&#xff0c;以及每…

Linux【安全 01】云服务器主机安全加固(修改SSHD端口、禁用登陆失败的IP地址、使用密钥登录)

云服务器主机安全加固 1.SSH登录尝试的系统日志信息2.安全加固方法2.1 修改SSHD端口2.2 禁用登陆失败的IP地址2.3 使用密钥登录 3.总结 1.SSH登录尝试的系统日志信息 Last failed login: Sat Oct 7 14:10:39 CST 2023 from xxx.xx.xx.xxx on ssh:notty There were 10 failed …

仙女麻麻看过来~这是不是你们在找的外套?

分享女儿的秋冬穿搭 时尚与美观兼具的毛毛外套 洋气百搭不挑人穿 谁穿对都好看系列 经典宽松版型 不臃肿对身材包容性很强 小编墙裂推荐哦&#xff01;&#xff01;

计算机组成原理-磁盘存储器

文章目录 总览外存储器磁盘存储器磁盘的性能指标磁盘地址磁盘的工作过程磁盘阵列 总结 总览 外存储器 磁盘存储器 写是利用电流产生磁场从而写磁盘 读是利用载磁体移动时产生的电场从而得到数据 磁性材质易受外界磁场干扰 下图中 载磁体上N S的前后顺序代表对应存储二进制的比…

nginx的n种用法(nginx安装+正向代理+反向代理+透明代理+负载均衡+静态服务器)

nginx的安装 一、安装依赖 # 一键安装四个依赖 yum -y install gcc zlib zlib-devel pcre-devel openssl openssl-devel二、安装nginx yum install nginx三、检查是否安装成功 nginx -v四、启动/停止nginx /etc/init.d/nginx start /etc/init.d/nginx stop五、编辑配置文件…

Git永久或者限时保存用户名及密码,解决每次拉取或者提交代码时都需要手动输入验证信息

介绍 这里以我自身项目情况为例: 依据项目要求,这边使用了 TortoiseGit进行项目的统一管理,下载了 TortoiseGit克隆项目之后,每次拉取或者提交代码,都会弹出一个提示框,要求输入用户名及密码。 解决方式 单个仓库内设置,只作用于对当前仓库 在当前项目目录文件夹下,…