Chrome 源碼閱讀:跟蹤一個鼠標事件的流程

我們通過在關鍵節點打斷點的方式,去分析一個鼠標事件的流程。

我們知道chromium是多進程模型,那么,我們可以推測:一個鼠標消息先從主進程產生,再通過跨進程通信發送給渲染進程,渲染進程再發送給WebFrame,最后被派發到目標Node上

于是,首先,我們在主進程,找到鼠標時間的最終消費點,打上斷點,進行分析:

主進程繼續往下走,就是把事件通過跨進程通信框架mojo發送過去的邏輯了:

接下來,我們要換個進程,在渲染進程打上斷點,看看消息過來后,怎么走的流程:

首先搜索這個mojom的事件,確認渲染進程斷點落腳處:

題外話:這個input_handler.mojom.cc到了渲染進程那就成了input_handler.mojom-blink.cc了。

這兩個文件99%相似,只有少量的不同(命名空間、基礎類型):

這兩個類的基類是一樣的:

這個類的頭文件寫明了,是由什么工具生成的:

很好奇生成源,我們也去看看:

// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.module blink.mojom;import "cc/mojom/browser_controls_state.mojom";
import "cc/mojom/overscroll_behavior.mojom";
import "cc/mojom/touch_action.mojom";
import "mojo/public/mojom/base/string16.mojom";
import "mojo/public/mojom/base/time.mojom";
import "third_party/blink/public/mojom/input/gesture_event.mojom";
import "third_party/blink/public/mojom/input/handwriting_gesture_result.mojom";
import "third_party/blink/public/mojom/input/input_event_result.mojom";
import "third_party/blink/public/mojom/input/input_event.mojom";
import "third_party/blink/public/mojom/input/pointer_lock_context.mojom";
import "third_party/blink/public/mojom/input/pointer_lock_result.mojom";
import "third_party/blink/public/mojom/input/ime_host.mojom";
import "third_party/blink/public/mojom/input/stylus_writing_gesture.mojom";
import "third_party/blink/public/mojom/input/touch_event.mojom";
import "third_party/blink/public/mojom/selection_menu/selection_menu_behavior.mojom";
import "ui/base/ime/mojom/ime_types.mojom";
import "ui/events/mojom/event_constants.mojom";
import "ui/events/mojom/event_latency_metadata.mojom";
import "ui/events/mojom/event.mojom";
import "ui/events/mojom/scroll_granularity.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
import "ui/gfx/range/mojom/range.mojom";
import "ui/latency/mojom/latency_info.mojom";[EnableIf=is_android]
import "third_party/blink/public/mojom/input/synchronous_compositor.mojom";// These structs are purposely duplicated from ui/events/mojom/event.mojom.
// They map WebInputEvent <-> WebInputEvent across mojo.
// We have to work at unifying them. The current problem is that the browser
// uses WebInputEvents inside the render widget host and input router. Once
// we move these to ui::Event's then we can get rid of these duplicated
// mojom structs. Ideally the browser would use ui::Event up until we
// pass the events into the renderer and just use a StructTraits to perform
// conversion from ui::mojom::Event --> blink::WebInputEvent.
struct KeyData {int32 dom_key;int32 dom_code;int32 windows_key_code;int32 native_key_code;bool is_system_key;bool is_browser_shortcut;mojo_base.mojom.String16 text;mojo_base.mojom.String16 unmodified_text;
};struct PointerData {int32 pointer_id;float force;double tilt_x;double tilt_y;float tangential_pressure;int32 twist;blink.mojom.Button button;ui.mojom.EventPointerType pointer_type;int32 movement_x;int32 movement_y;bool is_raw_movement_event;gfx.mojom.PointF widget_position;gfx.mojom.PointF screen_position;MouseData? mouse_data;int32 device_id;
};struct WheelData {float delta_x;float delta_y;float wheel_ticks_x;float wheel_ticks_y;float acceleration_ratio_x;float acceleration_ratio_y;uint8 phase;uint8 momentum_phase;blink.mojom.DispatchType cancelable;uint8 event_action;uint8 delta_units;
};struct MouseData {int32 click_count;WheelData? wheel_data;
};struct ScrollUpdate {float velocity_x;float velocity_y;
};struct ScrollData {float delta_x;float delta_y;ui.mojom.ScrollGranularity delta_units;bool target_viewport;blink.mojom.InertialPhaseState inertial_phase;bool synthetic;int32 pointer_count;// Used for GestureScrollBegin type only. If this is true, we use the scroll// sequence to do cursor control rather than scroll.bool cursor_control;ScrollUpdate? update_details;
};struct PinchBeginData {bool needs_wheel_event;
};struct PinchUpdateData {float scale;bool zoom_disabled;bool needs_wheel_event;
};struct PinchEndData {bool needs_wheel_event;
};struct FlingData {float velocity_x;float velocity_y;bool target_viewport;bool prevent_boosting;
};struct TapData {int32 tap_count;bool needs_wheel_event;
};struct TapDownData {int32 tap_down_count;
};struct GestureData {gfx.mojom.PointF screen_position;gfx.mojom.PointF widget_position;blink.mojom.GestureDevice source_device;bool is_source_touch_event_set_blocking;ui.mojom.EventPointerType primary_pointer_type;int32 primary_unique_touch_event_id;int32 unique_touch_event_id;gfx.mojom.Size? contact_size;ScrollData? scroll_data;PinchBeginData? pinch_begin_data;PinchUpdateData? pinch_update_data;PinchEndData? pinch_end_data;TapData? tap_data;TapDownData? tap_down_data;FlingData? fling_data;
};struct TouchPoint {blink.mojom.TouchState state;float radius_x;float radius_y;float rotation_angle;PointerData pointer_data;
};struct TouchData {blink.mojom.DispatchType cancelable;bool moved_beyond_slop_region;bool touch_start_or_first_move;bool hovering;uint32 unique_touch_event_id;array<TouchPoint> touches;
};struct Event {blink.mojom.EventType type;int32 modifiers;mojo_base.mojom.TimeTicks timestamp;ui.mojom.LatencyInfo latency;ui.mojom.EventLatencyMetadata event_latency_metadata;KeyData? key_data;PointerData? pointer_data;GestureData? gesture_data;TouchData? touch_data;
};// Represents the current state of overscroll.
struct DidOverscrollParams {gfx.mojom.Vector2dF accumulated_overscroll;gfx.mojom.Vector2dF latest_overscroll_delta;gfx.mojom.Vector2dF current_fling_velocity;gfx.mojom.PointF causal_event_viewport_point;cc.mojom.OverscrollBehavior overscroll_behavior;
};// A struct wrapper for the TouchAction enumeration because
// enumerations cannot be optional.
struct TouchActionOptional {cc.mojom.TouchAction touch_action;
};// Types related to sending edit commands to the renderer.
struct EditCommand {string name;string value;
};// A structure that indicates selection offsets if the selection could be
// established.
struct SelectAroundCaretResult {// The offset differences between the extended selection and the initial// selection (which is a caret).int32 extended_start_adjust;int32 extended_end_adjust;// The offset differences between the word selection (regardless of the// extended selection granularity) and the initial selection (which is a// caret).int32 word_start_adjust;int32 word_end_adjust;
};// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.blink_public.input
// GENERATED_JAVA_CLASS_NAME_OVERRIDE: SelectionGranularity
enum SelectionGranularity {kWord,kSentence,
};// An enumeration that describes the allowed non-directional pan action for the
// element under pointer being considered.
enum PanAction {// No pan action allowed.kNone,// Pan action is scroll.kScroll,// Pan action moves cursor when initial touch move is in horizontal direction,// or scrolls in the vertical direction.kMoveCursorOrScroll,// Pan action is stylus writable.kStylusWritable,
};// Interface exposed by the browser to the renderer.
interface WidgetInputHandlerHost {// When the renderer's main thread computes the touch action, send this to the// browser.SetTouchActionFromMain(cc.mojom.TouchAction touch_action);// Sets the pan action possible for the element under pointer which could be// one of the actions described under enum PanAction. Note that this is// different from TouchAction and does not contain directional pan info.SetPanAction(PanAction pan_action);// Sent by the compositor when input scroll events are dropped due to bounds// restrictions on the root scroll offset.DidOverscroll(DidOverscrollParams params);// Sent by the compositor when a GSB has started scrolling the viewport.DidStartScrollingViewport();// Required for cancelling an ongoing input method composition.ImeCancelComposition();// Sends the character bounds after every composition change// to always have correct bound info.ImeCompositionRangeChanged(gfx.mojom.Range range,array<gfx.mojom.Rect>? character_bounds,array<gfx.mojom.Rect>? line_bounds);// Updates the mouse capture state of this widget. While capture is enabled,// all mouse events, including those that don't hittest to this widget, will// be targeted to this widget. This enables Blink to behave correctly when// a scrollbar is being dragged, or text is being drag-highlighted, even// when the mouse passes across different RenderWidget areas.SetMouseCapture(bool capture);// Updates the browser whether this main frame widget has ongoing autoscroll// selection. Any further mouse up event should always be dispatched to the// main frame in addition to it's event target (OOP child frame) if the state// is active. This API should only ever be called on the InputHandler for a// main frame's RenderWidgetHost.SetAutoscrollSelectionActiveInMainFrame(bool autoscroll_selection);// Requests locking the target of mouse events to a single element and// removing the cursor from view.  Mostly used by the Pointer Lock API.// See https://www.w3.org/TR/pointerlock/ for more info. This call is// also used by Pepper Flash.// |from_user_gesture| indicates whether this request came from a user// gesture or not.// |unadjusted_movement| indicates whether the request asked for raw mouse// movement data or just what the operating system returns (often accelerated// mouse movement).// |result| kSuccess if the mouse has been locked or the appropriate error// reason if not.// |context| is one end of a mojo pipe that will stay connected as long as// the mouse is locked. Is a NullRemote if |result| is not kSuccess.RequestMouseLock(bool from_user_gesture,bool unadjusted_movement)=> (PointerLockResult result,pending_remote<blink.mojom.PointerLockContext>? context);
};// This interface provides the input actions associated with the FrameWidget.
// Other input actions may also be dispatched via the WidgetInputHandler
// interface. If frame input actions are dispatched the WidgetInputHandler
// should be fetched via the associated interface request so that input calls
// remain in order. See https://goo.gl/x4ee8A for more details.
interface FrameWidgetInputHandler {// Adds text decorations between a given valid start and end offsets in the// currently focused editable field.AddImeTextSpansToExistingText(uint32 start, uint32 end, array<ui.mojom.ImeTextSpan> ime_text_spans);// Clears text decorations type between a given valid start and end offsets// in the currently focused editable field.ClearImeTextSpansByType(uint32 start, uint32 end, ui.mojom.ImeTextSpanType type);// Sets the text composition to be between the given start and end offsets in// the currently focused editable field.SetCompositionFromExistingText(int32 start, int32 end, array<ui.mojom.ImeTextSpan> ime_text_spans);// Deletes the current selection plus the specified number of characters// before and after the selection or caret.ExtendSelectionAndDelete(int32 before, int32 after);// Deletes the current selection plus the specified number of characters// before and after the selection or caret.ExtendSelectionAndReplace(uint32 before,uint32 after,mojo_base.mojom.String16 replacement_text);// Deletes text before and after the current cursor position, excluding the// selection. The lengths are supplied in Java chars (UTF-16 Code Unit),// not in code points or in glyphs.DeleteSurroundingText(int32 before, int32 after);// Deletes text before and after the current cursor position, excluding the// selection. The lengths are supplied in code points, not in Java chars// (UTF-16 Code Unit) or in glyphs. Does nothing if there are one or more// invalid surrogate pairs in the requested rangeDeleteSurroundingTextInCodePoints(int32 before, int32 after);// Selects between the given start and end offsets in the currently focused// editable field.SetEditableSelectionOffsets(int32 start, int32 end);// Stylus Writing - perform Gesture action in input using gesture data.HandleStylusWritingGestureAction(blink.mojom.StylusWritingGestureData gesture_data)=> (HandwritingGestureResult result);// Message payload is the name/value of a WebCore edit command to execute.ExecuteEditCommand(string command, mojo_base.mojom.String16? value);// These messages are typically generated from context menus and request the// renderer to apply the specified operation to the current selection.Undo();Redo();Cut();Copy();CopyToFindPboard();CenterSelection();Paste();PasteAndMatchStyle();Delete();SelectAll();CollapseSelection();// Pushed from the browser to the renderer each time the IME is activated,// e.g. an editable element becomes focused.[EnableIf=is_android]PassImeRenderWidgetHost(pending_remote<ImeRenderWidgetHost> remote);// Replaces the selected region or a word around the cursor with the// specified string.Replace(mojo_base.mojom.String16 word);// Replaces the misspelling in the selected region with the specified string.ReplaceMisspelling(mojo_base.mojom.String16 word);// Requests the renderer to select the region between two points.// Expects a SelectRange_ACK message when finished.SelectRange(gfx.mojom.Point base, gfx.mojom.Point extent);// Sent by the browser to ask the renderer to adjust the selection start and// end points by the given amounts. A negative amount moves the selection// towards the beginning of the document, a positive amount moves the// selection towards the end of the document. Will send show selection menu// event when needed.AdjustSelectionByCharacterOffset(int32 start, int32 end, SelectionMenuBehavior behavior);// Requests the renderer to select the specified granularity around caret and// to potentially show the selection handles and / or context menu after// selection.// Expects ack with new selection information when finished, or null if the// selection failed.SelectAroundCaret(SelectionGranularity granularity, bool should_show_handle,bool should_show_context_menu)=> (SelectAroundCaretResult? result);// Requests the renderer to move the selection extent point to a new position.// Expects a MoveRangeSelectionExtent_ACK message when finished.MoveRangeSelectionExtent(gfx.mojom.Point extent);// Tells the renderer to scroll the currently focused node into view only if// the currently focused node is a Text node (textfield, text area or content// editable divs).ScrollFocusedEditableNodeIntoView();// Replies when the next PageScaleAnimation has completed. Can only be called// on the outermost main frame. Can be used to reliably wait for a// ScrollFocusedEditableNodeIntoView to complete since that may create a// PageScaleAnimation which can take several frames to complete.// ScrollFocusedEditableNodeIntoView cannot use a reply callback for this// since it may be called on a subframe but the scroll will be completed in// another renderer when it bubbles up to the root. Additionally, the caller// may not be the one to have called ScrollFocusedEditableNodeIntoView; for// example, a test that simulates tapping an input box.WaitForPageScaleAnimationForTesting() => ();// Requests the renderer to move the caret selection toward the point.MoveCaret(gfx.mojom.Point point);
};// An enumeration describing the active and focus states. If a widget is
// focused then it must also be active, therefore there is no focused and
// not active value in this enumeration. All widgets in a tab will have
// the same active state. Active state is tab specific, and focus state is
// frame specific. See
// https://www.chromium.org/developers/design-documents/aura/focus-and-activation/
enum FocusState
{kFocused,kNotFocusedAndActive,kNotFocusedAndNotActive
};// Interface exposed by the renderer to the browser. This class represents
// an input interface for an associated Widget object. See FrameWidgetInputHandler
// for an interface at the frame level.
interface WidgetInputHandler {// Tells widget focus has been changed.SetFocus(FocusState state);// Tells widget mouse capture has been lost.MouseCaptureLost();// This message notifies the renderer that the next key event is bound to one// or more pre-defined edit commands. If the next key event is not handled// by blink, the specified edit commands shall be executed against current// focused frame.// Parameters// * edit_commands//   See t_p/b/renderer/core/editing/commands/editing_command_type.h//   Contains one or more edit commands.// See t_p/b/renderer/core/editing/commands/editor_command.cc for// detailed definition of webkit edit commands.//// This message must be sent just before sending a key event.SetEditCommandsForNextKeyEvent(array<EditCommand> commands);// Sends the cursor visibility state to the render widget.CursorVisibilityChanged(bool visible);// This message sends a string being composed with an input method.// Note, the response is specifically for Devtools to learn about completionImeSetComposition(mojo_base.mojom.String16 text,array<ui.mojom.ImeTextSpan> ime_text_spans,gfx.mojom.Range range, int32 start, int32 end) => ();// This message deletes the current composition, inserts specified text, and// moves the cursor.// Note, the response is specifically for Devtools to learn about completionImeCommitText(mojo_base.mojom.String16 text,array<ui.mojom.ImeTextSpan> ime_text_spans,gfx.mojom.Range range, int32 relative_cursor_position) => ();// This message inserts the ongoing composition.ImeFinishComposingText(bool keep_selection);// Request from browser to update text input state.RequestTextInputStateUpdate();// Request from browser to update the cursor and composition information which// will be sent through ImeCompositionRangeChanged. Setting// |immediate_request| to true  will lead to an immediate update. If// |monitor_updates| is set to true then changes to text selection or regular// updates in each compositor frame (when there is a change in composition// info) will lead to updates being sent to the browser.RequestCompositionUpdates(bool immediate_request, bool monitor_request);// Sends an input event to the render widget. The browser should use this// API if it wants to know about the result of the rendering handling// the event. The callback may be delayed based on the event running on// the main thread so DispatchNonBlockingEvent is always preferred if// you don't require notification.DispatchEvent(Event event)=> (blink.mojom.InputEventResultSource source,ui.mojom.LatencyInfo updated_latency,blink.mojom.InputEventResultState state,DidOverscrollParams? overscroll,TouchActionOptional? touch_action);// Sends a non-blocking input event to the render widget. The behaviour// of this API is the same as DispatchEvent just that there is no callback// after the event is processed.DispatchNonBlockingEvent(Event event);// Forces input to be flushed and resolves the callback only once the input// has been fully processed, meaning its effects are visible to the full// system. In practice, this will force a redraw and wait until the new// CompositorFrame (containing all changes caused by prior input) has been// displayed.WaitForInputProcessed() => ();// Attach the synchronous compositor interface. This method only// should be called for Android WebView.[EnableIf=is_android]AttachSynchronousCompositor(pending_remote<SynchronousCompositorControlHost> control_host,pending_associated_remote<SynchronousCompositorHost> host,pending_associated_receiver<SynchronousCompositor> compositor_request);// Return an associated FrameWidgetInputHandler interface so that input// messages to the frame associated with this widget can be sent// serially.GetFrameWidgetInputHandler(pending_associated_receiver<FrameWidgetInputHandler> interface_request);// Notifies the renderer whether hiding/showing the browser controls is// enabled, what the current state should be, and whether or not to// animate to the proper state.UpdateBrowserControlsState(cc.mojom.BrowserControlsState constraints,cc.mojom.BrowserControlsState current,bool animate);
};

