Android dump渲染和合成图层GraphicBuffer指南

news/2024/12/1 0:38:14/

      Android dump渲染和合成图层GraphicBuffer指南



引言

  博客停更很久了,提起笔来渐感生疏啊!看来,还是得抽出时间来更新更新啊!好了,感慨也发完了,是时候切入正题了。本篇博客主要以本人在实际项目的开发中,为了定位Android显示异常究竟是GPU渲染,合成的问题,还是DRM端送显异常的问题而来。这里为了后续的复盘,也为可能有共同需求的朋友所以记录下来,最终发展成为如何dump Android渲染和合成图层GraphicBuffer,并通过YUV软件查看流程(主要是教大家如何把锅甩给队友)!通过本篇博客,读者将会至少学会如下两点:

  • 通过dump Android渲染图层GraphicBuffer,查看Android渲染结果是否正确
  • 通过dump Android合成图层GraphicBuffer,查看Android合成结果是否正确

    这里需要注意一点的是,这里的合成指的是GPU(Client)的合成方式!

好了不多说了,直接开干!

能搜寻到这篇博客的,肯定是对Android graphci有一定掌握的朋友,所以这里就不会过多解释一些名词和代码逻辑了。总之这是一篇专业性比较强的文章(因为一般的朋友也不会搜这个)!

注意:本篇的介绍是基于Android 11®平台为基础的(其中Q的版本差异也不是很大),其中涉及的代码路径如下:

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp
frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp
frameworks/native/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp
frameworks/base/cmds/screencap
frameworks/av/cmds/screenrecord



一.通过Android内置命令dump Android合成图层GraphicBuffer

  在正式开始分析我们如何自行添加dump相关逻辑代码,进而dump渲染和合成图层GraphicBuffer之前,这里我简单介绍下如何使用Android内置的cmd命令,进行相关的dump逻辑,这里的dump逻辑仅仅只能dump GPU合成图层GraphicBuffer。

上述源码的逻辑,强烈建议读者参阅借鉴一下,这个很有必要,因为我的最终代码实现就是参考Android提供的这两个cmd命令而来!


1.1 Screencap dump一帧GPU合成图层GraphicBuffer

  Screencap的命令格式如下,它将当前当前Android显示的图层以GPU合成的模式,并通过png格式保存下来。该命令的使用方法如下:

130|XXX:/ # screencap  --help                                                                                                                       
screencap: invalid option -- -
usage: screencap [-hp] [-d display-id] [FILENAME]-h: this message-p: save the file as a png.-d: specify the physical display ID to capture (default: 0)see "dumpsys SurfaceFlinger --display-id" for valid display IDs.
If FILENAME ends with .png it will be saved as a png.
If FILENAME is not given, the results will be printed to stdout.130|XXX:/ #screencap  -p /sdcard/screencap.png

关于screencap的具体实现逻辑就不过多介绍,感兴趣的可以frameworks/base/cmds/screencap查看相关的源码逻辑!


1.2 Screenrecord dump一帧或多帧GPU合成图层GraphicBuffer

  Screenrecord的命令格式如下,它将当前当前Android显示的图层以GPU合成的模式,并通过多种格式保存下来。该命令的使用方法如下:

