Secure operating system kernel based on Rust language and RISC-V architecture and implementation method thereof
By adopting the Rust language ownership system, borrow checking and smart pointers in the operating system kernel, the problem of memory security failure is solved, and a high-security and high-efficiency operating system kernel is achieved.
Patent Information
- Application Number
- CN202510008803.X
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2025-01-03
- Publication Date
- 2025-05-02
AI Technical Summary
The existing operating system kernel lacks security checks during the compilation period, resulting in memory security failure problems, such as use after release, null pointer dereferences, and buffer crossing boundaries.
The security operating system kernel is developed using the Rust language, and uses Rust's ownership system, borrow checking, smart pointer and error handling characteristics to perform memory management, concurrent security and exception handling.
Through Rust's security check mechanism, avoid memory security failures, ensure the security and concurrent security of the kernel, and improve the efficiency of the kernel.
Smart Images

Figure HDA0005227741860000011 
Figure HDA0005227741860000012 
Figure HDA0005227741860000013
Abstract
Description
Technical Field
[0001] The present invention belongs to the technical field of operating system kernels, and specifically relates to a secure operating system kernel based on Rust language and RISC-V architecture and an implementation method thereof. Background Art
[0002] In recent years, with the rise of the localization wave, the localization of basic software in key areas is advancing rapidly. The operating system kernel is an important system basic software that is responsible for managing computer hardware resources and providing services for upper-level applications, allowing applications to ignore hardware details and focus on their own logic. A typical operating system kernel consists of memory management, process management, file management and other parts.
[0003] Rust is a brand new system-level programming language that can ensure memory safety, type safety, and concurrency safety. Rust uses an ownership system and borrowing checks instead of a garbage collection mechanism for memory management, ensuring memory safety without introducing runtime overhead. Rust prevents undefined implicit type conversions and avoids problems such as memory access out of bounds. Rust's memory management mechanism and smart pointers prevent data competition during multi-threaded runtime, ensuring concurrency safety. Rust introduces Option and Result enumerations, requiring developers to explicitly handle exceptions when programming to avoid common problems such as null pointers. The above advantages show that Rust is a language suitable for system kernel development and can ensure the security of the system kernel.
[0004] RISC-V is an open source processor instruction set architecture with many advantages such as low power consumption, customizability, and scalability. Therefore, RISC-V is a feasible path for China to master independent and controllable chip technology. At present, the software ecosystem of RISC-V is developing rapidly. Compilers such as GCC and LLVM and simulators such as QEMU have provided support for the RISC-V architecture. However, compared with mature architectures such as x86 and ARM, RISC-V still needs more basic software to support it.
[0005] Currently, operating system kernels are mainly written in C language and run on x86 or ARM architecture, such as MINIX, Xv6, PINTOS, etc. However, the programming mechanism of C language is too flexible and lacks the necessary safety check mechanism, which may cause a series of memory safety failures, such as use after free, null pointer dereference, and buffer out of bounds. Summary of the invention
[0006] In view of the problem that the existing operating system kernel lacks security checks during the compile time, the present invention provides a secure operating system kernel based on the Rust language and the RISC-V architecture and its implementation method, adopts the Rust language to develop the operating system kernel, and avoids memory safety failures in the prior art through a series of security check mechanisms. For use after release, Rust's ownership check mechanism can correct it during the compile time; for null pointer dereference, Option and Result provide representation and processing methods for such situations; for buffer out-of-bounds, Rust performs boundary checks on array accesses, and uses iterators to further simplify such operations.
[0007] Specifically, the present invention can be achieved through the following technical solutions:
[0008] A method for implementing a secure operating system kernel based on the Rust language and RISC-V architecture, wherein the secure operating system kernel is developed using the Rust language, and the Rust language's ownership system, borrowing check, smart pointers, error handling features, etc. are utilized to ensure the security of the operating system kernel;
[0009] The ownership system is used to bind memory resources to variables and release the bound resources after the variables have reached the end of their life cycle; it reduces the resource consumption of garbage collection and avoids memory safety issues such as dangling pointers and secondary releases;
[0010] The borrow check is used to ensure that a resource has only one mutable reference or multiple immutable references at the same time, to prevent data competition and ensure data security of concurrent system processes;
[0011] The smart pointers include Rc (reference count), RefCell (reference cell), etc. By using the Rc smart pointer, the same data can be read concurrently between multiple control flows, and Rust can automatically release its memory space when the reference count of the data is reduced to zero; by using the RefCell smart pointer, the ownership check at compile time can be broken, allowing more flexible data sharing, and Rust can ensure that there is only one writer or multiple readers of the data in RefCell at the same time in real time at runtime, thereby ensuring memory safety; combining the use of the two can ensure the concurrent safety of the system kernel.
[0012] The error handling uses Option and Result enumerations to define function return values. By analyzing None and Err variants, it can handle error situations including null pointers and no return values, accurately identify error types, and promptly handle exceptions in the system kernel.
[0013] The secure operating system kernel includes a hardware driver module, a system kernel module and a user program module. The hardware driver module is used to control the computer hardware under the RISC-V architecture and provide an interface for the system kernel module to interact with the hardware; the system kernel module is used to implement the basic functions of the operating system kernel and provide a system call interface for the user program module; the user program module is used to call and test the functions of the system kernel module and its correctness.
[0014] The hardware driver module further includes a RISC-V page table driver, an interrupt controller driver, a communication serial port driver and a disk driver, which configure and drive the RISC-V page table, the interrupt controller, the communication serial port and the disk respectively; wherein:
[0015] The RISC-V page table driver constructs a three-level page table in SV39 mode, can simulate the conversion process from virtual address to physical address, loads the page table base address into the SATP (Supervisor Address Translation and Protection) register and refreshes the TLB (Translation Lookaside Buffer) cache when switching page tables. The driver provides an interface for the virtual memory module in the memory management module to interact with the memory management of the RISC-V processor;
[0016] The interrupt controller driver includes a PLIC (Platform-Level Interrupt Controller) driver and a CLINT (Core Local Interruptor) local interrupt controller driver; wherein PLIC processes interrupts generated by external devices, specifically, in the present invention, PLIC processes interrupts of communication serial port devices and disk devices; CLINT processes clock interrupts and software interrupts, specifically, in the present invention, CLINT processes exceptions such as on-chip clocks, system calls, and page faults;
[0017] The communication serial port driver initializes and interrupts the serial port device, provides a communication interface for receiving and sending characters for the system kernel module, and provides an input echo function for the system terminal;
[0018] The disk driver initializes and interrupts the disk device, provides a disk block read and write interface for the system kernel module, and builds an initial file system when the system is started for the first time.
[0019] The system kernel module part further includes a memory management module, a process management module and a file management module.
[0020] The memory management module further includes a physical memory management module and a virtual memory management module, wherein:
[0021] The physical memory management module pages the free physical memory. The free pages are managed by a linked list. The linked list needs to be modified for allocating and releasing physical memory. When there is no free physical memory, the None variant in Rust is returned to avoid returning a null pointer. Based on the memory allocation and release interface implemented in the physical memory management module, the dynamic memory allocator of the buddy algorithm is implemented, and the GlobalAlloc (global allocator) interface provided by the alloc library in Rust is further implemented to directly use the data structure in the alloc library in the system kernel.
[0022] The virtual memory management module is based on the physical memory management module and the RISC-V page table driver, and can provide respective virtual memory spaces for the system kernel and different user processes; the main functions of the virtual memory management module include:
[0023] When the system starts, it constructs a page table for the kernel, maps the device's address space, kernel stack, and context switch page, uses smart pointers to protect the kernel page table, obtains its immutable reference when accessing the page table, and obtains its mutable reference when modifying the page table, ensuring the data security of the kernel page table during concurrency; when the process starts, it constructs a page table for the process, maps the user stack and context switch page;
[0024] When allocating and releasing virtual space, the virtual address of the required operation is translated into physical address through the page table, and the corresponding request is initiated to the physical memory allocation;
[0025] When the kernel reads and writes user space, it can translate the virtual address of the selected process into a physical address, and read and write memory at the physical address to complete the data transfer.
[0026] The process management module can perform interrupt processing, process scheduling, process control and process synchronization.
[0027] The interrupt handling function jumps to the interrupt handling function when all exceptions and interrupts occur, and handles external device interrupts, clock interrupts, software interrupts or other abnormal situations. Specifically, the communication serial port interrupts, disk interrupts, page fault exceptions, system calls and timer interrupts are classified and processed. Rust's unique match expression is used to perform pattern matching and classification processing on interrupts to ensure that any type of interrupt is processed and avoid undefined behavior.
[0028] The process scheduling adopts a time slice round-robin process scheduling algorithm. Each process occupies an equal time slice. When the time slice ends, the scheduler selects other processes to run. Each RISC-V core has a process scheduler, which starts to execute after the system starts. If the current core has no schedulable process, the scheduler will put the core into a dormant state and wait for an interrupt to occur. Based on Rust's ownership characteristics, smart pointers are used to protect the process queue. The process scheduler of each core needs to obtain the write operation permission of the process queue before starting the scheduling operation. It is ensured that the process queue will not be accessed by multiple cores at the same time, further ensuring the security of concurrent data.
[0029] In a specific implementation, when a clock interrupt arrives, the system executes the interrupt processing function and then performs process scheduling; a complete process scheduling process is as follows:
[0030] First, the context of the current process is saved and switched to the kernel thread of the current process; secondly, the context of the current kernel thread is saved and switched to the scheduler context of the current core; then the scheduler starts executing and selects the next process to enter the processor; then the scheduler context is saved and switched to the kernel thread of the target process; finally, the system call returns and returns to the user space of the target process.
[0031] The process control can be performed through the process control block, including creating child processes, executing programs, changing process sizes, process sleep and wakeup, waiting for child processes, and process exit operations. All process control blocks are stored in an array to record the information of each process. The Option enumeration provided by Rust is used to wrap each process control block in the Option enumeration. If the accessed process exists, its Some variant is returned; if the accessed process does not exist, its None variant is returned.
[0032] When creating a child process, a new process control block is allocated, and its parent process is set, the complete page table of the parent process and its mapped physical memory pages are copied, the file descriptor of the parent process is copied, and finally the child process is placed in a schedulable queue;
[0033] When executing a program, the file system is called and the ELF (Executable and Linkable Format) header is checked. The program is read into the memory in segments, program stack space is allocated and running parameters are passed in, and the process control block information is updated.
[0034] When changing the size of a process, when increasing the space, first allocate physical memory pages, then add the page mapping to the process page table; when reducing the space, first cancel the page mapping, then release the physical memory;
[0035] When a process sleeps and wakes up, the process state is changed to mark the sleep and wake-up of the process. When waking up a process, all processes with the same sleep address will be woken up;
[0036] When waiting for the child process to exit, the parent process executes this operation to wait for its child process to complete execution, and puts the parent process into a sleep state during the waiting process;
[0037] When a process exits, all physical memory mapped by its page tables and the memory occupied by the page tables themselves are released.
[0038] The process synchronization uses spin locks and sleep locks to protect shared data in critical areas by applying for and releasing locks, including process scheduling queues, lists of files opened by the system, etc. Among them, the process that applies for the spin lock will be in a busy waiting state, and the process that applies for the sleep lock will enter a sleep state until other processes wake it up. The application and release of the lock are implemented using the RISC-V atomic instruction amoswap to ensure the atomicity of the spin lock. Furthermore, Rust's core library provides an AtomicBool variable to wrap the instruction, and the atomic operation of the spin lock can be implemented by operating the atomic Boolean variable.
[0039] The file management module includes a physical file system and a virtual file system, and is hierarchically designed with a six-layer structure, specifically divided into a hardware layer, a cache layer, a log layer, an index node layer, a directory layer, and a file descriptor layer.
[0040] The physical file system caches some disk blocks and uses a log system to record all file system operations to ensure the persistence and atomicity of the operations. It is divided into a hardware layer, a cache layer, and a log layer.
[0041] The hardware layer is implemented by the disk driver, which copies the disk blocks required by the file system to the cache blocks in the memory by calling the interface provided by the disk driver; when a process starts the copy operation, it enters the sleep state; when the operation is completed, the disk issues an interrupt to wake up the process to continue execution;
[0042] The cache layer consists of a circular queue, which caches the disk blocks requested by the virtual file system to improve the access speed. The present invention evicts cache blocks by using the LRU (Least Recently Used) algorithm; each cache block records its reference count, valid bits, and corresponding disk block number information; all reads and writes to the disk need to be performed through the cache layer;
[0043] The log layer ensures that any file operation will not be completed only partially due to external factors, causing the file system to be in an inconsistent error state, and controls all write operations to the disk. Its operation process is as follows: first, the process declares the start of a file system operation, writes all content to the log, and finally declares the completion of a file operation; when there is no process in an unfinished file operation, the log layer performs a group commit, and writes all uncommitted log operations to the log area of the disk; after completing a group commit, a complete commit is recorded in the log area of the disk, and finally all content in the log area is installed to its correct disk location; when the disk stops running due to external factors, the system will check whether there is a complete commit in the disk log area when restarting, and if so, it will be installed to the correct disk location.
[0044] The virtual file system, based on the physical file system function, realizes a higher level of abstraction, uses index nodes to describe a single file, represents the tree structure of the file system as a directory, and uses file descriptors to control the directories opened by the process; it is divided into an index node layer, a directory layer, and a file descriptor layer.
[0045] The index node layer, the index node describes the information of the file or directory. On the disk, all index nodes are arranged in a continuous space, recording the file type, number of connections and data location; in the memory, the index node additionally stores the device number, number of references and valid bit information. When operating the index node, first read the corresponding index node from the disk cache according to the index node number, lock the index node and release the lock after modification, and write the modified index node and file block to the log. Using Rust's ownership system idea, for the same index node, each process that needs to read the file will obtain a copy of the index node and have ownership of the copy without obtaining the index node lock, which helps improve the concurrency of file operations. When the process wants to update the index node, it needs to obtain the lock of the index node to ensure concurrency safety;
[0046] The directory layer can search or create a file directory; when searching, it obtains the corresponding directory index node according to the input file directory; when creating, it locates the target path and creates a new directory index node;
[0047] In the file descriptor layer, the process records the files it opens and distinguishes them by file descriptors in the order of opening. When a process opens a file, it gets a new file descriptor, and operates on its file descriptor when reading or writing the file. The file descriptor uniformly abstracts the console, pipes, and files, and the interface for reading and writing other devices is consistent with the file.
[0048] The user program module calls the functions provided by the system kernel module through the system call interface in the system kernel module, and the implementation includes: creating a child process, waiting for a child process, process execution, process exit, process deletion, process sleep, obtaining process number, changing space size, obtaining system time, read operation, write operation, creating a pipe, opening a file, closing a file, creating a link, canceling a link, creating a directory and other functions.
[0049] The user program module includes a terminal, a system kernel test program and a file system operation program; the terminal can obtain another executable program from the file system and create a subprocess to execute the program; the system kernel test program tests and checks the memory management module, the process management module and the file management module; the file system operation program can create new files or directories, edit and save file contents.
[0050] The present invention also provides a secure operating system kernel based on Rust language and RISC-V architecture, wherein the secure operating system kernel includes: a hardware driver module, a system kernel module and a user program module;
[0051] The hardware driver module includes a RISC-V page table driver, an interrupt controller driver, a communication serial port driver, and a disk driver; it is used to control the computer hardware under the RISC-V architecture and provide an interface for the system kernel module to interact with the hardware;
[0052] The system kernel module includes a memory management module, a process management module and a file management module, which are used to implement the basic functions of the operating system kernel and provide a system call interface for the user program module;
[0053] The user program module includes a terminal, a system kernel test program and a file system operation program; and is used to call and test the function and correctness of the system kernel module.
[0054] Compared with the prior art, the present invention has the following beneficial effects:
[0055] The operating system kernel provided by the present invention has high security, and the operating system kernel is completely written in Rust language based on RISC-V architecture. Through the static check of the code by the Rust compiler, it is guaranteed that there will be no security vulnerabilities in the kernel code during the writing process. This is reflected in the ownership system, borrowing check, smart pointer and error handling introduced by Rust. The ownership system binds memory resources to variables and releases the bound resources after the variables go out of the life cycle. Reduce the resource consumption of garbage collection and avoid memory safety issues such as dangling pointers and secondary release. Borrowing check is used to ensure that a resource has only one mutable reference or multiple immutable references at the same time, prevent data competition, and ensure data security of system processes during concurrency. Smart pointers improve the flexibility of kernel programming through reference counting or internal variability design methods, while ensuring that concurrent security is not damaged. Error handling uses Option and Result enumerations to replace the concept of NULL with None or Err, so that the kernel code must perform additional processing on such special cases. Avoid the incorrect use of null pointers and uninitialized variables.
[0056] The operating system kernel provided by the present invention has high operating efficiency. Compared with the garbage collection mechanism of other high-level programming languages, Rust adopts the ownership system to manage memory, avoiding the problem of garbage collection during program operation and reducing operating efficiency. Rust adopts the RAII mechanism, and resources are acquired or assigned when initialized, and are automatically released after leaving the scope, avoiding resource leakage and the problem of empty resources wasting memory. Rust follows the concept of zero-cost abstraction, that is, the abstract functions such as interfaces, generics, closures, etc. provided in the Rust language will not reduce its compiled execution efficiency. Help the system kernel improve performance while simplifying the code.
[0057] The operating system kernel structure provided by the present invention is concise, with clear layers and strong portability. The operating system kernel designed by the present invention adopts a typical UNIX system structure, which includes hardware drivers, memory management, process management, file management and user programs from bottom to top. At the same time, the functions of the system kernel are abstracted as a system call interface and provided to user programs. The present invention is completed based on the general RISC-V architecture, and all parameters related to the hardware platform are independently macro-defined. When ported to other RISC-V platforms, only a small amount of code and macro definition need to be changed. BRIEF DESCRIPTION OF THE DRAWINGS
[0058] In order to more clearly illustrate the embodiments of the present invention or the technical solutions in the prior art, the drawings required for use in the embodiments or the description of the prior art will be briefly introduced below. Obviously, the drawings described below are only some embodiments of the present invention. For those skilled in the art, other drawings can be obtained based on these drawings without paying any creative work.
[0059] Figure 1 This is a schematic diagram of the overall architecture and component elements of the secure operating system kernel based on the Rust language and RISC-V architecture of the present invention.
[0060] Figure 2 It is a schematic diagram of a mapping scheme from virtual memory to physical memory under a memory management module in a system kernel of the present invention.
[0061] Figure 3 It is a schematic diagram of the interrupt processing scheme under the process management module in the system kernel of the present invention.
[0062] Figure 4 The present invention is a flowchart of the process scheduling process under the process management module in the system kernel.
[0063] Figure 5 It is a schematic diagram of process state changes and conditions under the process management module in the system kernel of the present invention.
[0064] Figure 6 The figure is a schematic diagram of the overall architecture of the file system under the file management module in the system kernel of the present invention.
[0065] Figure 7 The present invention is a flowchart of log recording under the file management module in the system kernel.
[0066] Figure 8 It is a schematic diagram of the index node data structure under the file management module in the system kernel of the present invention. DETAILED DESCRIPTION
[0067] The present invention is further described in detail with reference to the following specific examples and drawings. The process, conditions, experimental methods, etc. for implementing the present invention, except for the contents specifically mentioned below, are all common knowledge and common common sense in the art and are not particularly limited by the present invention.
[0068] The present invention provides a method for implementing a secure operating system kernel based on Rust language and RISC-V architecture, including a hardware driver module, a system kernel module and a user program module. The hardware driver module includes a RISC-V page table driver, an interrupt controller driver, a communication serial port driver and a disk driver; the system kernel module includes a memory management module, a process management module and a file management module; the user program module includes a terminal, a system kernel test program and a basic file system operation program. The system kernel module abstracts the hardware driver and provides it to the user program in the form of a system call. In the system kernel module, the memory management module includes a physical memory management module and a virtual memory management module; the process management module can perform interrupt processing, process scheduling, process control and process synchronization; the file management module includes a physical file system and a virtual file system. The present invention utilizes the characteristics of Rust language to ensure the security of the system kernel: follow the ownership rules to avoid dangling pointers and ensure memory security; prevent data competition through borrowing checks and smart pointers to ensure concurrency security; use enumeration for explicit error handling to ensure that kernel exceptions are handled in a timely manner. The operating system kernel provided by the present invention has the characteristics of high security, high operating efficiency, simple structure and good portability.
[0069] The present invention proposes a method for implementing a secure operating system kernel based on Rust language and RISC-V architecture, wherein the operating system kernel includes a hardware driver module, a system kernel module, and a user program module. The core work of the present invention is in the system kernel module, which includes a memory management module, a process management module, and a file management module. In the system kernel module, the memory management module includes a physical memory management module and a virtual memory management module; the process management module implements interrupt processing, process control, process scheduling, and process synchronization; the file management module includes a physical file system and a virtual file system, which are divided into a hardware layer, a cache layer, a log layer, an index node layer, a directory layer, and a file descriptor layer from bottom to top.
[0070] The physical memory management module performs paging management on the physical memory starting from the kernel start position, and further implements dynamic memory management based on paging management. The virtual memory management module maps the virtual memory space of the kernel and user processes to the physical memory, and implements the data transfer function between different page table spaces.
[0071] The physical memory management module manages the allocatable memory. Figure 2As shown in the figure, all physical memory after the system kernel data is allocatable memory. After paging the area, each page is managed by a linked list pointer. Based on the above paging logic, the buddy algorithm is used for dynamic memory allocation. The buddy algorithm divides each physical memory page into blocks, and the size of each block is a power of 2. A memory block may be in an idle or allocated state, and has a buddy block of the same size and adjacent address. When allocating a piece of memory, the size of the requested space is rounded up to a power of 2, and a matching free block is searched. If it does not exist, the larger block is recursively split until a free block of the appropriate size is obtained. When releasing memory, recursively check whether the buddy block is idle. If it is idle, merge the two blocks into a larger block. The dynamic memory allocator based on the buddy algorithm provides alloc (memory allocation) and dealloc (memory release) functions. These two functions can be used to implement the GlobalAlloc interface provided by the alloc library in Rust. Based on the implementation of this interface, the kernel and user programs can use the data structures in the alloc library. Help improve development efficiency and data structure security.
[0072] Virtual memory management maps the virtual memory space of the kernel and user processes to physical memory according to the page table. The mapping scheme of the kernel page table is as follows: Figure 2 As shown. Among them, the page at the top of the virtual memory space is the context switch page, and its purpose is to enable different processes to use the same virtual address to save the context content when the context is switched. The subsequent page is the kernel stack of the process. When the kernel thread of a process starts running, the kernel stack will be used as its stack space. This design ensures the isolation between user threads and kernel threads. In particular, device registers are also accessed through memory addresses, but their memory addresses do not belong to the range of physical memory. The present invention adopts direct mapping when implemented. That is, the device register address is directly mapped to the same address of the kernel page table.
[0073] The process management module includes interrupt handling, process scheduling, process control and process synchronization functions. Interrupt handling uniformly handles multiple interrupt sources and distributes them to other modules. Process scheduling switches the context of different processes. Process control manages the switching of processes between different modes. Process synchronization uses spin locks and sleep locks to protect critical sections and prevent data conflicts.
[0074] The logic of interrupt processing is as follows Figure 3As shown, the operating system kernel of the present invention mainly receives four interrupt sources. They are the communication serial port UART (Universal Asynchronous Receiver / Transmitter), the disk device based on the VIRTIO (Virtual Input / Output) interface, the timer TIMER and the environment call ECALL (Environment Call) instruction. Among them, the communication serial port and the disk are external devices, and their interrupts are sent to PLIC, which sends an interrupt to the RISC-V core. The timer and environment call are local interrupts, and CLINT sends an interrupt to the RISC-V core. When any of the above interrupts occurs, the control flow jumps to the interrupt handling function. The function is implemented by a match expression, which performs pattern matching on the interrupt cause and forwards the interrupt that can be processed to the corresponding module. Rust requires that the match expression must handle all situations of the input conditions to ensure the certainty and security of the statement execution. Accordingly, wildcards are used to match the remaining unprocessed interrupt situations and output them uniformly.
[0075] The logic of process scheduling is as follows Figure 4 As shown. In the present invention, each process includes two threads, namely, a user thread and a kernel thread. Among them, the user thread runs in the U mode of RISC-V, and each user thread has an independent page table; the kernel thread runs in the S mode of RISC-V, shares the same kernel page table, but uses an independent kernel stack. When the process time slice ends, the process enters the sleep state or the process actively gives up the CPU, a process scheduling occurs. Take the scheduling of switching from process A to process B as an example. First, save the context of the user thread of process A, switch from the thread to its kernel thread; switch the context of the kernel thread of process A and the process scheduler, and execute the process scheduler; then switch the context of the process scheduler and the kernel thread of process B; finally restore the context of the user thread of process B, and complete a process scheduling. In the system kernel of the present invention, all cores share a process queue, and the process scheduler needs to access the queue when executing. Rust's ownership characteristics are used in the design, and the process queue is protected using smart pointers. The process scheduler of each core needs to obtain the write operation permission of the process queue before starting the scheduling operation. It is ensured that the process queue will not be accessed by multiple cores at the same time, which further ensures the security of concurrent data.
[0076] Process control enables processes to switch between different states, maximizing the operating efficiency of the operating system kernel. When the system starts, all processes are in an idle state; after the system kernel completes initialization, it will start the init process, which is used to release the resources of all subsequent orphan processes. Figure 5As shown in the figure, when fork is called, a child process is created, and the kernel copies the page table and physical pages of its parent process to the child process. The child process enters the ready state and waits to be scheduled. When the scheduler selects a ready process, the process obtains the CPU and enters the running state. If a running process needs to wait for resources to be ready (sleep lock, disk cache, serial port input), the process enters the sleep state until the required resources are ready. If a process's time slice ends or it voluntarily gives up the CPU, the process directly enters the ready state. When a process calls exit or is killed for other reasons, it enters the zombie state. The parent process is responsible for recycling all child processes in the zombie state. If the parent process of a process has exited, the parent process of the process is set to the init process. The Option enumeration provided by Rust is used to wrap the process control block. If the read process does not exist (for example, the parent process has exited), the None variant of the Option enumeration will be returned. The None variant must be considered in the design to avoid errors such as accessing null pointers.
[0077] Process synchronization is implemented by two types of locks, namely spin locks and sleep locks. Among them, the spin lock is implemented based on the amoswap atomic instruction of the RISC-V architecture, and the Rust core library provides the AtomicBool variable to wrap the instruction. Importing this variable during implementation can simply implement the locking and releasing of the optional lock. In order to avoid the waste of CPU resources and deadlock problems caused by spin locks, a sleep lock is designed based on the spin lock. When applying for a sleep lock, if the lock is held, the process applying for the lock releases all held locks and enters a sleep state. When the lock is released, all processes that are sleeping due to applying for this lock will be awakened, try to acquire all locks before they sleep and continue execution.
[0078] The file management module includes a physical file system and a virtual file system, and adopts a hierarchical design. The overall architecture of the file system is as follows: Figure 6 As shown in the figure, the physical file system is divided into the hardware layer, cache layer and log layer; the virtual file system is divided into the index node layer, directory layer and file descriptor layer. The physical file system interacts with the disk, caches the used disk blocks into the memory, and uses logs to record all disk write operations to ensure the consistency and persistence of disk operations. The virtual file system uses the interface of the physical file system, uses index nodes to record files and directories, and provides file descriptors for upper-level programs to operate the file system.
[0079] The hardware layer is based on the disk driver to implement disk initialization and disk read and write operations. Specifically, when the disk is initialized, the various parts of the file system are loaded into the disk. Starting from the lowest address, the first two blocks are the boot block and the super block, which are responsible for disk startup and recording the metadata of the file system. The log block stores the log information written by the log layer and records whether the log is complete and valid. The index node block records the information of all files and directories in the file system. The bitmap block records the occupancy of all blocks on the disk. All remaining space is the data block storage area.
[0080] The cache layer is composed of a circular queue to form a cache space, and two pointers are used to implement the LRU replacement algorithm. The cache queue is implemented by wrapping the cache block array with the Option enumeration in Rust. When obtaining a cache block, if there is no free block at present, an unreferenced cache block is evicted according to the LRU algorithm. When the cache queue is full and cannot be evicted, the None variant is returned. The head and tail cache block mutable references are used to mark the newest and oldest blocks in the current cache queue. Each time a cache block is evicted or added, two mutable references are maintained to implement the LRU eviction algorithm. At the same time, these two mutable references are checked by Rust borrowing to ensure that no data contention occurs on the cache block.
[0081] The log layer records all disk reads and writes, and writes them uniformly to the disk log block, and finally writes them to the corresponding data block. When the system starts, check whether there is a complete and valid log in the log block. If it exists, it means that an abnormal shutdown occurred during the last system operation, and the complete log record is reloaded into the data block. Ensure the consistency and persistence of the file system. Figure 7 The process of writing logs in the log layer is shown. First, it is asserted that the current log space is sufficient to store a new file system operation, otherwise the file system operation is refused to be performed and the process is put into sleep mode until there is enough log space; the process declares the start of a file system operation, writes all contents to the log, and finally declares the completion of a file operation; when there is no process in an unfinished file operation, the log layer performs a group commit and writes all uncommitted log operations to the log area of the disk; after completing a group commit, a complete commit is recorded in the log area of the disk, and finally all contents in the log area are installed to their correct disk locations. In this process, if the system stops running due to external force, if the log area has not recorded a complete commit, then all changes will not be stored on the disk; if the log area has recorded a complete commit, then all changes will be correctly restored to the disk. The integrity of the file system is guaranteed.
[0082] The inode layer uses inode data structures to store files and directories. Figure 8The data structure of the index node is shown, including the file type, disk device number, number of links, direct block address and indirect block address of the file size. Among them, the file type may be a file or a directory, the disk device number records the storage location of the file, the number of links records the number of directories to which the file is linked, and the file size records the number of data blocks it occupies. The data blocks of the file are divided into direct blocks and indirect blocks. This design makes the reading speed of small files faster and can also support larger files. The data block address of the disk is saved in the direct block, while the indirect block requires two disk accesses to obtain the data block address. The file recorded by an index node can appear in multiple locations of the file system, which is determined by the number of links. When multiple processes want to obtain the same index node, it will cause concurrency problems such as cache update conflicts. The system kernel of the present invention uses the ownership system idea of Rust. Each process will obtain a copy of the index node and own its copy, which helps to improve the concurrency of file operations. When the process wants to update the index node, it needs to obtain the lock of the index node to ensure concurrency safety.
[0083] The directory layer and the file descriptor layer provide a higher level of abstraction for the file system. The directory layer uses a tree structure to describe the files and directories in the file system. By decomposing and analyzing the input directory string, the directory layer can locate the target index node. The file descriptor layer provides the highest level of abstraction. Each process uses an array to save the index node address of its opened file, and allows the use of array numbers to read and write the corresponding file. At the same time, the file descriptor can disguise the device as a file, so that the reading and writing of the device has the same operation mode as reading and writing files. Furthermore, when the serial port device or other device is initialized, its read and write functions are recorded in the system device list. When a process reads and writes a file descriptor, if its type is a device, the device read and write function is called, otherwise the file read and write function is called.
[0084] Example
[0085] The operating system kernel designed by the present invention based on Rust language and RISC-V architecture can be implemented on virtual machines such as QEMU and development boards of RISC-V architecture. Taking the implementation under QEMU as an example: the device register base address of the UART communication serial port is set to 0x10000000, the device register base address of the disk based on the VIRTIO interface is set to 0x10001000, the device register base address of the CLINT local interrupt controller is set to 0x2000000, the device register base address of the PLIC platform-level interrupt controller is set to 0x0c000000, and the starting address of the physical memory is 0x80000000. Use a linker script to put the first instruction of the kernel at the beginning of the physical memory, and at the same time, link the kernel in the order of text, rodata, data, and bss segments, and finally export the highest address of the kernel code and data as the starting address of the physical memory allocation.
[0086] Specifically, during the kernel implementation process, the security provided by the Rust language is fully utilized to ensure the security of the system kernel. The following example illustrates the security that Rust can provide compared to the traditional C language.
[0087] In the physical memory allocation module of the memory management module, a successful allocation request will return a section of free memory. In the traditional C language implementation, the free memory will be directly represented by its first address, that is, a memory address will be directly returned. However, when this section of memory is used up, the process may not notify the system kernel to release this section of memory. If the process is not recycled in time, this section of unreleased memory will cause a memory leak. In the Rust implementation of the present invention, free memory is represented by a memory description structure, which contains the starting address of the free memory and its length. When a process applies for memory, it will obtain ownership of a memory description structure. When the memory description structure goes out of its life cycle (no longer used), Rust will automatically call its release function to avoid memory leaks and ensure memory safety.
[0088] In the kernel implementation, the smart pointers provided by Rust are used to ensure concurrency safety. This type of data structure includes Rc (reference counting), RefCell (reference unit), and Mutex (mutex lock) and Arc (atomic counting) in a multi-threaded environment. The following takes the Rc and RefCell data structures in a single-threaded environment as examples to explain how this type of data structure protects key shared data structures and ensures the concurrency safety of the system kernel. There are read-only PID (Process ID) and mutable memory mapping, child process list and other data structures in the process control block. For read-only data structures, they will no longer be changed once the process is initialized; for mutable data structures, they may change during the process running. Use Rc to wrap read-only data structures. This data structure can generate multiple immutable references to the same data. When any immutable reference exists in its life cycle, the data structure will not be released. This ensures that when concurrently reading data such as PID, the PID will not be released because it leaves the life cycle. Use RefCell to wrap mutable data structures. This data structure allows mutable and immutable references to the same data, but Rust will check at runtime that only one mutable reference or multiple immutable applications exist at the same time. If the above conditions are broken, Rust will enter a panic state and interrupt the current application execution. This helps mutable data structures to be accessed concurrently while meeting Rust's safety requirements. For similar data structures, similar data protection measures often do not exist in system kernels implemented in C. Various parts of the kernel can freely access shared data, and careful debugging is often required during programming to avoid concurrent writes. Rust wraps the concurrent safety of the system kernel through the above-mentioned wrapper data structure.
[0089] The object-oriented programming features provided by Rust can help simplify the code and make the code structure clearer. For example, both PID and kernel stack resources are recycled. When a process is allocated, one is selected from the free resource pool for allocation, and when the process is released, it is put back into the resource pool. Therefore, the Recyclable interface is defined during implementation, which includes three functions: init, alloc, and recycle. Both the PID type and the kernel stack type implement the Recyclable interface. Compared with the process-oriented design concept of C language, this design method makes the code more readable and the function interface names more unified.
[0090] The protection content of the present invention is not limited to the above embodiments. Without departing from the spirit and scope of the present invention, changes and advantages that can be thought of by those skilled in the art are included in the present invention and are protected by the attached claims.
Claims
1. A method for implementing a secure operating system kernel based on Rust language and RISC-V architecture, characterized in that: The secure operating system kernel is developed using the Rust language, and the Rust language's features including ownership system, borrowing check, smart pointer, and error handling are used to ensure the security of the operating system kernel; the secure operating system kernel includes: a hardware driver module, a system kernel module, and a user program module, wherein: The hardware driver module is used to control the computer hardware under the RISC-V architecture and provide an interface for the system kernel module to interact with the hardware; The system kernel module includes a memory management module, a process management module and a file management module, which are used to implement the basic functions of the operating system kernel and provide a system call interface for the user program module; The user program module is used to call and test the functions and correctness of the system kernel module.
2. The method for implementing a secure operating system kernel according to claim 1, characterized in that: The hardware driver module includes a RISC-V page table driver, an interrupt controller driver, a communication serial port driver, and a disk driver; wherein: The RISC-V page table driver constructs a three-level page table in SV39 mode, simulates the conversion process from virtual address to physical address, loads the page table base address into the SATP register and refreshes the TLB cache when switching page tables; The interrupt controller driver includes a PLIC platform-level interrupt controller driver and a CLINT local interrupt controller driver, which are responsible for processing interrupts generated by external devices including communication serial ports and disks, and processing clock interrupts and software interrupts caused by on-chip clocks, system calls, and page fault exceptions; The communication serial port driver initializes and interrupts the serial port device, provides a communication interface for receiving and sending characters for the system kernel module, and provides an input echo function for the system terminal; The disk driver initializes and interrupts the disk device, provides a disk block read and write interface for the system kernel module, and builds an initial file system when the system is started for the first time.
3. The method for implementing a secure operating system kernel according to claim 1, characterized in that: In the system kernel module, the memory management module includes a physical memory management module and a virtual memory management module; wherein: The physical memory management module pages the free physical memory, manages the free pages through a linked list, allocates and releases physical memory by modifying the linked list, and returns a None variant in Rust when there is no free physical memory; The virtual memory management module provides respective virtual memory spaces for the system kernel and different user processes based on the physical memory management module and the RISC-V page table driver; The virtual memory management module realizes the construction and release of page tables, the allocation and release of virtual space, and the data transfer between different page tables; wherein: The described construction and release of page tables, when the system is started, the page table is constructed for the kernel, the address space, kernel stack and context switch page of the device are mapped, and the kernel page is protected by a smart pointer; when the process is started, the page table is constructed for the process, and the user stack and context switch page are mapped; The allocation and release of virtual space is performed by translating the physical address of the virtual address required to be operated through the page table and initiating a corresponding request to the physical memory allocation; When the system kernel needs to read or write the memory data of the user process, the virtual address of the user space and the user process page table are used for translation between the different page tables to obtain the final physical address of the read or write and complete the data transfer.
4. The method for implementing a secure operating system kernel according to claim 1, characterized in that: In the system kernel module, the process management module implements interrupt processing, process scheduling, process control and process synchronization; wherein: The interrupt processing, when all exceptions and interrupts occur, jumps to the interrupt processing function to process external device interrupts, clock interrupts and software interrupts; The process scheduling adopts a time slice round-robin process scheduling algorithm, where each process occupies an equal time slice, and when the time slice ends, the scheduler selects other processes to run; The process control switches the state of the process, changes the program executed by the process, changes the memory size occupied by the process, generates and waits for child processes, and uses the initial process to manage and recycle all processes without a parent process; The process synchronization uses spin locks and sleep locks to protect shared data in critical areas by applying for and releasing locks; wherein a process applying for a spin lock will be in a busy waiting state, and a process applying for a sleep lock will enter a sleep state until it is awakened by other processes.
5. The method for implementing a secure operating system kernel according to claim 4, characterized in that: When a clock interrupt arrives, the system executes the interrupt processing function and then performs process scheduling. During process scheduling, the following operations are performed: Save the context of the current process and switch to the kernel thread of the current process; Save the context of the current kernel thread and switch to the scheduler context of the current core; The scheduler starts executing and selects the next process to enter the processor; Save the scheduler context and switch to the kernel thread of the target process; The system call returns to the user space of the target process; and / or, The process control block is used to perform operations including creating a child process, executing a program, changing the process size, process sleep and wake-up, waiting for a child process, and process exit, and all the process control blocks are stored in a fixed-length array; wherein: The child process is created, a new process control block is allocated, and its parent process is set, the complete page table of the parent process and its mapped physical memory pages are copied, the file descriptor of the parent process is copied, and finally the child process is placed in a schedulable queue; The execution program calls the file system and checks the ELF header, reads the program into the memory in segments, allocates program stack space and passes in operating parameters, and updates the process control block information; When the process size is changed and the space is increased, the physical memory page is first allocated and then the page mapping is added to the process page table; when the space is reduced, the page mapping is first cancelled and then the physical memory is released; The process sleeps and wakes up, changes the process state to mark the sleep and wake up of the process, and when waking up the process, all processes with the same sleep address are woken up; The waiting child process and process exit, the parent process performs this operation to wait for its child process to complete execution, and puts the parent process into a sleep state during the waiting process; when the process exits, all physical memory mapped by its page table and the memory occupied by the page table itself are released; and / or, The application and release of the lock ensure the atomicity of the spin lock, and the atomic operation of the spin lock is realized by operating the atomic Boolean variable.
6. The method for implementing a secure operating system kernel according to claim 1, characterized in that: In the system kernel module, the file management module includes: a physical file system and a virtual file system, and is hierarchically designed with a 6-layer structure, wherein: The physical file system includes a hardware layer, a cache layer, and a log layer, which interacts with the disk driver, caches disk blocks, and records all file system operations to ensure the persistence and atomicity of the operations; The virtual file system includes an index node layer, a directory layer and a file descriptor layer. Based on the physical file system function, a higher level of abstraction is achieved. An index node is used to describe a single file, the tree structure of the file system is represented as a directory, and a file descriptor is used to control the directory opened by the process.
7. The method for implementing a secure operating system kernel according to claim 6, characterized in that: In the physical file system, The hardware layer is implemented by the disk driver, which copies the required disk blocks to the cache blocks in the memory; when a process starts the copy operation, it enters the sleep state; when the operation is completed, the disk sends an interrupt to wake up the process to continue execution; The cache layer, the cache consists of a circular queue, which caches the disk blocks requested by the virtual file system to improve the access speed, and uses the LRU least recently used algorithm to evict cache blocks; each cache block records its reference number, valid bits and corresponding disk block number information; The log layer ensures that any file operation will not be incomplete due to external factors, and controls the write operation of the file system. Its operation process is as follows: The process declares the start of a file system operation, writes all content to the log, and finally declares the completion of a file operation; When there is no process in the process of unfinished file operation, the log layer performs a group commit and writes all the uncommitted log operations to the log area of the disk; After completing a group commit, a complete commit is recorded in the log area of the disk, and finally all the contents of the log area are installed to their correct disk locations; When the disk stops running due to external factors, the system will check whether there is a complete commit in the disk log area when it restarts. If so, it will be installed to the correct disk location; and / or, In the virtual file system, The index node layer, the index node describes the information of the file or directory. In the disk, all index nodes are arranged in a continuous space, recording their file type, number of connections and data location; in the memory, the index node additionally stores the device number, number of references and valid bit information. When operating the index node, first read the corresponding index node from the disk cache according to the index node number, lock the index node and release the lock after modification, and write the modified index node and file block into the log; The directory layer searches or creates a file directory; when searching, it obtains a corresponding directory index node according to the input file directory; when creating, it locates the target path and creates a new directory index node; In the file descriptor layer, a process records the files it opens and uses file descriptors to distinguish them in the order of opening. When a process opens a file, it obtains a new file descriptor, and operates on its file descriptor when reading or writing the file. The file descriptor uniformly abstracts the console, pipe, and file, and the interface for reading and writing other devices is consistent with the file.
8. The method for implementing a secure operating system kernel according to claim 1, characterized in that: By abstracting and encapsulating the functions provided by the memory management module, the process management module and the file management module, one or more system call interfaces are obtained. The user program module implements the following functions by calling the system call interface: creating a child process, waiting for a child process, process execution, process exit, process deletion, process sleep, obtaining a process number, changing the space size, obtaining the system time, read operations, write operations, creating a pipe, opening a file, closing a file, creating a link, canceling a link, and creating a directory.
9. The method for implementing a secure operating system kernel according to claim 1, characterized in that: The user program module includes a terminal, a system kernel test program and a file system operation program; the terminal obtains another executable program from the file system and creates a subprocess to execute the program; the system kernel test program tests and checks the memory management module, the process management module and the file management module; the file system operation program creates a new file or directory, edits and saves the file content.
10. A secure operating system kernel based on Rust language and RISC-V architecture, characterized in that: The secure operating system kernel includes: a hardware driver module, a system kernel module and a user program module; The hardware driver module includes a RISC-V page table driver, an interrupt controller driver, a communication serial port driver, and a disk driver; it is used to control the computer hardware under the RISC-V architecture and provide an interface for the system kernel module to interact with the hardware; The system kernel module includes a memory management module, a process management module and a file management module, which are used to implement the basic functions of the operating system kernel and provide a system call interface for the user program module; The user program module includes a terminal, a system kernel test program and a file system operation program; and is used to call and test the function and correctness of the system kernel module.