可見,這個生成的不止一個事件,包含了大部分用戶事件了。去看看所在目錄,也初步熟悉blink的目錄結構了:

后面我們再詳細介紹這套mojo跨進程通信框架的細節。

言歸正傳,我們attach到render進程,繼續打斷點跟蹤鼠標事件。

想在渲染進程找到WidgetInputHandler類對應的消息,只需要在后面加個Impl即可,我們通過符號跳轉,找到WidgetInputHandlerImpl類:

接下來,中間彎彎繞繞太多,我們直接在node打個斷點,看看鼠標事件如何傳遞到node具體的處理邏輯中的:

事件首先被捕獲并封裝為一個MouseEventPointerEvent對象。然后通過EventDispatcher類和相關方法,事件被分發到目標Node。對應的HTML元素(通過HTMLElement和特化的TextControlInnerEditorElement)會處理這個事件,然后這個時間觸發默認基類的處理器。

WebFrameWidget:繼承自WebWidget,但是大部分函數依然是虛函數,用于專門負責處理一個WebFrame(即一個網頁框架)的渲染和事件。如果要想顯示一個網頁,那么需要繼承自WebFrameWidget并實現相關純虛函數。

WebFrameWidgetImpl:是WebFrameWidget在blink里的一個具體實現類。它實現了接口中定義的所有方法,并提供了框架的具體行為。WebFrameWidgetImpl負責實際的繪圖邏輯、輸入事件處理、視圖的更新和大小調整等。這個實現將抽象的行為具體化,它通過調用Blink渲染引擎的其他組件,如布局引擎、繪圖系統等,來完成對Web內容的渲染和事件處理。WebFrameWidgetImpl是Web內容在Blink中被渲染的核心地方,它直接與底層的渲染流水線交互。

