Android 特许权限白名单

2023-11-14

1. 前言

        在项目开发中,需求:app中有恢复出厂设置的功能,分解这个需求的时候,第一反应肯定不是第三方app,恢复出厂设置肯定需要有系统权限,属于系统级的app。然后在看手机系统中的功能,恢复出厂设置功能属于设置模块,找到源码阅读,当然是能借用的代码就拿过来直接用了。一段操作猛如虎,然后烧写版本无法开机,瞬间石化~, 怎么办,还是看log分析原因吧。

2. log分析

06-23 14:49:09.414  5472  5472 E AndroidRuntime: *** FATAL EXCEPTION IN SYSTEM PROCESS: main
06-23 14:49:09.414  5472  5472 E AndroidRuntime: java.lang.IllegalStateException: Signature|privileged permissions not in privapp-permissions whitelist: {com.test.mtk: android.permission.MASTER_CLEAR}
06-23 14:49:09.414  5472  5472 E AndroidRuntime:        at com.android.server.pm.permission.PermissionManagerService.systemReady(PermissionManagerService.java:2967)
06-23 14:49:09.414  5472  5472 E AndroidRuntime:        at com.android.server.pm.permission.PermissionManagerService.access$100(PermissionManagerService.java:122)
06-23 14:49:09.414  5472  5472 E AndroidRuntime:        at com.android.server.pm.permission.PermissionManagerService$PermissionManagerServiceInternalImpl.systemReady(PermissionManagerService.java:3028)
06-23 14:49:09.414  5472  5472 E AndroidRuntime:        at com.android.server.pm.PackageManagerService.systemReady(PackageManagerService.java:21995)
06-23 14:49:09.414  5472  5472 E AndroidRuntime:        at com.android.server.SystemServer.startOtherServices(SystemServer.java:2104)
06-23 14:49:09.414  5472  5472 E AndroidRuntime:        at com.android.server.SystemServer.run(SystemServer.java:529)
06-23 14:49:09.414  5472  5472 E AndroidRuntime:        at com.android.server.SystemServer.main(SystemServer.java:366)
06-23 14:49:09.414  5472  5472 E AndroidRuntime:        at java.lang.reflect.Method.invoke(Native Method)
06-23 14:49:09.414  5472  5472 E AndroidRuntime:        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:503)
06-23 14:49:09.414  5472  5472 E AndroidRuntime:        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:914)

        Signature|privileged permissions not in privapp-permissions whitelist: {com.test.mtk: android.permission.MASTER_CLEAR}   

        如果要恢复出厂设置,则需要在AndroidManifest.xml文件中配置

       <uses-permission android:name="android.permission.MASTER_CLEAR" />

        而且我也配置了 android:sharedUserId="android.uid.system"  表示属于系统级别的app, 但还是报这个错误, 意思是android.permission.MASTER_CLEAR此权限没有配置到 特许权限白名单中。

3. 需求分解

        2.1 首先我们来看设置模块恢复出厂设置的代码:

# packages/apps/Settings/src/com/android/settings/MasterClearConfirm.java

    private void doMasterClear() {
        Intent intent = new Intent(Intent.ACTION_FACTORY_RESET);
        intent.setPackage("android");
        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
        intent.putExtra(Intent.EXTRA_REASON, "MasterClearConfirm");
        intent.putExtra(Intent.EXTRA_WIPE_EXTERNAL_STORAGE, mEraseSdCard);
        intent.putExtra(Intent.EXTRA_WIPE_ESIMS, mEraseEsims);
        getActivity().sendBroadcast(intent);
    }

