Method for realizing one-way dependence of each component of modularized operating system
By dispersing the structure definition and operations of resources into two layers in the operating system, one-way dependence between components is achieved, and the complexity and non-reusability problems caused by interdependence between modules in existing operating systems are solved, and the stability and scalability of the system are improved.
Patent Information
- Application Number
- CN202411752263.8
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2024-12-02
- Publication Date
- 2025-03-25
AI Technical Summary
The existing operating systems are difficult to maintain and develop due to the extensive interdependence between modules, and the software is complex and unreusable, and there are circular dependencies between components, which increases the risk of error propagation.
By dispersing the structure definition and operation of resources into two layers, the lower-level components are responsible for the basic structure definition and state management of resources, and the upper-level components are responsible for various operations on resources, realizing one-way dependence between components and avoiding circular dependence.
It improves the stability and security of componentized systems, enhances the independence and loose coupling of each component, simplifies code understanding and debugging, reduces potential circular dependency problems, and improves the flexibility and scalability of the system.
Smart Images

Figure CN119690617A_ABST
Abstract
Description
Technical Field
[0001] The present invention relates to the technical field of operating systems, and in particular to a method for realizing unidirectional dependency of components of a componentized operating system. Background Art
[0002] Operating system development has always been a complicated matter. The current popular operating systems (such as Linux) have become increasingly large and bloated over time, making them difficult to maintain and develop. The pain point of developing an operating system is that it is tedious for developers to write operating system software, and there are too many details to pay attention to. The root cause is the software complexity caused by the extensive interdependence of operating system internal modules, and the non-reusability of software caused by the self-contained nature of the operating system.
[0003] We believe that the future operating system will not be as large and universal as the current Linux and Windows, but a variety of componentized customized operating systems that can be quickly combined and have rich functions. They can quickly adapt to the various processors, accelerators, peripherals and application requirements in the future, and are superior to existing general-purpose operating systems in terms of development convenience, performance and security. However, in the development of such a componentized operating system, if a large number of bidirectional pointers are used between internal modules in pursuit of performance and development convenience, this makes it difficult to understand, modify and maintain each module in the system, and also increases the risk of errors propagating between modules.
[0004] Specifically, when developing based on the Rust language, it is common to reference existing crates to introduce the functions of other components. The basic method is to establish a dependency on an external crate in Cargo.toml, and then call its code like referencing an internal module. However, this method has limitations. If there is mutual dependency between two crates, or there is a circular dependency between multiple crates, this problem is called a circular dependency. Summary of the invention
[0005] In view of the shortcomings of the prior art, the present invention provides a method for realizing one-way dependency between components of a componentized operating system. A component is a pre-built, reusable, independent entity that encapsulates specific functions. The core content is the one-way dependency between components, which can improve the stability and security of the componentized system operation.
[0006] The present invention needs to realize the one-way dependency between the components of the componentized operating system written in Rust language, and disperse the structural definition and operation of resources into two layers. The lower-layer components contain the structural definition and maintenance status, and the upper-layer components contain various operations, so that the operations are separated from the structure, and the independence and loose coupling between the components are ensured, thereby avoiding the problems of increased complexity, difficult testing, poor scalability, etc. caused by circular dependencies.
[0007] The technical solution of the present invention is:
[0008] A method for implementing unidirectional dependency of components of a componentized operating system, comprising:
[0009] The structure definition and operation of resources are distributed into two layers. The lower layer components are used for the basic structure definition and status management of resources, and the upper layer components are used to perform various operations on resources, so that the operation is separated from the structure.
[0010] Starting from the upper-layer components, search and locate the target resources layer by layer from top to bottom, and operate the target resources. The top-down relationship is called the positive direction. Dependencies are established by default. The upper-layer components rely on the lower-layer components to complete construction, startup, and operation.
[0011] Preferably, according to the present invention, the lower layer components are used for basic structure definition of resources and state management of basic structure of resources; including:
[0012] Resource structure definition: define the data structure of various resources and clarify their attributes;
[0013] State management: used to maintain the current state information of various resources, including: creation, destruction, activation, suspension state transition, and implementation of state storage and update mechanism;
[0014] Event notification: When the resource status changes, a notification is sent to the upper-level component to perform corresponding operations;
[0015] Resource registration and deregistration: Provides interfaces for registering and deregistering resources to dynamically manage the lifecycles of various resources.
[0016] Preferably, according to the present invention, the upper layer component is used to perform various operations on resources; including:
[0017] Resource creation and destruction: Provides interfaces to create and destroy resources;
[0018] Resource operation: Provides specific operation interfaces, including process scheduling, memory allocation, and device reading and writing. Each operation is performed by calling the structure defined by the lower-level components.
[0019] Status query and change: Provide an interface to query the current status of resources and provide an interface to change the status of resources;
[0020] Event processing: respond to event notifications from lower-level components and perform corresponding operations.
[0021] Preferably according to the present invention, in the lower-level components, the resource data structures in each lower-level component establish dependencies according to data inclusion or reference relationships;
[0022] In the upper-level components, the operation process methods within each upper-level component establish dependencies based on the process scheduling relationship.
[0023] Preferably, according to the present invention, one-way dependency between components is realized by registering callbacks, including: calling a macro with a mutex lock;
[0024] Registering a callback is passing a function to another function so that it will be called when a certain event or condition occurs; specifically:
[0025] 1) Define the callback function;
[0026] 2) Define a structure or function that accepts a callback;
[0027] 3) Register callback: In the main program or elsewhere, create an EventHandler instance and register the callback function:
[0028] 4) Trigger event: When a specific condition occurs, the callback function is triggered by calling the event handling method; the callback is called and data is passed.
[0029] Preferably, according to the present invention, one-way dependency between components is achieved by introducing an intermediate layer; including:
[0030] By referencing mutex_ops::MutexTrait, the lock / force_unlock method is promoted to the upper-level component mutex_ops for implementation;
[0031] Add a high-level component tid_map to cooperate with the upper-level component mutex_ops. The high-level component tid_map acts as an intermediary to manage the relationship between the task ID and the specific task, ensuring that WaitQueue only cares about the TaskID and WaitQueue is only responsible for the TaskID of the push / pop task.
[0032] The reverse dependency of the operation process is completed by segmenting Mutex by structure and operation through the middle layer tid_map. The specific implementation is: implement the lock / force_unlock method in the mutex_ops component:
[0033] The lock method is to call Mutex.lock in mutex_ops, and directly use Mutex.lock to obtain the lock logic; for the waiting task, it is managed through tid_map, the TaskID of the current task is obtained and added to the waiting queue;
[0034] The force_unlock method is to call Mutex.force_unlock directly, use tid_map to find the task to be awakened when unlocking, remove the task from the waiting queue and add it to the running queue.
[0035] A computer device comprises a memory and a processor, wherein the memory stores a computer program, and when the processor executes the computer program, it implements the steps of a method for realizing unidirectional dependency of various components of a componentized operating system.
[0036] A computer-readable storage medium stores a computer program, which, when executed by a processor, implements the steps of a method for realizing unidirectional dependency of various components of a componentized operating system.
[0037] The beneficial effects of the present invention are:
[0038] The present invention realizes the one-way dependency relationship between components of the componentized operating system, has a loose coupling, enables each component to be developed, tested and maintained more independently, and improves the flexibility and scalability of the system. Through a top-down hierarchical structure, the implementation direction of the operating system is locked into a one-way direction. In addition, the one-way dependency also helps to reduce potential circular dependency problems and simplifies the understanding and debugging process of the code. Therefore, realizing the one-way dependency between components helps to build a clear, robust and easily expandable operating system. BRIEF DESCRIPTION OF THE DRAWINGS
[0039] Figure 1 A schematic diagram of the hierarchical problem of the mutex lock of the present invention;
[0040] Figure 2 This is a schematic diagram of implementing one-way dependency between components by registering callbacks;
[0041] Figure 3 This is a schematic diagram of implementing one-way dependency between components by introducing an intermediate layer;
[0042] Figure 4 A diagram of the problem between drivers and devices involving mutex locks; DETAILED DESCRIPTION
[0043] The present invention will be further defined below in conjunction with the accompanying drawings and embodiments, but is not limited thereto.
[0044] Example 1
[0045] A method for implementing unidirectional dependency of components of a componentized operating system, comprising:
[0046] The structure definition and operation of resources are distributed into two layers. The lower layer components are used for the basic structure definition and status management of resources, and the upper layer components are used to perform various operations on resources, so that the operation is separated from the structure.
[0047] Considering the primary and secondary directions of the relationship between resources, it is assumed that managers / users are the upper layer and subordinates / users are the lower layer. Starting from the upper layer components, search and locate the target resources layer by layer from top to bottom, and operate the target resources. Therefore, the components of the componentized operating system kernel also have upper and lower layers. The top-down relationship is called the positive direction. Dependency is established by default. The upper layer components rely on the lower layer components to complete the construction, startup and operation.
[0048] Example 2
[0049] The method for implementing unidirectional dependency of components of a componentized operating system according to Embodiment 1 is different in that:
[0050] The lower-level components are used to define the basic structure of resources and manage the status of the basic structure of resources; they include:
[0051] Resource structure definition: Define the data structure of various resources and clarify their attributes; for example, the process structure contains fields for process ID, state (ready, running, blocked), priority, and program counter.
[0052] State management: used to maintain the current state information of various resources, including: creation, destruction, activation, suspension state transition, implementation of state storage and update mechanism; ensure accurate reflection of resource status.
[0053] Event notification: When the resource status changes, a notification is sent to the upper-level component to perform corresponding operations;
[0054] Resource registration and deregistration: Provides interfaces for registering and deregistering resources to dynamically manage the lifecycles of various resources.
[0055] The upper-level components are used to perform various operations on resources, including:
[0056] Resource creation and destruction: Provides interfaces to create and destroy resources; such as creating processes, allocating memory, and opening devices.
[0057] Resource operation: Provides specific operation interfaces, including process scheduling, memory allocation, and device reading and writing. Each operation is performed by calling the structure defined by the lower-level components.
[0058] Status query and change: Provides an interface to query the current status of resources, for example, querying process status and memory usage. Provides an interface to change resource status; for example, changing a process from ready to running.
[0059] Event processing: respond to event notifications from lower-level components and perform corresponding operations, such as handling device interrupts and scheduling new processes.
[0060] The present invention distributes the structure definition and operation of resources into two layers. The lower layer components include the structure definition maintenance status, and the upper layer components include various operations. The two layers solve different problems respectively.
[0061] In the lower-level components, the resource data structures in each lower-level component establish dependencies based on data inclusion or reference relationships;
[0062] In the lower-level components, each resource data structure can establish dependencies through inclusion or reference relationships to better manage and organize resources. This dependency relationship helps to clarify the association between resources and supports efficient resource access and management.
[0063] For example, processes and address spaces
[0064] Process structure:
[0065] pub struct Process{
[0066] pid:u64,
[0067] pub parent:AtomicU64,
[0068] pub stack_size:AtomicU64,
[0069] pub children:Mutex <Vec<Arc <process>>>,
[0070] pub tasks:Mutex<Vec <axtaskref>>,
[0071]
[0072] Address Space:
[0073]
[0074] In the upper-level components, the operation process methods within each upper-level component establish dependencies based on the process scheduling relationship.
[0075] In the upper-level components, the dependencies between various operation process methods are usually based on process scheduling relationships, which can achieve more efficient resource scheduling and operation execution.
[0076] Resource Allocation
[0077]
[0078] }else{
[0079] println! ("Memory not allocated for process{}.",self.pid);
[0080] }
[0081] }else{
[0082] println! ("No memory allocated for process{}.",self.pid);
[0083] }
[0084] }
[0085] In this example, the schedule_process method depends on the result of allocate_memory. The process can only be scheduled for execution when the memory is successfully allocated and the status is updated. This scheduling relationship forms an orderly execution flow between operations, thereby effectively managing system resources.
[0086] Mutex level issues such as Figure 1 As shown in the figure, there is a natural circular relationship between the mutex and the protected resources and waiters. Take Task accessing File as an example. Task is the waiting visitor of the resource. File represents a certain I / O resource, which may have a long access delay, so it needs to be protected by Mutex. This is a top-down dependency. At the same time, the Mutex mechanism requires a waiter queue to temporarily store those Tasks in the waiting state, which requires a structural reverse reference; it also requires a wake-up operation, which also requires a bottom-up process reference.
[0087] Based on the idea of unidirectional dependency, in order to avoid using direct pointers or references and cut off the relationship loop from the starting point of the reverse relationship, the present invention proposes two solutions:
[0088] One-way dependencies between components are achieved by registering callbacks, such as Figure 2 As shown, it includes: a macro whose calling mode is mutex lock;
[0089] Registering a callback is to pass a function (callback) to another function so that it will be called when a certain event or condition occurs; specifically:
[0090] 1) Define the callback function;
[0091] First, define a callback function, usually with a signature that matches the expected function arguments. For example, in Rust, you can use a closure or a function pointer:
[0092] fn my_callback(data:i32){
[0093] println! ("Callback called with data:{}",data);
[0094] }
[0095] 2) Define a structure or function that accepts a callback;
[0096] Create a structure or function that can accept a callback as a parameter. For example:
[0097] struct EventHandler{
[0098] callback:Option <Box<dyn Fn(i32)> >, / / Use trait objects to store callbacks
[0099] }
[0100] impl EventHandler{
[0101] fn register_callback <f>(&mut self,cb:F)
[0102] where
[0103] F:Fn(i32)+'static, / / Requires the callback to meet the Fn characteristics and survive statically
[0104] {
[0105] self.callback = Some(Box::new(cb)); / / Register callback
[0106] }
[0107] fn trigger_event(&self,data:i32){
[0108] if let Some(ref cb)=self.callback{
[0109] cb(data); / / Call callback
[0110] }
[0111] }
[0112] }
[0113] 3) Register callback: In the main program or elsewhere, create an EventHandler instance and register the callback function:
[0114] fn main(){
[0115] let mut handler=EventHandler{callback:None};
[0116] handler.register_callback(my_callback); / / Register callback
[0117] handler.trigger_event(42); / / Trigger event, call callback
[0118] }
[0119] 4) Trigger event: When a specific condition occurs, the callback function handler.trigger_event(10) is triggered by calling the event handling method (such as trigger_event); the callback is called and the data is passed.
[0120] The calling method is replaced with the mutex lock macro, modules / fileops / src / lib.rs;
[0121] Use mutex_lock! macro instead of calling file.lock() directly to ensure safety in a multithreaded environment and avoid data competition.
[0122] Among them, the type of file is Arc <AxMutex <file>>
[0123] AxMutex comes from the underlying mutex component, so it can be called.
[0124] Regarding mutex_lock! macro, the specific structure is defined in modules / mutex_helper / src / lib.rs:
[0125] MutexHelper is a helper class that is responsible for managing the mutex logic associated with the current task. It contains a reference to the current task and implements some functions for waiting and waking up.
[0126] Mutex is a structure that implements mutual exclusion locks. It provides a lock method for acquiring locks. In the process of acquiring locks, the blocking and awakening mechanisms of tasks may be involved. When a task calls Mutex.lock, a MutexHelper instance is passed in as a parameter. The Mutex.lock method first checks whether the lock can be acquired. If not, it calls the block method to block the current task.
[0127] If the task needs to be blocked, the block method of MutexHelper will add the current task to a waiting queue (WaitQueue) and mark it as blocked. At this time, the task will be suspended, waiting for other tasks to release the lock. Once other tasks release the lock, the Mutex component will trigger the wake-up mechanism. Mutex will check the waiting queue internally and call the unblock method to remove the task from the waiting state. In the unblock method, MutexHelper will register the corresponding callback through WaitQueue to wake up the blocked task. When the task is awakened, it can try to acquire the lock again, and continue execution if successful.
[0128] The whole process forms a bottom-up callback mechanism, which ensures that the task can effectively enter the waiting state when needed and be awakened at the appropriate time.
[0129] The callback registration method forms a reverse dependency at runtime, but this dependency is limited to the pair of components: the lower-level mutex and the upper-level mutex_helper.
[0130] One-way dependencies between components are achieved by introducing an intermediate layer; Figure 2 As shown, including:
[0131] First, the call to the mutex lock is almost the same as the reference implementation except that the spin lock is replaced.
[0132] By referencing mutex_ops::MutexTrait, the lock / force_unlock method is promoted to the upper-level component mutex_ops for implementation; in this way, the position of mutex_ops is high enough, and it can naturally call high-level components such as task / run_queue.
[0133] Add a high-level component tid_map to cooperate with the upper-level component mutex_ops; the high-level component tid_map acts as an intermediary to manage the relationship between the task ID and the specific task, ensuring that WaitQueue only cares about the TaskID, avoiding direct reference to the Task object, and removing the function of reverse calling the upper-level Task. WaitQueue is only responsible for the TaskID of the push / pop task; how to use and map the TaskID is the responsibility of the upper-level component.
[0134] By introducing the middle layer tid_map, the reference of WaitQueue to Task is decoupled, and the reverse dependency of the operation process is completed by splitting Mutex according to structure and operation;
[0135] In order to decouple the mutex_ops component from the task / run_queue, the middle layer tid_map is used to split the Mutex by structure and operation to complete the reverse dependency of the operation process. The specific implementation is: implement the lock / force_unlock method in the mutex_ops component:
[0136] The lock method is to call Mutex.lock in mutex_ops, and directly use Mutex.lock to obtain the lock logic; for the waiting task, it is managed through tid_map, the TaskID of the current task is obtained and added to the waiting queue;
[0137] The force_unlock method is to call Mutex.force_unlock directly, use tid_map to find the task to be awakened when unlocking, remove the task from the waiting queue and add it to the running queue.
[0138] Drivers and devices - Issues involving mutex locks such as Figure 4 shown.
[0139] Similar to the previous question, driver_ops is equivalent to the fileops level, and the original device dev is equivalent to the file level. Mutex is divided into two levels according to structure and operation.
[0140] The relative complexity lies in that the driver may be multi-layered, and there is a hierarchical relationship between the driver components; each level of bus can be regarded as a container for the device, and there is also a relative hierarchical relationship.
[0141] For example, the process for a virtio block device involves:
[0142] 1) Discover the raw device through virtio_mmio, hang it on the virtio bus, and identify it as virtio_dev;
[0143] 2) Continue to probe it through virtio_blk and find that it is a block device, number it and manage it based on / dev / vda;
[0144] 3) Upper-level components access this device through / dev / vda.
[0145] Example 3
[0146] A computer device includes a memory and a processor, wherein the memory stores a computer program, and when the processor executes the computer program, the steps of a method for realizing unidirectional dependency of components of a componentized operating system described in embodiment 1 or 2 are implemented.
[0147] Example 4
[0148] A computer-readable storage medium stores a computer program, which, when executed by a processor, implements the steps of a method for implementing unidirectional dependency of components of a componentized operating system as described in Example 1 or 2.< / file> < / f> < / axtaskref> < / process>
Claims
1. A method for realizing unidirectional dependency of components of a componentized operating system, characterized in that: include: The structure definition and operation of resources are distributed into two layers. The lower layer components are used for the basic structure definition and status management of resources, and the upper layer components are used to perform various operations on resources, so that the operation is separated from the structure. Starting from the upper-layer components, search and locate the target resources layer by layer from top to bottom, and operate the target resources. The top-down relationship is called the positive direction. Dependencies are established by default. The upper-layer components rely on the lower-layer components to complete construction, startup, and operation.
2. A method for realizing one-way dependency of components of a componentized operating system according to claim 1, characterized in that: The lower-level components are used to define the basic structure of resources and manage the status of the basic structure of resources; they include: Resource structure definition: define the data structure of various resources and clarify their attributes; State management: used to maintain the current state information of various resources, including: creation, destruction, activation, suspension state transition, and implementation of state storage and update mechanism; Event notification: When the resource status changes, a notification is sent to the upper-level component to perform corresponding operations; Resource registration and deregistration: Provides interfaces for registering and deregistering resources to dynamically manage the lifecycle of various resources.
3. A method for realizing one-way dependency of components of a componentized operating system according to claim 1, characterized in that: The upper-level components are used to perform various operations on resources, including: Resource creation and destruction: Provides interfaces to create and destroy resources; Resource operation: Provides specific operation interfaces, including process scheduling, memory allocation, and device reading and writing. Each operation is performed by calling the structure defined by the lower-level components. Status query and change: Provide an interface to query the current status of resources and provide an interface to change the status of resources; Event processing: respond to event notifications from lower-level components and perform corresponding operations.
4. A method for realizing one-way dependency of components of a componentized operating system according to claim 1, characterized in that: In the lower-level components, the resource data structures in each lower-level component establish dependencies based on data inclusion or reference relationships; In the upper-level components, the operation process methods within each upper-level component establish dependencies based on the process scheduling relationship.
5. A method for realizing one-way dependency of components of a componentized operating system according to claim 1, characterized in that: One-way dependencies between components are implemented by registering callbacks, including: calling macros with mutex locks; Registering a callback is passing a function to another function so that it will be called when a certain event or condition occurs; specifically: 1) Define the callback function; 2) Define a structure or function that accepts a callback; 3) Register callback: In the main program or elsewhere, create an EventHandler instance and register the callback function: 4) Trigger event: When a specific condition occurs, the callback function is triggered by calling the event handling method; the callback is called and data is passed.
6. A method for implementing unidirectional dependency of components of a componentized operating system according to any one of claims 1 to 5, characterized in that: One-way dependencies between components are achieved by introducing an intermediate layer, including: By referencing mutex_ops::MutexTrait, the lock / force_unlock method is promoted to the upper-level component mutex_ops for implementation; Add a high-level component tid_map to cooperate with the upper-level component mutex_ops. The high-level component tid_map acts as an intermediary to manage the relationship between the task ID and the specific task, ensuring that WaitQueue only cares about the TaskID and WaitQueue is only responsible for the TaskID of the push / pop task. The reverse dependency of the operation process is completed by segmenting Mutex by structure and operation through the middle layer tid_map. The specific implementation is: implement the lock / force_unlock method in the mutex_ops component: The lock method is to call Mutex.lock in mutex_ops, and directly use Mutex.lock to obtain the lock logic; for the waiting task, it is managed through tid_map, the TaskID of the current task is obtained and added to the waiting queue; The force_unlock method is to call Mutex.force_unlock directly, use tid_map to find the task to be awakened when unlocking, remove the task from the waiting queue and add it to the running queue.
Citation Information
Cited By
Implementation method and system for full-modularization unified multi-architecture kernel
CN121523753A