講到這里,也要引出一個重量級的基類:Node:

Node 類是一個非常重要的基類,它表示文檔中的一個節點。Node 類扮演了核心角色,以下是對 Node 類及其作用的更詳細介紹:

  1. 層次結構:
    Node 類位于 DOM(文檔對象模型)層次結構中的基礎位置。在 DOM 中,所有的元素、文本內容和屬性都被視為節點。因此,Node 類提供了一系列的基礎方法和屬性,用于管理節點之間的關系(例如父子關系和兄弟關系)、節點的遍歷以及節點的基本操作(比如插入、替換、刪除)。

  2. 事件模型:
    Node 類還是事件模型的一部分。在 Blink 中,事件通常會在節點之間傳播,遵循捕獲階段、目標階段和冒泡階段。Node 類提供了事件處理的相關方法,比如綁定事件監聽器、分發事件等。當事件發生時,比如用戶的點擊或鍵盤操作,它會被分發到正確的 Node 對象,并且通過事件監聽器進行相應的處理。

  3. 渲染:
    雖然 Node 類本身并不直接處理渲染,但它的派生類,如 Element 和特化后的 HTMLElement,會存儲與渲染相關的屬性(例如樣式信息)。這些類將 Node 的基礎功能擴展到了渲染管線中,這樣渲染引擎就可以使用這些信息來呈現視覺元素。

  4. 類型多樣性:
    DOM 中有不同類型的節點,包括但不限于元素節點(Element)、文本節點(Text)、注釋節點(Comment)和文檔節點(Document)。Node 類是這些具體節點類型的基類,通過繼承和多態,不同類型的節點可以擁有特化的行為,并且仍然能夠通過 Node 類的接口進行通用處理。

  5. API 和腳本接口:
    Node 類還提供了一系列的 API,供 JavaScript 腳本訪問和操縱節點。開發者可以通過這些 API 查詢節點信息、修改節點結構、動態添加或移除節點等。這為開發者提供了強大的能力來改變頁面內容和行為。