1|XXX:/ # screenrecord --help                                                                                                                       
Usage: screenrecord [options] <filename>Android screenrecord v1.3.  Records the device's display to a .mp4 file.Options:
--size WIDTHxHEIGHTSet the video size, e.g. "1280x720".  Default is the device's maindisplay resolution (if supported), 1280x720 if not.  For best results,use a size supported by the AVC encoder.
--bit-rate RATESet the video bit rate, in bits per second.  Value may be specified asbits or megabits, e.g. '4000000' is equivalent to '4M'.  Default 20Mbps.
--bugreportAdd additional information, such as a timestamp overlay, that is helpfulin videos captured to illustrate bugs.
--time-limit TIMESet the maximum recording time, in seconds.  Default / maximum is 180.
--display-id IDspecify the physical display ID to record. Default is the primary display.see "dumpsys SurfaceFlinger --display-id" for valid display IDs.
--verboseDisplay interesting information on stdout.
--helpShow this message.Recording continues until Ctrl-C is hit or the time limit is reached.1|XXX:/ #screenrecord --verbose --time-limit 10 --output-format raw-frames /sdcard/raw-frames.frames
//说明:录制屏幕,录制时间为10s,格式为裸BGR(FORMAT_FRAMES),不添加任何信息
1|XXX:/ #screenrecord --verbose --time-limit 10 --output-format frames /sdcard/frames.frames
//说明:录制屏幕,录制时间为10s,格式为裸BGR(FORMAT_FRAMES),只是每帧前面会加上用于描述帧信息的20字节头。
1|XXX:/ #screenrecord --verbose --time-limit 30 --output-format h264 /sdcard/demo.h264
//说明:录制屏幕,录制时间为30s,格式为h264(FORMAT_H264)1|XXX:/ #screenrecord /sdcard/demo.mp4
//说明:录制屏幕,录制时间为默认的180s,格式为MP4(FORMAT_MP4)

关于screenrecord的具体实现逻辑就不过多介绍,感兴趣的可以frameworks/base/cmds/screencap查看相关的源码逻辑!




二.自定义逻辑dump Android渲染和合成图层GraphicBuffer指南

  通过前面的章节,我们简单介绍了如何使用Android内置的cmds命令dump GPU合成图层的GraphicBuffer,本章节我们重点介绍如何自定义dump Android渲染图层和GPU合成图层。


2.1dump Android渲染图层GraphicBuffer

  这块我们可以在GLESRenderEngine.cpp的如下方法中添加相关的逻辑,如下:

//frameworks/native/libs/renderengine/gl/GLESRenderEngine.cpp
static void dump_content_of_layers_to_file(const sp<GraphicBuffer>& target)
{ALOGE("dump_content_of_layers_to_file");// ALOGE("dump_content_of_layers_to_file");// ALOGE("dump_content_of_layers_to_file");int result = -1;void *addr = NULL;static int DumpSurfaceCount = 0;int32_t bufStride;FILE * pfile = NULL;char layername[100] ;memset(layername,0,sizeof(layername));uint32_t w, s, h, f;w = target->getWidth();h = target->getHeight();s = target->getStride();f = target->getPixelFormat();android_dataspace d;uint32_t buffer_size = 0;d = HAL_DATASPACE_UNKNOWN;buffer_size = s * h * bytesPerPixel(f);bufStride = bytesPerPixel(f);ALOGE("buffer_layer info w:%d h:%d s:%d f:%d d:%d size:%d", w, h, s, f, d, buffer_size);sprintf(layername,"/data/dump/buffer_layer_%d_frame_%d_%d_%d.bin",DumpSurfaceCount,w,h,bufStride);ALOGD("The dump  file info : %s", layername);DumpSurfaceCount ++;pfile = fopen(layername,"w+");if(pfile){//获取FrameBufferSurface对应的ion地址result = target->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &addr);if(addr != NULL){ALOGE("The addr : %p", addr);int result = -1;// system("mkdir /data/dump && chmod 777 /data/dump");result = fwrite( (const void *)addr,(size_t)( (buffer_size)),1,pfile);if(result >0){ALOGD("fwrite success!");}else{ALOGE("fwrite failed error %d", result);}}else{ALOGE("lock buffer error!");}fclose(pfile);target->unlock();}
}status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,const std::vector<const LayerSettings*>& layers,ANativeWindowBuffer* const buffer,const bool useFramebufferCache, base::unique_fd&& bufferFence,base::unique_fd* drawFence) {ATRACE_CALL();if (layers.empty()) {ALOGV("Drawing empty layer stack");return NO_ERROR;}if (bufferFence.get() >= 0) {// Duplicate the fence for passing to waitFence.base::unique_fd bufferFenceDup(dup(bufferFence.get()));if (bufferFenceDup < 0 || !waitFence(std::move(bufferFenceDup))) {ATRACE_NAME("Waiting before draw");sync_wait(bufferFence.get(), -1);}}if (buffer == nullptr) {ALOGE("No output buffer provided. Aborting GPU composition.");return BAD_VALUE;}//dump layerschar pro_value[PROPERTY_VALUE_MAX];property_get("buffer.dump",pro_value,0);if(!strcmp(pro_value,"true")){ALOGD("dump_content_of_layers_to_file!");//dump_content_of_layers_to_file(mCurrentBuffer);//int layer_order = 0;for (auto const layer : layers) {if (layer->source.buffer.buffer != nullptr) {sp<GraphicBuffer> gBuf = layer->source.buffer.buffer;dump_content_of_layers_to_file(gBuf);//layer_order++;}}}...
}

当然上述仅仅是提供了一种思路,具体的上述源码逻辑用在什么地方,读者可以根据自己的需要自行调整。这里我们简单测试一下,看看生成的dump文件如下:

XXX:/data/dump # setprop buffer.dump true
XXX:/data/dump # ls
buffer_layer_0_frame_2880_2560_4.bin  buffer_layer_3_frame_1920_56_4.bin    buffer_layer_6_frame_1920_24_4.bin
buffer_layer_1_frame_1920_1080_4.bin  buffer_layer_4_frame_2880_2560_4.bin  buffer_layer_7_frame_1920_56_4.bin
buffer_layer_2_frame_1920_24_4.bin    buffer_layer_5_frame_1920_1080_4.bin  buffer_layer_8_frame_22_28_4.bin

2.2 dump Android GPU合成图层GraphicBuffer

  这块我们可以在FramebufferSurface.cpp的如下方法中添加相关的逻辑,如下:

//frameworks/native/services/surfaceflinger/DisplayHardware/FramebufferSurface.cppvoid dump_content_of_layers_to_file(const sp<GraphicBuffer>& target)
{ALOGE("dump_content_of_layers_to_file");ALOGE("dump_content_of_layers_to_file");ALOGE("dump_content_of_layers_to_file");int result = -1;void *addr = NULL;static int DumpSurfaceCount = 0;int32_t bufStride;FILE * pfile = NULL;char layername[100] ;memset(layername,0,sizeof(layername));uint32_t w, s, h, f;w = target->getWidth();h = target->getHeight();s = target->getStride();f = target->getPixelFormat();android_dataspace d;uint32_t buffer_size = 0;d = HAL_DATASPACE_UNKNOWN;buffer_size = s * h * bytesPerPixel(f);bufStride = bytesPerPixel(f);ALOGE("FrameBufferSurface info w:%d h:%d s:%d f:%d d:%d size:%d", w, h, s, f, d, buffer_size);sprintf(layername,"/data/dump/hwc_layer_%d_frame_%d_%d_%d.bin",DumpSurfaceCount,w,h,bufStride);ALOGD("The dump  file info : %s", layername);DumpSurfaceCount ++;pfile = fopen(layername,"w+");if(pfile){//获取FrameBufferSurface对应的ion地址result = target->lock(GraphicBuffer::USAGE_SW_READ_OFTEN, &addr);if(addr != NULL){ALOGE("The addr : %p", addr);int result = -1;system("mkdir /data/dump && chmod 777 /data/dump");result = fwrite( (const void *)addr,(size_t)( (buffer_size)),1,pfile);if(result >0){ALOGD("fwrite success!");}else{ALOGE("fwrite failed error %d", result);}}else{ALOGE("lock buffer error!");}fclose(pfile);target->unlock();usleep(1000 * 5);//延时5毫秒}
}#define HWC_DUMP_LAYER 1
status_t FramebufferSurface::nextBuffer(uint32_t& outSlot,sp<GraphicBuffer>& outBuffer, sp<Fence>& outFence,Dataspace& outDataspace) {...#if HWC_DUMP_LAYERchar pro_value[PROPERTY_VALUE_MAX];property_get("hwc.dump",pro_value,0);if(!strcmp(pro_value,"true")){dump_content_of_layers_to_file(mCurrentBuffer);}#endifstatus_t result = mHwc.setClientTarget(mDisplayId, outSlot, outFence, outBuffer, outDataspace);...
}

当然上述仅仅是提供了一种思路,具体的上述源码逻辑用在什么地方,读者可以根据自己的需要自行调整。这里我们简单测试一下,看看生成的dump文件如下:

XXX:/data/dump #setprop hwc.dump true
XXX:/data/dump # ls
hwc_layer_0_frame_1920_1080_4.bin  hwc_layer_2_frame_1920_1080_4.bin  hwc_layer_4_frame_1920_1080_4.bin  hwc_layer_6_frame_1920_1080_4.bin
hwc_layer_1_frame_1920_1080_4.bin  hwc_layer_3_frame_1920_1080_4.bin  hwc_layer_5_frame_1920_1080_4.bin  hwc_layer_7_frame_1920_1080_4.bin

2.3.dump渲染和合成图层GraphicBuffer指南

  到这里dump的相关逻辑就告一段落了,细心的朋友也许会发现dump渲染和合成的图层代码逻辑基本完全一致。是的,这是因为无论是渲染的图层还是合成之后的图层它们都是通过GraphicBuffer来进行存储指向的。这里我们简单总结下dump SurfaceFlinger中各种图层GraphicBuffer内容的思路:

  • 首先要获取各种图层所指向的GraphicBuffer
  • 获取GraphicBuffer的存储地址(通常是通过内存映射过来的)
  • 然后将获取到的地址中的内容,以一定的格式进行存储,通常是GRB888格式(也可以进行相关的封装)

这里重点补充一下,关于dump GraphicBuffer获取的信息大小,格式,以及存储计算规则是否正确可以通过dumpsys SurfaceFlinger进行查看,如下:

GraphicBufferAllocator buffers:
0xb400edc6f16e8500:  420.00 KiB | 1920 (1920) x   56 |    1 |        1 | 0xb00 | NavigationBar0#0
0xb400edc6f16e8780:  420.00 KiB | 1920 (1920) x   56 |    1 |        1 | 0xb00 | NavigationBar0#0
0xb400edc6f16e8a00:  180.00 KiB | 1920 (1920) x   24 |    1 |        1 | 0xb00 | StatusBar#0
0xb400edc6f16e8aa0:  420.00 KiB | 1920 (1920) x   56 |    1 |        1 | 0xb00 | NavigationBar0#0
0xb400edc6f16e8be0:  420.00 KiB | 1920 (1920) x   56 |    1 |        1 | 0xb00 | NavigationBar0#0
0xb400edc6f16e9040:  180.00 KiB | 1920 (1920) x   24 |    1 |        1 | 0xb00 | StatusBar#0
0xb400edc6f16e9400:  180.00 KiB | 1920 (1920) x   24 |    1 |        1 | 0xb00 | StatusBar#0
0xb400edc6f16e95e0:  180.00 KiB | 1920 (1920) x   24 |    1 |        1 | 0xb00 | StatusBar#0
0xb400edc6f16e9900: 8100.00 KiB | 1920 (1920) x 1080 |    1 |        1 | 0xb00 | com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher#0
0xb400edc6f16e9e00: 28800.00 KiB | 2880 (2880) x 2560 |    1 |        2 | 0xb00 | com.android.systemui.ImageWallpaper#0
0xb400edc6f16ea620: 8100.00 KiB | 1920 (1920) x 1080 |    1 |        1 | 0xb00 | com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher#0
0xb400edc6f16eaf80: 8100.00 KiB | 1920 (1920) x 1080 |    1 |        1 | 0x1a00 | FramebufferSurface
0xb400edc6f16eb660: 8100.00 KiB | 1920 (1920) x 1080 |    1 |        1 | 0xb00 | com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher#0
0xb400edc6f16eb8e0: 8100.00 KiB | 1920 (1920) x 1080 |    1 |        1 | 0xb00 | com.android.launcher3/com.android.launcher3.uioverrides.QuickstepLauncher#0
0xb400edc6f2126240: 8100.00 KiB | 1920 (1920) x 1080 |    1 |        1 | 0x1a00 | FramebufferSurface
0xb400edc777c22740:    0.12 KiB |    1 (  32) x    1 |    1 |        1 | 0x300 | placeholder
Total allocated by GraphicBufferAllocator (estimate): 79800.12 KB
Imported gralloc buffers:
+ name:com.android.launcher3/com.android.launcher3.uioverrides.Quickst, id:849, size:8.1e+03KiB, w/h:1920x1080, usage: 0xb00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x1080, stride:7680 bytes, size:8294400
+ name:com.android.launcher3/com.android.launcher3.uioverrides.Quickst, id:844, size:8.1e+03KiB, w/h:1920x1080, usage: 0xb00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x1080, stride:7680 bytes, size:8294400
+ name:com.android.launcher3/com.android.launcher3.uioverrides.Quickst, id:840, size:8.1e+03KiB, w/h:1920x1080, usage: 0xb00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x1080, stride:7680 bytes, size:8294400
+ name:com.android.launcher3/com.android.launcher3.uioverrides.Quickst, id:747, size:8.1e+03KiB, w/h:1920x1080, usage: 0xb00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x1080, stride:7680 bytes, size:8294400
+ name:FramebufferSurface, id:443, size:8.1e+03KiB, w/h:1920x1080, usage: 0x1a00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x1080, stride:7680 bytes, size:8294400
+ name:FramebufferSurface, id:418, size:8.1e+03KiB, w/h:1920x1080, usage: 0x1a00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x1080, stride:7680 bytes, size:8294400
+ name:com.android.systemui.ImageWallpaper#0, id:332, size:2.9e+04KiB, w/h:2880x2560, usage: 0xb00, req fmt:263, fourcc/mod:875713112/0, compressed: falseplanes: R/G/B:	 w/h:2880x2560, stride:11520 bytes, size:29491200
+ name:StatusBar#0, id:321, size:1.9e+02KiB, w/h:1920x24, usage: 0xb00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x24, stride:7680 bytes, size:184320
+ name:StatusBar#0, id:317, size:1.9e+02KiB, w/h:1920x24, usage: 0xb00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x24, stride:7680 bytes, size:184320
+ name:NavigationBar0#0, id:315, size:4.3e+02KiB, w/h:1920x56, usage: 0xb00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x56, stride:7680 bytes, size:430080
+ name:StatusBar#0, id:290, size:1.9e+02KiB, w/h:1920x24, usage: 0xb00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x24, stride:7680 bytes, size:184320
+ name:NavigationBar0#0, id:273, size:4.3e+02KiB, w/h:1920x56, usage: 0xb00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x56, stride:7680 bytes, size:430080
+ name:NavigationBar0#0, id:265, size:4.3e+02KiB, w/h:1920x56, usage: 0xb00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x56, stride:7680 bytes, size:430080
+ name:StatusBar#0, id:204, size:1.9e+02KiB, w/h:1920x24, usage: 0xb00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x24, stride:7680 bytes, size:184320
+ name:NavigationBar0#0, id:175, size:4.3e+02KiB, w/h:1920x56, usage: 0xb00, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1920x56, stride:7680 bytes, size:430080
+ name:placeholder, id:72, size:12KiB, w/h:1x1, usage: 0x300, req fmt:1, fourcc/mod:875708993/0, compressed: falseplanes: R/G/B/A:	 w/h:1x1, stride:128 bytes, size:128
Total imported by gralloc: 8e+04KiB



三.通过7yuv软件查看dump出来的GraphicBuffer

  通过上面一顿猛如虎一样的操作,我们终于dump到了各个图层的GraphicBuffer图层,那么我们要怎么查看上面dump出来的内容,这里推荐Windows下面的7yuv软件查看,至于ubuntu下面的相关软件,这个我暂时没有找到合适的查看软件。这里我们通过7yuv软件打开上面dump出来的文件,如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

这里需要重点注意的是,7yuv查看的时候的宽,高,Format格式的设置。这个是重点!上面的四个截图,就是Android合成的四个图层,应用图层,导航栏,状态栏,壁纸。

好了,到这里我想朋友们,都应该跃跃欲试自己尝试dump和查看了!




四.写在最后

  至此Android dump渲染和合成图层GraphicBuffer阶段整个就完成了,读者是感到意犹未尽呢,还是想说一句尼玛,瞎扯淡呢!

好了,Android dump渲染和合成图层GraphicBuffer分析就告一段落了,各位青山不改绿水长流,各位江湖见!当然各位读者的点赞和关注是我写作路上前进的最大动力了,如果有啥不对或者不爽的也可以踩一踩也无妨!你们的鼓励和批评是博主前进路上最大的动力。

各位读友,千万不要喷我,因为我这也是第一次深入到Android显示这块的源码逻辑,为啥我深入到了这块,因为入职了一家原厂。所以我现在是菜鸟一杯,如果有对Android graphic刚兴趣的朋友,也可以联系我,一起学习进步!


http://www.ppmy.cn/news/487136.html

相关文章

Linux—vmstat命令详解

vmstat概念 vmstat命令是 Virtual Meomory Statistics&#xff08;虚拟内存统计&#xff09;的缩写&#xff0c;可用来动态监控系统资源的 CPU 使用、进程状态、内存使用、虚拟内存使用、硬盘输入/输出状态等信息使用情况 vmstat下载 有些系统可能没有自带vmsata命令&#xf…

一文看懂华为Mate30:4摄5G+7680帧超高速慢动作摄影,6200元起

【惊奇科技】华为Mate30 Pro简单上手 电影镜头貌似有点意思 作者 | 吴波 出品 | 网易手机&数码《易评机》栏目组 &#xff08;油管&B站&#xff1a;惊奇科技 抖音&#xff1a;JQ163&#xff09; 今年对于华为手机来说可谓历经各种坎坷&#xff0c;在重压之下华为还是于…

win11解决80端口默认被占用的问题

错误原因是Nginx无法启动, 提示80端口被占用 报错: [emerg] 14180#15404: bind() to 0.0.0.0:80 failed (10013: An attempt was made to access a socket in a way forbidden by its access permissions) 首先查看80端口被谁占用&#xff1a; TCP 0.0.0.0:80 …

数据处理快人一步!聊一聊如何使用CUDA的Stream

作者 | 伊凡 编辑 | 极市平台 原文链接&#xff1a;https://zhuanlan.zhihu.com/p/51402722 点击下方卡片&#xff0c;关注“自动驾驶之心”公众号 ADAS巨卷干货&#xff0c;即可获取 点击进入→自动驾驶之心技术交流群 后台回复【CUDA】获取CUDA实战书籍&#xff01; 导读 来…

前端大屏适配几种方案

记录一下前端大屏的几种适配方案。 我们是1920*1080的设计稿。 文章目录 一、方案一&#xff1a;remfont-size1.查看适配情况1.1 1920*1080情况下1.2 3840*2160(4k屏)情况下1.3 7680*2160 超宽屏下 二、方案二&#xff1a;vw&#xff08;单位&#xff09;三、方案三&#xff1…

端口排查步骤-7680端口分析-Dosvc服务

简介&#xff1a; 对通过服务启动的进程查找主进程&#xff0c;出现大量7680端口的内网连接&#xff0c;百度未找到端口信息&#xff0c;需证明为系统服务&#xff0c;否则为蠕虫。 1、 确认端口对应进程PID netstat -ano 7680端口对应pid&#xff1a;6128 2、 查找pid对应进程…

【数据库】MySQL 高级(进阶) SQL 语句

文章目录 前提条件一、常用查询1. SELECT&#xff08;显示查询&#xff09;2. DISTINCT&#xff08;不重复查询&#xff09;3. WHERE&#xff08;有条件查询&#xff09;4. AND/OR&#xff08;且/或&#xff09;5. IN &#xff08;显示已知值的字段&#xff09;6. BETWEEN&…

OrCAD Capture 元件位号Part Reference有下划线

原因&#xff1a; 提示用户曾经修改过原理图封装。 现象&#xff1a; USB20_12 解决办法&#xff1a; 对着元器件右键>User Assigned Reference > Uset&#xff0c;即可消除下划线。 修改后&#xff1a;