input device 按键处理

2024-06-03 15:32
文章标签 input device 按键 处理

本文主要是介绍input device 按键处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

/**********************************************************************************/
目标:
/**********************************************************************************/
1. 关屏模式下:按下powerKey亮屏的过程:
2. 亮屏模式下:按下powerKey 出现关机界面的过程
3. 亮屏模式下:长按键,重启的过程
4. 关屏模式下:长按键,重启的过程


/**********************************************************************************/
inputManaerService的初始化过程
frameworks/base/services/java/com/android/server/SystemServer.java
    private void startOtherServices() {
            Slog.i(TAG, "Input Manager");
            // xxx MOD:
            // inputManager = new InputManagerService(context);
            inputManager = new xxxInputManagerService(context, null);


            Slog.i(TAG, "Window Manager");
            wm = WindowManagerService.main(context, inputManager,
                    mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL,
                    !mFirstBoot, mOnlyCore);
            ServiceManager.addService(Context.WINDOW_SERVICE, wm);
            ServiceManager.addService(Context.INPUT_SERVICE, inputManager);


            mActivityManagerService.setWindowManager(wm);


            inputManager.setWindowManagerCallbacks(wm.getInputMonitor());
            inputManager.start();


            try {
                Slog.i(TAG, "Wired Accessory Manager");
                // Listen for wired headset changes
                inputManager.setWiredAccessoryCallbacks(
                        new WiredAccessoryManager(context, inputManager));
            } catch (Throwable e) {
                reportWtf("starting WiredAccessoryManager", e);
            }
}


/**********************************************************************************/
xxx/frameworks/base/services/java/com/android/server/input/xxxInputManagerService.java
public class xxxInputManagerService extends xxxBaseInputManagerService {


    private Context mContext;


    public xxxInputManagerService(Context context, Handler handler) {
        super(context, handler);
        mContext = context;
    }


    @Override
    public void start() {
        super.start();
        HandyMode.initialize(mContext, this);
    }
}


xxx/frameworks/base/services/java/com/android/server/input/xxxBaseInputManagerService.java
public class xxxBaseInputManagerService extends InputManagerService {


    public xxxBaseInputManagerService(Context context, Handler handler) {
        super(context, handler);
    }
}


/**********************************************************************************/
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
/*
 * Wraps the C++ InputManager and provides its callbacks.
 */
public class InputManagerService extends IInputManager.Stub
        implements Watchdog.Monitor {
    static final String TAG = "InputManager";
    private static native long nativeInit(InputManagerService service,
            Context context, MessageQueue messageQueue);
    private static native void nativeStart(long ptr);
}


/**********************************************************************************/
frameworks/base/core/java/android/hardware/input/IInputManager.aidl
/** @hide */
interface IInputManager {
    // Gets input device information.
    InputDevice getInputDevice(int deviceId);
    int[] getInputDeviceIds();
}


service的名字在那个文件定义的?
frameworks/base/core/java/android/content/Context.java
    /**
     * Use with {@link #getSystemService} to retrieve a
     * {@link android.hardware.input.InputManager} for interacting with input devices.
     *
     * @see #getSystemService
     * @see android.hardware.input.InputManager
     */
    public static final String INPUT_SERVICE = "input";


frameworks/base/core/java/android/hardware/input/


InputManagerService.java的构造函数:
    public InputManagerService(Context context) {
        this.mContext = context;
        this.mHandler = new InputManagerHandler(DisplayThread.get().getLooper());


        mPtr = nativeInit(this, mContext, mHandler.getLooper().getQueue());


        LocalServices.addService(InputManagerInternal.class, new LocalService());
    }


    private static native long nativeInit(InputManagerService service,
            Context context, MessageQueue messageQueue);




/**********************************************************************************/
frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static jlong nativeInit(JNIEnv* env, jclass /* clazz */,
        jobject serviceObj, jobject contextObj, jobject messageQueueObj) {
    sp<MessageQueue> messageQueue = android_os_MessageQueue_getMessageQueue(env, messageQueueObj);
    if (messageQueue == NULL) {
        jniThrowRuntimeException(env, "MessageQueue is not initialized.");
        return 0;
    }


    NativeInputManager* im = new NativeInputManager(contextObj, serviceObj,
            messageQueue->getLooper());
    im->incStrong(0);
    return reinterpret_cast<jlong>(im);
}