總的來說,Node 類是 Blink 和 Web 開發者用來操作和理解 Web 頁面結構的基礎,它為構建、遍歷和交互提供了基本的框架。通過 Node 及其派生類,Blink 渲染引擎能夠將結構化的 HTML 文檔轉化為用戶可以看到和交互的網頁。

未完待續 ....

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/23993.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/23993.shtml
英文地址,請注明出處:http://en.pswp.cn/web/23993.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【FAS】《CN103106397B》

原文 CN103106397B-基于亮瞳效應的人臉活體檢測方法-授權-2013.01.19 華南理工大學 方法 / 點評 核心方法用的是傳統的形態學和模板匹配&#xff0c;亮點是雙紅外發射器做差分 差分&#xff1a;所述FPGA芯片控制兩組紅外光源&#xff08;一近一遠&#xff09;交替亮滅&…

[力扣題解] 700. 二叉搜索樹中的搜索

題目&#xff1a;700. 二叉搜索樹中的搜索 思路 觀察法 二叉搜索樹的搜索操作&#xff0c;比較根節點的數值&#xff0c; 如果等于&#xff1a;找到了&#xff1b;大于根節點&#xff1a;在右子樹&#xff0c;往右走&#xff1b;小于根節點&#xff1a;在左子樹&#xff0c;…