就是发送一个带有Intent.ACTION_FACTORY_RESET 属性的广播给系统, 系统服务端frameworks/base/services/core/java/com/android/server/MasterClearReceiver.java 接收到广播后做恢复出厂的任务,大致是这么一个流程。

        2.2 接下来我们在看看Intent.ACTION_FACTORY_RESET 属性的定义

 /**
     * A broadcast action to trigger a factory reset.
     *
     * <p>The sender must hold the {@link android.Manifest.permission#MASTER_CLEAR} permission. The
     * reason for the factory reset should be specified as {@link #EXTRA_REASON}.
     *
     * <p>Not for use by third-party applications.
     *
     * @see #EXTRA_FORCE_FACTORY_RESET
     *
     * {@hide}
     */
    @SystemApi
    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
    public static final String ACTION_FACTORY_RESET = "android.intent.action.FACTORY_RESET";

        看注释我们知道,使用此action 必须要申请MASTER_CLEAR权限,不能用于第三方app。 好接下来我们去看看MASTER_CLEAR权限定义的地方

       2.3 所有权限定义的地方在 frameworks/base/core/res/AndroidManifest.xml 文件中

    <!-- Not for use by third-party applications. -->
    <permission android:name="android.permission.MASTER_CLEAR"
        android:protectionLevel="signature|privileged" />

         从定义的地方,此权限的保护级别为  signature|privileged ,第一点需要有系统签名, 第二点需要放置到手机 */priv-app/ 分区下,才可以正常使用该权限。通过这两点,我们就知道自己的app要放置到手机的哪个分区了。我工程的Android.mk 文件如下:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES := $(call all-java-files-under, src)

LOCAL_MANIFEST_FILE := AndroidManifest.xml

LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res

LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets

LOCAL_PACKAGE_NAME := TestApp

#app编译生成路径:product/priv-app
LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/priv-app

LOCAL_PRIVILEGED_MODULE := true

LOCAL_PRIVATE_PLATFORM_APIS := true

#系统签名
LOCAL_CERTIFICATE := platform

LOCAL_STATIC_ANDROID_LIBRARIES := \
    androidx.core_core \
    androidx.appcompat_appcompat

include $(BUILD_PACKAGE)

include $(call all-makefiles-under,$(LOCAL_PATH))

   把工程代码放到系统源码中编译,最后app生成路径为:  product/priv-app/TestApp/ 

4. 源码看根因

       3.1 好了接下来,我们通过log找到源码报错的地方

#/frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java


private void systemReady() {
        mSystemReady = true;
        // mPrivappPermissionsViolations 不为空,就抛出异常
        if (mPrivappPermissionsViolations != null) {
            throw new IllegalStateException("Signature|privileged permissions not in "
                    + "privapp-permissions whitelist: " + mPrivappPermissionsViolations);
        }

        mPermissionControllerManager = mContext.getSystemService(PermissionControllerManager.class);
        mPermissionPolicyInternal = LocalServices.getService(PermissionPolicyInternal.class);
    }

        通过log查看堆栈  或者 Android studio 断点调试   流程图如下:

 SystemServer,  PMS , PermissionManagerService 都是系统核心的服务,当走到PermissionManagerService.SystemReady()方法这里的时候,直接抛出一个异常,导致系统没有正常启动,就无法顺利开机。

        3.2 我们在看看判断条件  mPrivappPermissionsViolations != null 时才会抛出异常,接下来继续分析mPrivappPermissionsViolations是在哪里赋值的