NativeInputManager::NativeInputManager(jobject contextObj,
        jobject serviceObj, const sp<Looper>& looper) :
        mLooper(looper), mInteractive(true) {
    JNIEnv* env = jniEnv();


    mContextObj = env->NewGlobalRef(contextObj);
    mServiceObj = env->NewGlobalRef(serviceObj);


    {
        AutoMutex _l(mLock);
        mLocked.systemUiVisibility = ASYSTEM_UI_VISIBILITY_STATUS_BAR_VISIBLE;
        mLocked.pointerSpeed = 0;
        mLocked.pointerGesturesEnabled = true;
        mLocked.showTouches = false;
    }
    mInteractive = true;


    sp<EventHub> eventHub = new EventHub();
    mInputManager = new InputManager(eventHub, this, this);
}


/**********************************************************************************/
frameworks/native/services/inputflinger/


EventHub::EventHub(void) :
        mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
        mOpeningDevices(0), mClosingDevices(0),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false), mNeedToScanDevices(true),
        mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
}


InputManager::InputManager(
        const sp<EventHubInterface>& eventHub,
        const sp<InputReaderPolicyInterface>& readerPolicy,
        const sp<InputDispatcherPolicyInterface>& dispatcherPolicy) {
    mDispatcher = new InputDispatcher(dispatcherPolicy);
    mReader = new InputReader(eventHub, readerPolicy, mDispatcher);
    initialize();
}


InputManager::InputManager(
        const sp<InputReaderInterface>& reader,
        const sp<InputDispatcherInterface>& dispatcher) :
        mReader(reader),
        mDispatcher(dispatcher) {
    initialize();
}




void InputManager::initialize() {
    mReaderThread = new InputReaderThread(mReader);
    mDispatcherThread = new InputDispatcherThread(mDispatcher);
}


/**********************************************************************************/
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
    public void start() {
        Slog.i(TAG, "Starting input manager");
        nativeStart(mPtr);


        // Add ourself to the Watchdog monitors.
        Watchdog.getInstance().addMonitor(this);


        registerPointerSpeedSettingObserver();
        registerShowTouchesSettingObserver();


        mContext.registerReceiver(new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                updatePointerSpeedFromSettings();
                updateShowTouchesFromSettings();
            }
        }, new IntentFilter(Intent.ACTION_USER_SWITCHED), null, mHandler);


        updatePointerSpeedFromSettings();
        updateShowTouchesFromSettings();
    }


frameworks/base/services/core/jni/com_android_server_input_InputManagerService.cpp
static void nativeStart(JNIEnv* env, jclass /* clazz */, jlong ptr) {
    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);


    status_t result = im->getInputManager()->start();
    if (result) {
        jniThrowRuntimeException(env, "Input manager could not be started.");
    }
}


status_t InputManager::start() {
    status_t result = mDispatcherThread->run("InputDispatcher", PRIORITY_URGENT_DISPLAY);


    result = mReaderThread->run("InputReader", PRIORITY_URGENT_DISPLAY);




    return OK;
}


/**********************************************************************************/
1. 关屏模式下:按下powerKey亮屏的过程
/**********************************************************************************/
void InputReader::loopOnce() {
    int32_t oldGeneration;
    int32_t timeoutMillis;
    bool inputDevicesChanged = false;
    Vector<InputDeviceInfo> inputDevices;


    size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);


    { // acquire lock
        AutoMutex _l(mLock);


        if (count) {
            processEventsLocked(mEventBuffer, count);
        }


    } // release lock




    // Flush queued events out to the listener.
    mQueuedListener->flush();
}




struct input_event {
struct timeval time;
__u16 type;
__u16 code;
__s32 value;
};


/*
 * A raw event as retrieved from the EventHub.
 */
struct RawEvent {
    nsecs_t when;
    int32_t deviceId;
    int32_t type;
    int32_t code;
    int32_t value;
};
从input_event 转换成 raw_event: 数据成员多出了 deviceID:
size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
    
    struct input_event readBuffer[bufferSize];
    RawEvent* event = buffer;
            Device* device = mDevices.valueAt(deviceIndex);
            if (eventItem.events & EPOLLIN) {
                int32_t readSize = read(device->fd, readBuffer,
                        sizeof(struct input_event) * capacity);


                        event->deviceId = deviceId;
                        event->type = iev.type;
                        event->code = iev.code;
                        event->value = iev.value;
                        event += 1;
}


void InputReader::processEventsLocked(const RawEvent* rawEvents, size_t count) ->
processEventsForDeviceLocked(deviceId, rawEvent, batchSize);
InputDevice* device = mDevices.valueAt(deviceIndex);
device->process(rawEvents, count);[转换为InputDevice]