【Java基礎】線程方法

start()&#xff1a;啟動線程&#xff0c;使線程進入就緒狀態。 run()&#xff1a;線程執行的代碼邏輯&#xff0c;需要重寫該方法。 停止線程 void interrupt() 中斷線程&#xff0c;讓它重新去爭搶cpu 如果目標線程長時間等待&#xff0c;則應該使用interrupt方法來中斷等待…

RDMA (2)

iWARP(RDMA)怎么工作的 招式1:bypass內核 非iWARP時,當應用向網絡適配器發出讀或者寫命令時,命令穿過用戶空間以及內核空間,因此需要在用戶空間和內核空間間進行切換。 iWARP使用RDMA,讓應用直接將命令送達到網絡適配器。這規避了對內核的調用,減少了開銷和延遲。 招式2…

【Kubernetes】三證集齊 Kubernetes實現資源超賣(附鏡像包)

目錄 插敘前言一、思考和原理二、實現步驟0. 資料包1. TLS證書簽發2. 使用 certmanager 生成簽發證書3. 獲取secret的內容 并替換CA_BUNDLE4.部署svc deploy 三、測試驗證1. 觀察pod情況2. 給node 打上不需要超售的標簽【可以讓master節點資源不超賣】3. 資源實現超賣4. 刪除還…