#/frameworks/base/services/core/java/com/android/server/pm/permission/PermissionManagerService.java

 private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,
            BasePermission bp, PermissionsState origPermissions) {
        boolean oemPermission = bp.isOEM();
        boolean vendorPrivilegedPermission = bp.isVendorPrivileged();
        boolean privilegedPermission = bp.isPrivileged() || bp.isVendorPrivileged();
        boolean privappPermissionsDisable =
                RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE;
        boolean platformPermission = PLATFORM_PACKAGE_NAME.equals(bp.getSourcePackageName());
        boolean platformPackage = PLATFORM_PACKAGE_NAME.equals(pkg.packageName);
        if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivileged()
                && !platformPackage && platformPermission) {
            if (!hasPrivappWhitelistEntry(perm, pkg)) {
                // Only report violations for apps on system image
                if (!mSystemReady && !pkg.isUpdatedSystemApp()) {
                    // it's only a reportable violation if the permission isn't explicitly denied
                    ArraySet<String> deniedPermissions = null;
                    if (pkg.isVendor()) {
                        deniedPermissions = SystemConfig.getInstance()
                                .getVendorPrivAppDenyPermissions(pkg.packageName);
                    } else if (pkg.isProduct()) {
                        #走这里的分支  deniedPermissions 值为null
                        deniedPermissions = SystemConfig.getInstance()
                                .getProductPrivAppDenyPermissions(pkg.packageName);
                    } else if (pkg.isProductServices()) {
                        deniedPermissions = SystemConfig.getInstance()
                                .getProductServicesPrivAppDenyPermissions(pkg.packageName);
                    } else {
                        deniedPermissions = SystemConfig.getInstance()
                                .getPrivAppDenyPermissions(pkg.packageName);
                    }
                    #通过打印log: deniedPermissions == null 为true, 说明权限白名单中没有配置MASTER_CLEAR权限,这里是问题的原因。
                    final boolean permissionViolation =
                            deniedPermissions == null || !deniedPermissions.contains(perm);
                    #这里的判断条件为true  
                    if (permissionViolation) {
                        Slog.w(TAG, "Privileged permission " + perm + " for package "
                                + pkg.packageName + " - not in privapp-permissions whitelist");

                        if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) {
                            if (mPrivappPermissionsViolations == null) {
                                mPrivappPermissionsViolations = new ArraySet<>();
                            }
          //添加包名和权限名,所以mPrivappPermissionsViolations有值,不为空
                            mPrivappPermissionsViolations.add(pkg.packageName + ": " + perm);
                        }
                    } else {
                        return false;
                    }
                }

我把app放置到product/priv-app 路径下,所以走的逻辑为:

else if (pkg.isProduct()) {
                        deniedPermissions = SystemConfig.getInstance()
                                .getProductPrivAppDenyPermissions(pkg.packageName);
}

继续跟踪代码,找到SystemConfig.java 中的 getProductPrivAppDenyPermissions 方法


 public ArraySet<String> getProductPrivAppDenyPermissions(String packageName) {
        return mProductPrivAppDenyPermissions.get(packageName);
 }

接下来,我们继续看mProductPrivAppDenyPermissions变量是怎么赋值的, 我们回到SystemConfig.java  的构造方法:

#frameworks/base/core/java/com/android/server/SystemConfig.java

 SystemConfig() {
        // Read configuration from system
        readPermissions(Environment.buildPath(
                Environment.getRootDirectory(), "etc", "sysconfig"), ALLOW_ALL);

        // Read configuration from the old permissions dir
        readPermissions(Environment.buildPath(
                Environment.getRootDirectory(), "etc", "permissions"), ALLOW_ALL);

        // Vendors are only allowed to customize these
        int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PRIVAPP_PERMISSIONS
                | ALLOW_ASSOCIATIONS;
        if (Build.VERSION.FIRST_SDK_INT <= Build.VERSION_CODES.O_MR1) {
            // For backward compatibility
            vendorPermissionFlag |= (ALLOW_PERMISSIONS | ALLOW_APP_CONFIGS);
        }
        readPermissions(Environment.buildPath(
                Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);
        readPermissions(Environment.buildPath(
                Environment.getVendorDirectory(), "etc", "permissions"), vendorPermissionFlag);

        // Allow ODM to customize system configs as much as Vendor, because /odm is another
        // vendor partition other than /vendor.
        int odmPermissionFlag = vendorPermissionFlag;
        readPermissions(Environment.buildPath(
                Environment.getOdmDirectory(), "etc", "sysconfig"), odmPermissionFlag);
        readPermissions(Environment.buildPath(
                Environment.getOdmDirectory(), "etc", "permissions"), odmPermissionFlag);

        String skuProperty = SystemProperties.get(SKU_PROPERTY, "");
        if (!skuProperty.isEmpty()) {
            String skuDir = "sku_" + skuProperty;

            readPermissions(Environment.buildPath(
                    Environment.getOdmDirectory(), "etc", "sysconfig", skuDir), odmPermissionFlag);
            readPermissions(Environment.buildPath(
                    Environment.getOdmDirectory(), "etc", "permissions", skuDir),
                    odmPermissionFlag);
        }

        // Allow OEM to customize these
        int oemPermissionFlag = ALLOW_FEATURES | ALLOW_OEM_PERMISSIONS | ALLOW_ASSOCIATIONS;
        readPermissions(Environment.buildPath(
                Environment.getOemDirectory(), "etc", "sysconfig"), oemPermissionFlag);
        readPermissions(Environment.buildPath(
                Environment.getOemDirectory(), "etc", "permissions"), oemPermissionFlag);

        // Allow Product to customize all system configs
        readPermissions(Environment.buildPath(
                Environment.getProductDirectory(), "etc", "sysconfig"), ALLOW_ALL);
        readPermissions(Environment.buildPath(
                Environment.getProductDirectory(), "etc", "permissions"), ALLOW_ALL);

        // Allow /product_services to customize all system configs
        readPermissions(Environment.buildPath(
                Environment.getProductServicesDirectory(), "etc", "sysconfig"), ALLOW_ALL);
        readPermissions(Environment.buildPath(
                Environment.getProductServicesDirectory(), "etc", "permissions"), ALLOW_ALL);
    }

这段代码的大致工作:就是读取手机中 system/etc/permissions/    product/etc/permissions/  odm/etc/permissions/   vendor/ete/permissons/ 路径下的权限配置.xml 文件,如下:

 如果该路径下没有log中提及的   com.test.mtk.xml  文件,就满足上面源码分析的条件,就抛异常导致系统无法正常开机启动。

5. 解决方案

       4.1  我的app是放置在手机系统product/priv-app 路径下的, 对应的特许权限白名单文件也应该放置到product/etc/permissions/ 路径下  怎么修改呢?我是直接通过Andorid.mk  文件实现的

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES := $(call all-java-files-under, src)

LOCAL_MANIFEST_FILE := AndroidManifest.xml

LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res

LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets

LOCAL_PACKAGE_NAME := TestApp

LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/priv-app

######编译priv-app 权限到apk中###########
LOCAL_REQUIRED_MODULES := com.test.mtk.xml

LOCAL_PRIVILEGED_MODULE := true
LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_CERTIFICATE := platform

LOCAL_STATIC_ANDROID_LIBRARIES := \
    androidx.core_core \
    androidx.appcompat_appcompat

include $(BUILD_PACKAGE)


######预编译priv-app 权限,输出路径为product/etc/permissions###########
# Permissions pre-grant
include $(CLEAR_VARS)
LOCAL_MODULE := com.test.mtk.xml
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT)/etc/permissions
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)

include $(call all-makefiles-under,$(LOCAL_PATH))

com.test.mtk.xml 内容:

<?xml version="1.0" encoding="utf-8"?>
<permissions>
    <privapp-permissions package="com.test.mtk">
        <permission name="android.permission.MASTER_CLEAR" />
    </privapp-permissions>
</permissions>

     4.2  假如你的app打算编译到手机的system/priv-app 路径下,则配置的特许权限白名单要对应放置到system/etc/permissions/ 路径下,则有两种修改方法:

      第一种方案 : 修改 framework/base/data/etc/privapp-permissions-platform.xml 把自己的权限加入其中,它最后编译后输出的路径为:/system/etc/permissions/,  是由Android.bp实现

# framework/base/data/etc/Android.bp

prebuilt_etc {
    name: "privapp-permissions-platform.xml",
    sub_dir: "permissions",
    src: "privapp-permissions-platform.xml",
}

       第二种方案: 还是通过Android.mk 文件实现,稍微修改一下路径就可以了:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES := $(call all-java-files-under, src)

LOCAL_MANIFEST_FILE := AndroidManifest.xml

LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res

LOCAL_ASSET_DIR := $(LOCAL_PATH)/assets

LOCAL_PACKAGE_NAME := TestApp

#app编译到system/priv-app/路径下
LOCAL_MODULE_PATH := $(TARGET_OUT)/priv-app

######编译priv-app 权限到apk中###########
LOCAL_REQUIRED_MODULES := com.test.mtk.xml

LOCAL_PRIVILEGED_MODULE := true
LOCAL_PRIVATE_PLATFORM_APIS := true
LOCAL_CERTIFICATE := platform

LOCAL_STATIC_ANDROID_LIBRARIES := \
    androidx.core_core \
    androidx.appcompat_appcompat

include $(BUILD_PACKAGE)