void InputDevice::process(const RawEvent* rawEvents, size_t count) {
    size_t numMappers = mMappers.size();
    for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
            for (size_t i = 0; i < numMappers; i++) {
                InputMapper* mapper = mMappers[i];
                mapper->process(rawEvent); [这里的mapper是分别处理某种类型的input event]
            }
    }
}


下面已PowerKey为例:
void KeyboardInputMapper::process(const RawEvent* rawEvent) {
    switch (rawEvent->type) {
    case EV_KEY: {
        int32_t scanCode = rawEvent->code; [所说的 scanCode 就是来着input event,rawEent的code]
        int32_t usageCode = mCurrentHidUsage;
        mCurrentHidUsage = 0;


        if (isKeyboardOrGamepadKey(scanCode)) {
            int32_t keyCode;
            uint32_t flags;
            if (getEventHub()->mapKey(getDeviceId(), scanCode, usageCode, &keyCode, &flags)) {
                keyCode = AKEYCODE_UNKNOWN;
                flags = 0;
            }
            processKey(rawEvent->when, rawEvent->value != 0, keyCode, scanCode, flags);
        }
        break;
    }



这里说的 getKeyCharacterMap and keyLayoutMap 分别是什么意思?
status_t EventHub::mapKey(int32_t deviceId, int32_t scanCode, int32_t usageCode,
        int32_t* outKeycode, uint32_t* outFlags) const {
    AutoMutex _l(mLock);
    Device* device = getDeviceLocked(deviceId);


    if (device) {
        // Check the key character map first.
        sp<KeyCharacterMap> kcm = device->getKeyCharacterMap();
        if (kcm != NULL) {
            if (!kcm->mapKey(scanCode, usageCode, outKeycode)) {
                *outFlags = 0;
                return NO_ERROR;
            }
        }


        // Check the key layout next.
        if (device->keyMap.haveKeyLayout()) {
            if (!device->keyMap.keyLayoutMap->mapKey(
                    scanCode, usageCode, outKeycode, outFlags)) {
                return NO_ERROR;
            }
        }
    }


    *outKeycode = 0;
    *outFlags = 0;
    return NAME_NOT_FOUND;
}


这里的 mapKey是那个函数实现的?最终有生成了个 keyCode?
void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
        int32_t scanCode, uint32_t policyFlags) {
    NotifyKeyArgs args(when, getDeviceId(), mSource, policyFlags,
            down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
            AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
    getListener()->notifyKey(&args);
}


/* Superclass of all input event argument objects */
struct NotifyArgs {
    virtual ~NotifyArgs() { }
    virtual void notify(const sp<InputListenerInterface>& listener) const = 0;
};


数据结构有转换为 NotifyArgs
/* Describes a key event. */
struct NotifyKeyArgs : public NotifyArgs {
    nsecs_t eventTime;
    int32_t deviceId;
    uint32_t source;
    uint32_t policyFlags;
    int32_t action;
    int32_t flags;
    int32_t keyCode;
    int32_t scanCode;
    int32_t metaState;
    nsecs_t downTime;
----
}


void InputDispatcher::notifyKey(const NotifyKeyArgs* args) {
    KeyEvent event;
    event.initialize(args->deviceId, args->source, args->action,
            flags, keyCode, args->scanCode, metaState, 0,
            args->downTime, args->eventTime);


    mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
}


KeyEvent是个class了


mPolicy->interceptKeyBeforeQueueing(&event, /*byref*/ policyFlags);
frameworks/base/services/core/java/com/android/server/input/InputManagerService.java


    GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
            "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I");


void NativeInputManager::interceptKeyBeforeQueueing(const KeyEvent* keyEvent,
        uint32_t& policyFlags) {
    // Policy:
    // - Ignore untrusted events and pass them along.
    // - Ask the window manager what to do with normal events and trusted injected events.
    // - For normal events wake and brighten the screen if currently off or dim.
    bool interactive = mInteractive.load();


    if ((policyFlags & POLICY_FLAG_TRUSTED)) {
        nsecs_t when = keyEvent->getEventTime();
        JNIEnv* env = jniEnv();
        jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
        jint wmActions;
        if (keyEventObj) {
            wmActions = env->CallIntMethod(mServiceObj,
                    gServiceClassInfo.interceptKeyBeforeQueueing,
                    keyEventObj, policyFlags);
            if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
                wmActions = 0;
            }
            android_view_KeyEvent_recycle(env, keyEventObj);
            env->DeleteLocalRef(keyEventObj);
        } 
        handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
    }
}




frameworks/native/include/input/InputDevice.h
/*
 * Describes the characteristics and capabilities of an input device.
 */