[補題記錄]Leetcode 209.長度最小的子數組

傳送門&#xff1a;長度最小的子數組 Problem/題意 給定一個整數數組和一個整數 target&#xff0c;要求算出數組中最小長度的連續子數組&#xff0c;數組元素的和大于等于 target。 Thought/思路 題目要求維護最小的長度&#xff0c;因此我們希望&#xff1a;當條件不滿足…

IP域名關系的研究與系統設計(學習某知名測繪系統)

IP域名關系庫管理包括域名庫檢索和whois庫檢索&#xff0c;詳情如下。 域名庫檢索支持以下5項功能&#xff1a; 1.通過過濾器檢索 篩選條件包含IP地址、口令、工具名稱、可利用的漏洞編號、創建時間&#xff1b; 2.通過關鍵字檢索 在查詢框中輸入域名庫名稱的部分關鍵詞&a…

計算機組成結構—IO系統概述

目錄 一、I/O 系統的發展 1. 早期階段 2. 接口模塊和 DMA 階段 3. 通道結構階段 4. 處理機階段 二、I/O 系統的組成 1. I/O 軟件 2. I/O 硬件 三、I/O 設備 1. I/O 設備分類 2. I/O 設備的組成 在計算機中&#xff0c;除 CPU 和主存兩大模塊之外&#xff0c;第三個重…