######预编译priv-app 权限,输出路径为system/etc/permissions###########
# Permissions pre-grant
include $(CLEAR_VARS)
LOCAL_MODULE := com.test.mtk.xml
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)

include $(call all-makefiles-under,$(LOCAL_PATH))

推荐这种方案,原因:特许权限白名单(com.test.mtk.xml)是与app的源码在一起,便于代码移植,也算是间接的解耦了。 如果是用第一种方案,你做的功能,如果换一个人来维护,这个privapp-permissions-platform.xml 修改很容易漏掉就又无法开机了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android 特许权限白名单 的相关文章

  • Android 12 源码下载、编译与烧录到Pixel 3a

    android 12 源码下载 编译与烧录到Pixel 3a 当前设备环境 源码下载 温馨跳转 个人总结源码下载 谷歌手机设备驱动的下载 编译 烧录 当前设备环境 操作系统 ubuntu 18 04 LTS 手机 谷歌手机Pixel 3a
  • 深入AMS源码(四)——ActivityManagerService的进程管理

    1 AMS中的进程管理 final ArrayList
  • AOD相关机制

    AOD的概念 AOD 即A lways O n D isplay 是android一种低功耗的显示模式的一种应用 他能保证屏幕某块区域一直亮 该应用开启时绘制的频率会低于正常的频率 由于AOD现实的不是和正常的亮屏之后显示的一样 只 会显示
  • Android四种Activity的加载模式

    建议首先阅读下面两篇文章 这样才可以更好的理解Activity的加载模式 Android的进程 线程模型 http www cnblogs com ghj1976 archive 2011 04 28 2031586 html 其中对 An
  • 深入PMS源码(三)—— PMS中intent-filter的匹配架构

    1 简介 由前面深入PMS源码 一 PMS的启动过程和执行流程和深入PMS源码 二 APK的安装和卸载源码分析两篇文章知道 无论是Android系统启动后执行的PMS启动 还是使用PackageInstaller安装APK的过程 最终都会使
  • Android混合开发全解析

    现在的app都开始流行混合开发了 这是一个app开发的新技术 作为android程序猿的我们也应该要了解并且掌握他 那么在使用之前 我们一定要搞清楚 我们的哪些场景使用混合开发好一些呢 这个问题一定要搞清楚 因为现在的混合开发还不成熟 We
  • android GMS认证之CTS 常用命令

    http blog csdn net hfreeman2008 article details 51084821 前面的一篇文章 lt
  • Android 全局手势识别原理

    本文是对全局手势识别进行分析 那什么是全局手势呢 简单来说就是在任何界面都需要识别的手势 比如 在任何界面从手机屏幕左侧滑动 当前的界面会退出 类似 back 键 我们知道 在 Android 系统中一个 Activity 在显示时 当对屏
  • Android zygote进程启动过程

    zygote启动过程中涉及到以下模块 app process zygote USAP socket FileDescriptor FD AndroidRuntime AppRuntime 定义于app process模块 继承自Androi
  • Android开发之RecyclerView的使用全解

    转自 http blog csdn net dmk877 article details 50816933 自Android 5 0之后 谷歌公司推出了RecylerView控件 RecylerView 我想看到一个新名词后大部分人会首先发
  • Android数据的四种存储方式

    Android数据的四种存储方式 SharePreferences SQLite Contert Provider File 网络存储 作为一个完整的应用程序 数据存储的操作是必不可少的 Android系统提供了四种存储数据方式 分别为 S
  • 如何dump SKP,SKP抓取

    1 如何dump SKP 我们知道绘制的操作 主要都是在SkiaPipline renderframe中进行的 frameworks base libs hwui pipeline skia SkiaPipeline cpp 429 voi
  • Service能够创建界面(addView)吗?

    一个Service能够创建界面 addView 吗 一个app 只有Service 没有Activity 能够通过WindowManager调用addView 添加可视界面吗 答案是可以 但是能够创建的界面类型 WindowManager
  • Android InputEventReceiver事件接收流程分析

    本文基于Android 12 InputEvent经过inputflinger读取后 通过Inputchannel发送到Java层的InputEventReceiver对象 输入事件和View的状态强相关 事件发送需要确定当前的焦点App
  • Android中的Loaders机制

    转自 http blog csdn net guoshaobei article details 17451647 Loaders机制在Android 3 0版本后引入 Loaders机制使一个Activity或者一个Fragment更加容
  • 从setContentView到onResume应用显示过程分析

    之前总体笼统地分析了Acitivity从启动到显示的过程 Activty启动到显示的过程 一 Activty启动到显示的过程 二 发现很多细节没有注意到 后续挑些过程中比较重要的部分重点分析 在上一篇文章分析了一个app从zygote到on
  • Android 特许权限白名单

    1 前言 在项目开发中 需求 app中有恢复出厂设置的功能 分解这个需求的时候 第一反应肯定不是第三方app 恢复出厂设置肯定需要有系统权限 属于系统级的app 然后在看手机系统中的功能 恢复出厂设置功能属于设置模块 找到源码阅读 当然是能
  • adb install安装流程

    把一个编译好的APK通过 include BUILD PREBUILT 预制到系统中 但是启动后一直crash log中显示 dlopen failed cannot locate symbol 02 25 16 18 20 143 126
  • Android图形显示系统4 图像生产者(下)

    一 概述 在上一篇文章 Android图形显示系统2 图像消费者 中 我们详细地讲解了图像消费者 我们已经了解了 Android 中的图像元数据是如何被 SurfaceFlinger HWComposer 或者 OpenGL ES 消费的
  • Android 13 - binder阅读(6)- 使用ServiceManager获取服务

    最近事情好多 使用ServiceManager获取服务就暂时先不学习了 不过从之前的学习中我们也大致可以猜到使用ServiceManager获取服务的过程 根据服务名称获取到ServiceManager中服务代理对应的Handle 再到Bi

随机推荐

  • 计组(唐第三版)

    目录 前言 讲解问题 1 快速理解基本的电路符号 a 高低电平 b 高电平有效和低电平有效的理解及表示 c 基本的门元件 2 数电小白也能看得懂的74138译码器 c 74138译码器结构功能 c 74138译码器具体结构 3 唐书例4 1
  • 最详细的Python安装+Pycharm安装配置教程,从下载到安装配置

    最详细的Python安装 Pycharm安装配置教程 从下载到安装配置 本章节我们将向大家介绍如何在本地搭建Python开发环境 Python可应用于多平台包括 Linux 和 Mac OS X 你可以通过终端窗口输入 python 命令来
  • docker-compose实现容器任务编排

    项目开发中 往往都需要启动多个容器 容器之间又相互依赖 存在着启动的顺序 docker compose就是可以通过命令控制依次启动容器 容器编排工具可以帮助我们批量地创建 调度和管理容器 帮助我们解决规模化容器的部署问题 Docker 三种
  • PyQt5 按钮Buttons样式设计

    效果截图 PyQt 模型设计 PyQt 设计器截图 ui 源码
  • 存储IOPS指标说明

    二 IOPS 说明 2 1 IOPS Input OutputPer Second IOPS 即每秒的输入输出量 或读写次数 是衡量磁盘性能的主要指标之一 IOPS是指单位时间内系统能处理的I O请求数量 一般以每秒处理的I O请求数量为单
  • 材料阅读 - 四散的安全

    20201005 阅读了三篇与安全相关的文章 这里记录一下 1 以 威胁应对 为中心 看企业信息安全能力建设 这篇文章发表在了很多地方 发表的念头也比较早了 都过了两年了 对企业的安全能力 从架构上 最后到以后的安全产品都进行了介绍 同时也
  • 多态性 - C++中实现运行时多态的方式

    一 概述 C 中的多态性是指同一个函数可以有多种不同的实现方式 并且在运行时根据实际情况进行选择执行 在C 中实现多态有两种方式 静态多态和动态多态 静态多态是指在编译时确定函数的实现 包括函数重载和模板函数 动态多态是指在运行时根据对象的
  • 针对无人机航拍视频中动态背景下的目标检测

    目录 目录 传统目标检测技术 传统目标检测技术 1 帧间差分 通过连续两帧相同位置像素点间的灰度差来确定目标移动 但只适用于静态背景和目标单一条件的目标检测 仅适用于无人机悬停状态下的目标检测 2 背景差分法 通过预先设置背景 然后通过对检
  • “体育游戏第一股”投资未来,望尘科技走向价值兑现周期

    2022年的游戏市场 遗憾以疲弱之势落下帷幕 游戏市场规模与用户数量 均出现了小幅下降 显示出存量市场的典型特征 但与此同时 更多垂直领域的拳头产品 响应市场需求的精品游戏 却屡屡掀起热潮 去年随世界杯而来的 最佳球会 就是一例 最佳球会
  • C# 基础知识 (四).C#简介及托管代码

    暑假转瞬即逝 从10天的支教生活到1周的江浙沪旅游 在这个漫长的暑假中我经历了很多东西 也学到了很多东西 也认识到了很多不足之处 闲暇之余我准备重新进一步巩固C 相关知识 包括C 入门知识 C 并行开发 ASP网站等 这篇文章我介绍的是书籍
  • JS 地址截取 省市区 (含自治区,直辖市,县,自治县)

    方法一 通过js处理 var str 湖北省武汉市江夏区文化大道110号 var str 内蒙古自治区乌兰浩特市二区 var str 重庆市渝中区中兴路 var str 湖北省黄石市阳新县 var str 湖北省宜昌市长阳土家族自治县 va
  • 同步与异步的区别

    同步与异步的区别 最近在学习ajax 而ajax Asynchronous JavaScript and XML 是一种异步的JavaScript和XML技术 鉴于此 就先来了解下同步与异步的思想和区别 一 同步与异步 同步 同步是指一个进
  • LIBSVM入门

    一 引言 LIBSVM提供了多语言 java python和matlab 的SVM实现 可以便捷地处理分类或回归问题 本文记录基于matlab的LIBSVM学习笔记 二 环境搭建 LIBSVM下载链接 https github com cj
  • Vue3 + Element Plus 按需引入 - 自动导入

    文章目录 1 前言 1 1 目的 1 2 最终效果 2 准备工作 3 按需引入 3 1 安装插件 3 2 修改 vite config ts 文件 4 其他 4 1 ElMessageBox 使用时报错 4 1 1 Eslint 报错 El
  • B/S架构和C/S架构的定义和区别(不同点)

    一 B S架构和C S架构的定义 1 B S Browser Server 浏览器和服务器架构 比如百度 微博 淘宝等网站 包含寄户端浏览器 web应用服务器 数据库服务器的软件系统 用户只需要一个浏览器就可以访问服务 系统更新时候 只需要
  • 【操作系统】操作系统知识点总结(秋招篇)

    文章目录 前言 操作系统主要做了哪些工作 进程 线程 协程之间的区别 进程的组成部分 介绍一下进程的PCB 讲一下进程的五态 以及它们的状态转移 用户态和内核态是什么 进程在用户态和内核态之间是如何切换的 讲一下进程之间的通信方式 讲一下进
  • [Unity2D]Tilemap Collider2D只给部分地图瓦片加上Collider的方法

    Unity2D Tilemap Collider2D 给Tilemap中的瓦片网格加上碰撞器 绿色的边框就是碰撞器 需要注意的是 如果给Tilpmap加碰撞器 其整个Tilpmap上的瓦片都会加上碰撞器 在一个Tilpmap上 如果想让部分
  • mongodb监控工具mongostat

    mongostat是mongodb自带的状态检测工具 在命令行下使用 会间隔固定时间获取mongodb的当前运行状态 并输出 常用命令格式 mongostat host 192 168 1 100 27017 uroot p123456 a
  • CreateRemoteThread的使用(转载)

    先解释一下远程进程 其实就是要植入你的代码的进程 相对于你的工作进程 如果叫本地进程的话 它就叫远程进程 可理解为宿主 首先介绍一下我们的主要工具CreateRemoteThread 这里先将函数原型简单介绍以下 CreateRemoteT
  • Android 特许权限白名单

    1 前言 在项目开发中 需求 app中有恢复出厂设置的功能 分解这个需求的时候 第一反应肯定不是第三方app 恢复出厂设置肯定需要有系统权限 属于系统级的app 然后在看手机系统中的功能 恢复出厂设置功能属于设置模块 找到源码阅读 当然是能