/*
 * Describes the characteristics and capabilities of an input device.
 */
class InputDeviceInfo {
public:
    InputDeviceInfo();
    InputDeviceInfo(const InputDeviceInfo& other);
}


/**********************************************************************************/
按键处理过程


frameworks/base/services/core/java/com/android/server/input/InputManagerService.java
    // Native callback.
    private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
    }


frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
    /* Provides an opportunity for the window manager policy to intercept early key
     * processing as soon as the key has been read from the device. */
    @Override
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
    }



frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
    /** {@inheritDoc} */
    @Override
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey, "android.policy:KEY");
  }
frameworks/base/services/core/java/com/android/server/power/PowerManagerService.java
        @Override // Binder call
        public void wakeUp(long eventTime, String reason, String opPackageName) {
            if (eventTime > SystemClock.uptimeMillis()) {
                throw new IllegalArgumentException("event time must not be in the future");
            }


            mContext.enforceCallingOrSelfPermission(
                    android.Manifest.permission.DEVICE_POWER, null);


            final int uid = Binder.getCallingUid();
            final long ident = Binder.clearCallingIdentity();
            try {
                wakeUpInternal(eventTime, reason, uid, opPackageName, uid);
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
        }
    private void wakeUpInternal(long eventTime, String reason, int uid, String opPackageName,
            int opUid) {
        synchronized (mLock) {
            if (wakeUpNoUpdateLocked(eventTime, reason, uid, opPackageName, opUid)) {
                updatePowerStateLocked();
            }
        }
    }


/**********************************************************************************/
输入设备的创建过程
/**********************************************************************************/
这和EventHub里的device有什么不同?
class EventHub : public EventHubInterface
{
    struct Device {
        Device* next;


        int fd; // may be -1 if device is virtual
        const int32_t id;
        const String8 path;
        const InputDeviceIdentifier identifier;
     }
}


KeyedVector<int32_t, Device*> mDevices;


创建EventHub对象时:mNeedToScanDevices(true)
EventHub::EventHub(void) :
        mBuiltInKeyboardId(NO_BUILT_IN_KEYBOARD), mNextDeviceId(1), mControllerNumbers(),
        mOpeningDevices(0), mClosingDevices(0),
        mNeedToSendFinishedDeviceScan(false),
        mNeedToReopenDevices(false), mNeedToScanDevices(true),
        mPendingEventCount(0), mPendingEventIndex(0), mPendingINotify(false) {
}




size_t EventHub::getEvents(int timeoutMillis, RawEvent* buffer, size_t bufferSize) {
        if (mNeedToScanDevices) {
            mNeedToScanDevices = false;
            scanDevicesLocked();
            mNeedToSendFinishedDeviceScan = true;
        }


}


遍历路径下每个文件的方法:参考文件:
frameworks/native/services/inputflinger/EventHub.cpp的函数:status_t EventHub::scanDirLocked(const char *dirname)


/**********************************************************************************/
2. 亮屏模式下:按下powerKey 出现关机界面的过程
/**********************************************************************************/
[    5196.839152] /dev/input/event0: EV_KEY       KEY_POWER            DOWN                
[    5196.839152] /dev/input/event0: EV_SYN       SYN_REPORT           00000000            
[    5198.226475] /dev/input/event0: EV_KEY       KEY_POWER            UP 


frameworks/base/services/core/java/com/android/server/GestureLauncherService.java
    public boolean interceptPowerKeyDown(KeyEvent event, boolean interactive) {
MetricsLogger.histogram(mContext, "power_double_tap_interval", (int) doubleTapInterval);
}


frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
    private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
        GestureLauncherService gestureService = LocalServices.getService(
                GestureLauncherService.class);
        boolean gesturedServiceIntercepted = false;
        if (gestureService != null) {
            gesturedServiceIntercepted = gestureService.interceptPowerKeyDown(event, interactive);
        }
     }


frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java
    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
        // Handle special keys.
        switch (keyCode) {
            case KeyEvent.KEYCODE_POWER: {
                result &= ~ACTION_PASS_TO_USER;
                isWakeKey = false; // wake-up will be handled separately
                if (down) {
                    interceptPowerKeyDown(event, interactive);
                } else {
                    interceptPowerKeyUp(event, interactive, canceled);
                }
                break;
            }
}

这篇关于input device 按键处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1027388

相关文章

百度OCR识别结构结构化处理视频

https://edu.csdn.net/course/detail/10506

如何在Java中处理JSON数据?