Apple開發者應用商店(AppStore)描述文件及ADHOC描述文件生成

創建AD HOC描述文件 1.選中Profiles,然后點擊加號創建 2.創建已注冊設備可安裝描述文件 3.選擇要注冊的id 4.選擇證書 5.選擇設備 6.輸入文件名,點擊生成 7.生成成功,點擊下載

TCP為什么握手是三次,而揮手是四次

TCP&#xff08;傳輸控制協議&#xff09;使用三次握手&#xff08;3WHS&#xff09;來建立一個可靠的連接&#xff0c;并使用四次揮手&#xff08;4WHS&#xff09;來終止連接。以下是每個步驟的詳細解釋&#xff1a; 三次握手&#xff08;3WHS&#xff09;建立連接&#xff…

solidity的modifier修飾符

solidity的modifier修飾符 什么是modifier修飾符 修飾器&#xff08;modifier&#xff09;是solidity特有的語法&#xff0c;類似于面向對象編程中的decorator&#xff0c;聲明函數擁有的特性&#xff0c;并減少代碼冗余。 Solidity 中關鍵字 modifier 用于聲明一個函數修改…

electron調用dll時應用程序閃退

electron調用dll時&#xff0c;直接閃退&#xff0c;且用如下方式監聽無任何輸出&#xff1a; window-all-closed 或 will-quit 此時需要檢查傳給dll的參數及參數類型是否正確&#xff0c;特別是使用ffi-napi時調用dll&#xff0c;使用 ref-napi定義類型&#xff0c;經常容易…

go 源碼學習1:scanner學習

scanner所在包是scanner.go type scanner struct {// 步驟是一個函數&#xff0c;用于執行下一個轉換。// 也嘗試使用整數常量和單個函數以及帶有開關的函數&#xff0c;// 但是直接使用函數在64位Mac Mini上快了10%&#xff0c;// 而且閱讀起來更直觀。step func(*scanner, …

域名區分英文大小寫嗎?

在互聯網的早期&#xff0c;域名系統(DNS)的設計并沒有考慮大小寫敏感性。然而&#xff0c;隨著技術的發展和用戶需求的多樣化&#xff0c;域名的大小寫問題逐漸引起了人們的關注。本文將探討域名是否區分英文大小寫&#xff0c;以及這一特性對網站運營和用戶體驗的影響。 一、…

【Android】Git Patch生成的文件怎么合并到項目里面和遇到的一些問題

前言 Git patch是一種描述文件&#xff0c;它記錄了一系列的文件變更&#xff08;如新增、修改、刪除&#xff09;以及變更的具體內容。通過使用patch文件&#xff0c;可以將這些變更應用到其他代碼庫中&#xff0c;從而實現代碼的同步和更新。 Git 提供了兩種補丁方案&#…

Java使用OpenCV計算兩張圖片相似度

業務&#xff1a;找出兩個表的重復的圖片。 圖片在表里存的是二進制值&#xff0c;存在大量由于一些特殊情況例如掃描有差異&#xff0c;導致圖片存的二進制值不同&#xff0c;但圖片其實是一樣來的。 所以找出兩個表重復相同的圖片&#xff0c;不可能只是單純的比較二進制值…

flask招聘數據分析及展示平臺-計算機畢業設計源碼39292

目 錄 摘要 1 緒論 1.1研究意義 1.2國內外研究進展 1.3flask框架介紹 2 1.4論文結構與章節安排 3 2 招聘數據分析及展示平臺分析 4 2.1 可行性分析 4 2.2 系統流程分析 4 2.2.1數據增加流程 5 2.3.2數據修改流程 5 2.3.3數據刪除流程 5 2.3 系統功能分析 5 2.3.1 功能性分…

亞馬遜新品如何快速吸引流量?自養號測評助賣家一臂之力

在亞馬遜平臺上每天都會有大量的新品推出&#xff0c;而這些新品中有部分可能并沒有什么流量和訂單&#xff0c;有些可能上架后立馬就能獲得流量了&#xff0c;那么亞馬遜上新品一般幾天出單&#xff1f; 一、亞馬遜上新品一般幾天出單&#xff1f; 亞馬遜上新品出單的時間因…

DispatcherTimer應用

DispatcherTimer 是 WPF 中用于執行定時任務的類&#xff0c;用于在指定的時間間隔內執行任務。它與 UI 線程的 Dispatcher 相關聯&#xff0c;因此可以用來更新 UI 元素&#xff0c;而不必擔心線程安全問題。 關鍵特性&#xff1a; 線程安全&#xff1a;DispatcherTimer 確保…

人工智能時代,想轉型AI產品經理?這篇文章你不應該錯過

前言 在這個日新月異的智能時代&#xff0c;人工智能&#xff08;AI&#xff09;已經從未來概念轉變為推動各行各業發展的核心驅動力。作為連接技術與市場的橋梁&#xff0c;AI產品經理的角色愈發關鍵&#xff0c;他們不僅是技術的翻譯者&#xff0c;更是創新的推動者。如果你…