如何在Java中处理JSON数据? 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿!今天我们将探讨在Java中如何处理JSON数据。JSON(JavaScript Object Notation)作为一种轻量级的数据交换格式,在现代应用程序中被广泛使用。Java通过多种库和API提供了处理JSON的能力,我们将深入了解其用法和最佳

AI学习指南机器学习篇-朴素贝叶斯处理连续特征和离散特征

AI学习指南机器学习篇-朴素贝叶斯处理连续特征和离散特征 在机器学习领域,朴素贝叶斯是一种常用的分类算法,它的简单性和高效性使得它在实际应用中得到了广泛的应用。然而,在使用朴素贝叶斯算法进行分类时,我们通常会面临一个重要的问题,就是如何处理连续特征和离散特征。因为朴素贝叶斯算法基于特征的条件独立性假设,所以对于不同类型的特征,我们需要采取不同的处理方式。 在本篇博客中,我们将探讨如何有效地处理

神经网络第四篇:推理处理之手写数字识别

到目前为止,我们已经介绍完了神经网络的基本结构,现在用一个图像识别示例对前面的知识作整体的总结。本专题知识点如下: MNIST数据集图像数据转图像神经网络的推理处理批处理  MNIST数据集          mnist数据图像 MNIST数据集由0到9的数字图像构成。像素取值在0到255之间。每个图像数据都相应地标有“7”、“2”、“1”等数字标签。MNIST数据集中,

vue怎么处理跨域

Vue.js 本身并不直接解决跨域问题,因为跨域问题主要是浏览器基于同源策略(Same-origin policy)的一种安全限制。然而,在Vue.js项目中,我们可以采取一些策略来绕过或处理跨域问题。 解决跨域问题的常用方法: 代理服务器:在开发环境中,我们可以配置一个代理服务器来转发API请求,从而绕过浏览器的同源策略。Vue CLI 提供了内置的代理功能,可以在 vue.config.j

【机器学习】自然语言处理的新前沿:GPT-4与Beyond

📝个人主页:哈__ 期待您的关注  目录 🔥引言 背景介绍 文章目的 一、GPT-4简介 GPT-4概述 主要特性 局限性和挑战 二、自监督学习的新进展 自监督学习的原理 代表性模型和技术 三、少样本学习和零样本学习 少样本学习的挑战 先进方法 四、跨模态学习 跨模态学习的概念 代表性技术 应用场景 第五部分:可解释性和透明性 AI的可解释

【文末附gpt升级秘笈】腾讯元宝AI搜索解析能力升级:千万字超长文处理的新里程碑

腾讯元宝AI搜索解析能力升级:千万字超长文处理的新里程碑 一、引言 随着人工智能技术的飞速发展,自然语言处理(NLP)和机器学习(ML)在各行各业的应用日益广泛。其中,AI搜索解析能力作为信息检索和知识抽取的核心技术,受到了广泛的关注和研究。腾讯作为互联网行业的领军企业,其在AI领域的探索和创新一直走在前列。近日,腾讯旗下的AI大模型应用——腾讯元宝,迎来了1.1.7版本的升级,新版本在AI搜

AndroidStudio打包处理

AndroidStudio非常强大,公司最近有一个需求是要实现对一个APP进行多个版本的打包,而且可以同时安装在手机上。这个需求详细一点的描述是:公司有一个APP,有多个开发商要使用我们的APP,为了大家都想有一个自己的APP,而且图标不一样,app名字不一样,背景不一样等。我查询了一下资料发现,在AndroidStudio的gradle是可以配置的。在此特意写一篇文章记录分享。 配置签名 首

【教师资格证考试综合素质——法律专项】学生伤害事故处理办法以及未成人犯罪法笔记相关练习题

目录 《学生伤害事故处理办法》 第一章 总 则 第二章 事故与责任 (谁有错,谁担责) 第三章  事故处理程序 第四章 事故损害的赔偿 第五章 事故责任者的处理 第六章 附 则 《中华人民共和国预防未成人犯罪法》 第一章 总 则 第二章 预防犯罪的教育 第三章 对不良行为的干预 第四章 对严重不良行为的矫治 第五章 对重新犯罪的预防 第六章法律责任 第七章 附 则

Kubernetes排错(十)-处理容器数据磁盘被写满

容器数据磁盘被写满造成的危害: 不能创建 Pod (一直 ContainerCreating)不能删除 Pod (一直 Terminating)无法 exec 到容器 如何判断是否被写满? 容器数据目录大多会单独挂数据盘,路径一般是 /var/lib/docker,也可能是 /data/docker 或 /opt/docker,取决于节点被添加时的配置,可通过 docker info 确定: