Multi-channel persistent fast packet receiving, sorting and lock-free asynchronous read-write method
Patent Information
- Application Number
- CN202610632297.6
- Authority / Receiving Office
- CN · China
- Patent Type
- Applications(China)
- Current Assignee / Owner
- Filing Date
- 2026-05-09
- Publication Date
- 2026-08-11
AI Technical Summary
若能在不加锁的情况下,实现对持续解析的数据内容的快速异步存储和读取并保证读写数据的同步和一致性必然大放异彩
[0031] Furthermore, when using the multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read/write method on an operating system employing request-based segmented paging, the storage space used in the multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read/write method can be locked using a memory lock.
Smart Images

Figure CN122547568A_ABST
Abstract
Description
Technical Field
[0001] This invention relates to the fields of computer communication, storage technology, and data processing, and particularly to a multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read / write method. Background Technology
[0002] Continuous reception of data packets through multiple channels, rapid storage, classification, sorting, and parsing of the received data packets, and fast asynchronous reading and writing of the parsing results are the most common requirements in the entire field of computer communication. The data packets refer to messages with boundaries and a unified data format, i.e., message data containing a header, data, and trailer. "Multiple channels" broadly refers to multiple data channels, meaning the received data can originate from multiple different data buses such as UART / SPI / IIC / CAN / PCI / Ehternat, or from multiple TCP / UDP receiving ports on the same network interface.
[0003] When continuously receiving and storing multi-channel data packets, the total data flow and rate cannot be determined in advance. Therefore, it's often necessary to pre-allocate a certain amount of storage space as a receive buffer for each data channel. If the pre-allocated receive buffer for each channel is too large, it can directly lead to insufficient computer memory, especially for embedded computers with limited memory. Conversely, if the initial pre-allocated receive buffer for each channel is too small, any channel will fill the allocated buffer after a short period of continuous reception, requiring the reallocation of a new receive buffer. In this case, the physical space of the old and new buffers is often discontinuous, making continuous reception and parsing of data packets inconvenient, as well as continuous sorting of all received data packets. Even using popular methods like multiple circular queues or ping-pong FIFOs to segment and store received data increases the time overhead of receiving and parsing data packets due to multiple data transfers during data integration. Therefore, the importance of a method for continuously receiving, storing, and quickly classifying and sorting multi-channel data packets with low time and space complexity is self-evident.
[0004] Furthermore, continuously receiving data packets necessitates continuously parsing and writing the parsed data to storage or retrieving it for use. In many cases, data reading and writing are simultaneous and asynchronous, making synchronization during continuous read / write operations a more common issue—ensuring that data isn't erroneously read when it's only partially written. Locking and semaphores are common methods for read / write synchronization, but they indirectly increase the time overhead during the process. Achieving fast asynchronous storage and retrieval of continuously parsed data without locking, while ensuring synchronization and consistency between read and write data, would be a significant advantage. Summary of the Invention
[0005] In view of the shortcomings of the prior art, the purpose of this invention is to provide a multi-channel continuous fast packet reception, sorting and lock-free asynchronous read and write method.
[0006] This invention proposes a multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read / write method, including:
[0007] S1: Employs a dynamic expansion mechanism to continuously receive and store multi-channel data packets;
[0008] S2: Classify and sort the stored data packets;
[0009] S3: Perform asynchronous reading and writing of data packet parsing results in a lock-free manner.
[0010] Furthermore, S1 specifically includes:
[0011] S101: By dynamically allocating memory, a message stack is created in advance for each channel to store the received data packets;
[0012] S102: When a new data packet is received, first check whether the remaining space of the corresponding message stack is sufficient to store the new data packet; if the remaining space is sufficient, store the new data packet sequentially in the corresponding message stack; if the remaining space is insufficient, call the function realloc to reallocate a larger storage space starting from the original message stack head address, then store the received new data packets sequentially, update the stack top position, and record the current time.
[0013] S103: Whenever a larger space is reallocated to the data stack corresponding to a certain channel, the data flow rate of the most recent period is calculated by the time difference and storage space difference with the last time the storage space was allocated, and the size of the next reallocated storage space is dynamically adjusted according to the data flow rate, so that the faster the data flow rate of the channel, the more storage space is allocated each time.
[0014] Furthermore, the message stack is a custom structure type, and the structure members of the message stack include at least: a contiguous buffer of physical storage space, the starting position and length of each stored data packet, the total space size and remaining space size of the message stack, the total number of stored data packets and the top position of the stack, and the physical storage space can be allocated at least by calling the functions malloc, calloc or realloc.
[0015] Furthermore, S2 specifically includes:
[0016] S201: Generate a sorting node for each stored data packet, wherein each sorting node points to the storage start address of the corresponding data packet;
[0017] S202: Generate a corresponding sorting key for each sorting node according to the specific sorting requirements;
[0018] S203: Sort the sort nodes by comparing their keys;
[0019] S204: Save the sorting results by generating a hash table or a binary search tree.
[0020] Furthermore, S204 specifically includes:
[0021] A hash table is generated, and the starting address pointer of each sorting node is stored sequentially as an array element in the position array of the hash table. The function qsort is called to quickly sort the pointers of each sorting node by comparing the sorting keys of each sorting node.
[0022] Alternatively, each sorting node can be treated as a child node of a binary tree, and the nodes can be sorted by inserting them into the corresponding positions in the binary search tree using the sorting key.
[0023] Furthermore, S3 specifically includes:
[0024] S301: Create a circular stack to store the parsed data content. Each element of the circular stack corresponds to a structure element generated after parsing a data packet. The member variables of the structure element contain all the data content to be parsed. Then, write and read threads are created to generate structure elements from the parsed data packet and read the generated structure elements, respectively.
[0025] S302: In the write thread, after parsing each new data packet, a new structure element is generated and written to the position after the top of the circular stack. Only after the writing is completed is the top of the stack updated to point to the position of the newly written element.
[0026] S303: In the read thread, each time it is necessary to read one or more recently parsed data elements, the starting position of the element is first calculated by the current stack top position and the number of data elements to be read. Then, the corresponding data element is read from the circular stack by calling the function memcpy. The stack top position is not changed during the reading process.
[0027] Furthermore, the circular stack is a custom structure type, and the member variables of the circular stack include at least a physical space contiguous data element buffer szElem[ELEM_CNTMAX], the stack top position top, and the overflow flag isOverFlow. Here, ELEM_CNTMAX is the maximum number of data elements that can be stored in the data element buffer, the initial value of the stack top position top is assigned to -1, and the initial value of the overflow flag isOverFlow is assigned to 0.
[0028] Furthermore, the method for updating the stack top position in S302 is: top = (top + 1) % ELEM_CNTMAX;
[0029] Before updating the top position of the stack, it is necessary to calculate whether the circular stack has overflowed. If top + 1 = ELEM_CNTMAX, then the overflow flag isOverFlow must be updated to 1 before updating the top position of the stack.
[0030] Further, the method for reading one or more recently parsed data elements in S303 is as follows: the number of data elements actually stored in the current circular stack is calculated from the current stack top position top and the overflow flag isOverFlow value; when the number of frames to be read rdCnt is less than or equal to the number of data elements actually stored in the circular stack, the position distribution of the data elements to be read is deduced by combining the current stack top position and the overflow flag, and then the rdCnt frame data elements to be read are copied by calling the memcpy function; when top + 1 < rdCnt and isOverFlow = 1, it means that the position distribution of the multiple frames of data elements to be read crosses the physical right boundary of the circular stack buffer and is divided into two segments. At this time, it is necessary to copy and read the two segments of data elements by calling the memcpy function twice. Otherwise, it means that the data elements to be read are stored in a continuous arrangement and only need to be copied completely by one memcpy function.
[0031] Furthermore, when using the multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read / write method on an operating system employing request-based segmented paging, the storage space used in the multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read / write method can be locked using a memory lock.
[0032] The beneficial effects of the technical solutions provided in the embodiments of the present invention include at least the following:
[0033] (1) In this embodiment of the invention, an independent message stack is generated for each channel, which ensures that the data packets received by each channel are physically stored continuously, which is beneficial for data packet classification, sorting and parsing.
[0034] (2) In the embodiments of the present invention, each channel does not need to pre-allocate too much cache space when continuously receiving and storing packets, which reduces the space complexity of the multi-channel packet receiving method.
[0035] (3) In this embodiment of the invention, the size of the buffer increased each time it is reallocated is dynamically adjusted according to the data flow during the packet receiving process, thereby balancing the frequency of space reallocation and saving time.
[0036] (4) In this embodiment of the invention, no lock is added during the asynchronous parallel reading and writing of data. The synchronization of reading and writing data is achieved by writing the stored data and then updating the top position of the circular stack, which saves the time overhead of the reading and writing synchronization process. Attached Figure Description
[0037] The accompanying drawings are for illustrative purposes only and are not intended to limit the invention. Throughout the drawings, the same reference numerals denote the same parts. Obviously, the drawings described below are merely some embodiments of the present invention, and those skilled in the art can obtain other drawings based on these drawings without any creative effort.
[0038] Figure 1 This is a flowchart illustrating the multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read / write method provided in this embodiment of the invention.
[0039] Figure 2 This is a code example diagram of the circular stack implementation provided in an embodiment of the present invention. Detailed Implementation
[0040] To enable those skilled in the art to better understand the technical solutions in the embodiments of the present invention, the technical solutions of the present invention will be clearly and completely described below with reference to the accompanying drawings. Obviously, the described embodiments are only some embodiments of the present invention, not all embodiments. It should be understood that these descriptions are merely exemplary and are not intended to limit the scope of the present invention. Based on the embodiments of the present invention, all other embodiments obtained by those skilled in the art without creative effort should fall within the scope of protection of the present invention.
[0041] The following description, in conjunction with the accompanying drawings, details the multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read / write method provided by the embodiments of the present invention through specific examples and application scenarios.
[0042] Reference manual attached Figure 1 The diagram illustrates a flowchart of the multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read / write method provided in an embodiment of the present invention.
[0043] This invention provides a multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read / write method, which may include the following steps:
[0044] S1: Employs a dynamic expansion mechanism to continuously receive and store multi-channel data packets.
[0045] In a possible implementation, S1 specifically includes sub-steps S101 to S103:
[0046] S101: By dynamically allocating memory, a message stack is created in advance for each channel to store the received data packets.
[0047] Optionally, the message stack is a custom structure type. The structure members of the message stack include at least: a contiguous buffer of physical storage space, the starting position and length of each stored data packet, the total size and remaining size of the message stack, the total number of stored data packets and the top position of the stack, and the physical storage space can be allocated by calling the functions malloc, calloc or realloc.
[0048] S102: Upon receiving a new data packet, first check if there is enough remaining space in the corresponding message stack to store the new data packet. If there is enough remaining space, store the new data packet sequentially in the corresponding message stack. If there is insufficient remaining space, call the function realloc to reallocate a larger storage space starting from the original message stack head address, then store the received new data packets sequentially, update the stack top position, and record the current time.
[0049] Those skilled in the art can determine the timing for calling the `realloc` function to reallocate more space based on the actual situation; this invention does not impose any limitations. It is sufficient to record the total amount of received data, the remaining space, and the stack top position in the message stack's data structure. Then, in the API function that writes data to the message stack, based on the current capacity and the amount of data to be stored, a `realloc` function call is made according to a custom strategy when capacity is insufficient. Finally, the total amount of received data, the remaining space, and the stack top position are updated. Therefore, the message stack is essentially a logically custom data structure, or more accurately, a container.
[0050] S103: Whenever a larger space is reallocated to the data stack corresponding to a certain channel, the data flow rate of the most recent period is calculated by the time difference and storage space difference between the last time the storage space is allocated and the last time the storage space is allocated. The size of the next reallocated storage space is dynamically adjusted according to the data flow rate, so that the faster the data flow rate of the channel, the more storage space is reallocated each time, thereby reducing the number of times the corresponding message stack is reallocated when the channel data flow rate is high.
[0051] Optionally, the method for dynamically adjusting the size of the next reallocated storage space based on the data traffic speed is as follows:
[0052]
[0053] in, C represents the amount of storage space required for the i-th channel during this dynamic expansion. min This represents the preset minimum expansion capacity, α represents the expansion adjustment coefficient, and v i T represents the data flow rate of the i-th channel over a recent period of time. i This represents the estimated buffer protection time for the i-th channel.
[0054] Furthermore, a packet description node is generated for the newly written packet. The packet description node includes at least the channel number channelId, the packet start address pointer pktPtr, the packet length pktLen, the receive timestamp recvTime, the channel sequence number channelSeq, the data type identifier typeFlag, and the check identifier checkFlag.
[0055] Write the packet descriptor node to the packet descriptor node index descIndex in the message stack so that subsequent classification, sorting and parsing processes access the original packet entity through the packet start address pointer pktPtr, without performing duplicate copying of the packet entity.
[0056] When running on an operating system that uses demand-segmented paging, memory locking is performed on the message stack buffer, packet descriptor node index, and dedicated memory management structure allocated in step S1.
[0057] It's important to note that the core of the multi-channel continuous fast packet receiving and storage method lies in the contiguous message stack of physical storage space. This message stack is implemented by calling the `realloc` function. During creation, the initial memory for the message stack can be dynamically allocated on the heap by calling `malloc`, `calloc`, or directly calling `realloc`. When writing data packets to the message stack, if the size of the data packet to be written to the top of the stack exceeds the remaining space capacity, `realloc` can allocate a larger receive buffer for that channel. It's worth noting that the allocation mechanism of `malloc` essentially finds a contiguous block of available space on the heap and marks it as occupied. The `realloc` function, however, first attempts to find a larger, contiguous block of space starting from the original allocated space address. If sufficient contiguous space is found at the original address, the larger block is marked as occupied. This process does not require moving or copying data from the original space; it only re-marks the new occupied space range, resulting in extremely low time overhead. However, there are exceptions. If the `realloc` function cannot find a sufficiently large contiguous space from the original address during the reallocation process, it will find enough space elsewhere on the heap, copy the data from the original space to the new space using `memcpy`, and then release the occupancy marker of the original space using `free`. In this case, the data copying during memory reallocation will incur significant time overhead. However, in general-purpose computers, the total heap capacity is often much larger than the global area, and the global area capacity is often much larger than the stack. This means that when using this method to receive data, such as network TCP port data, in general-purpose computers, there are rarely situations where `realloc` calls need to copy data from the original space to the new space. Even in the field of embedded computers, due to the large number of channels and varying data traffic per channel, the continuous packet receiving method provided by this invention can achieve low time and space complexity, unless packet receiving is carried out over a long period of time. In addition, it is worth noting that, since the method provided by this invention records the current time (which can be obtained through Systick or an external clock) before each realloc, and can directly calculate the recent data flow rate of the channel by using the time difference and capacity difference between two adjacent realloc memory reallocation times, the size of the space increased by reallocation can be adjusted accordingly. This avoids the waste of memory resources caused by excessive pre-allocation space, and also avoids the waste of time caused by frequent reallocation to expand space when receiving high-flow data due to insufficient pre-allocation space each time.
[0058] In this embodiment of the invention, by constructing a dynamic message stack based on contiguous memory for each channel and combining it with the realloc on-demand expansion mechanism, low-overhead memory expansion is achieved without data migration in most cases, thereby ensuring high efficiency and low latency in the multi-channel high-concurrency data reception process. Simultaneously, by recording the time difference and capacity difference between adjacent expansion moments to calculate the real-time data flow rate of the channel, and adaptively adjusting the subsequent expansion magnitude accordingly, the system can reduce the time overhead caused by frequent expansion in high-flow scenarios and avoid memory waste caused by excessive pre-allocation in low-flow scenarios. Furthermore, by combining the packet description node and zero-copy pointer mechanism, subsequent sorting and parsing stages do not require repeated data copying, achieving a dynamic balance between time complexity and space utilization, and improving the system's stability, scalability, and real-time processing capabilities in general-purpose computers and embedded environments.
[0059] S2: Classify and sort the stored data packets.
[0060] In a possible implementation, S2 specifically includes sub-steps S201 to S204:
[0061] S201: Generate a sorting node for each stored data packet, with each sorting node pointing to the storage start address of the corresponding data packet.
[0062] S202: Generate a corresponding sorting key for each sorting node according to the specific sorting requirements.
[0063] S203: Sort each sort node by comparing its key.
[0064] S204: Save the sorting results by generating a hash table or a binary search tree.
[0065] Optionally, S204 specifically includes:
[0066] A hash table is generated, and the pointers to the first addresses of each sorted node are stored sequentially as array elements in the position array of the hash table. The function qsort is called to quickly sort the pointers of each sorted node by comparing the sorting keys of each sorted node.
[0067] Alternatively, each sorting node can be treated as a child node of a binary tree, and the nodes can be sorted by inserting them into the corresponding positions in the binary search tree using the sorting key.
[0068] It's important to note that the main steps of the method for quickly classifying and sorting stored data packets are to generate sorting nodes with sorting keys for each packet based on sorting requirements. These sorting nodes can be implemented using structures, as long as their member variables contain pointers to the storage addresses of the data packets being sorted. There are two main sorting methods: One is to treat the sorting nodes as array elements, storing pointers to the sorting nodes corresponding to each packet in a hash table's position array, and then using the `qsort` function to quickly sort these pointers based on the sorting node's key. The advantage of this approach is that only the pointers to the sorting nodes need to be moved during the sorting process, rather than the entire data packet being sorted. Furthermore, `qsort` is the only general-purpose quicksort function interface provided by the C standard library; other methods such as bubble sort and merge sort only provide existing function interfaces in the POSIXC standard library. The other method is to use the sorting nodes as binary tree nodes. In this case, the sorting process is essentially comparing keys to generate a sorted binary tree, whether it's a red-black tree, a max-heap, or another type, which can be chosen according to actual needs.
[0069] In this embodiment of the invention, by constructing a sorting node containing only keywords and address pointers for each data packet, the "data body" and the "sorting structure" are decoupled. This allows the sorting process to operate only on lightweight pointers rather than large data packets, thereby significantly reducing memory relocation overhead and improving sorting efficiency. Furthermore, by combining hash tables and binary search trees as optional structures, the system can achieve efficient and fast sorting using qsort in batch data scenarios, and real-time ordered maintenance using a tree structure in dynamic insertion scenarios. This allows for a flexible balance between time complexity, real-time performance, and resource consumption under different business requirements. In addition, the unified sorting node structure facilitates direct access to the original data via pointers in the subsequent parsing stage, achieving zero-copy data transfer and further improving overall processing performance and system scalability.
[0070] It is important to note that the packet description node generated for each received packet in S1 (containing members such as the packet storage starting address pointer pktPtr, packet length pktLen, and channel number channelId) directly serves as input to the sorting node in S2. The sorting node in S2 points to the corresponding packet description node through pointers. During the sorting process, only the sorting node pointers are moved, not the packet entities. After the sorting is completed in S2, the ordered arrangement of the sorting nodes indirectly reflects the logical order of the packet description nodes. The asynchronous read / write operation in S3 accesses the packet parsing results based on the sorted packet description nodes, locates the original packet through the starting address pointer in the packet description node, and stores it into the circular stack after parsing. Thus, S1, S2, and S3 form a complete zero-copy data processing pipeline under the pointer passing of the packet description nodes: S1 is responsible for the continuous storage of packets and the generation of description nodes, S2 is responsible for the lightweight sorting of description nodes, and S3 is responsible for lock-free read / write of the parsing results based on the sorting results. The three work together to reduce the overall time and space complexity of multi-channel packet processing.
[0071] S3: Perform asynchronous reading and writing of data packet parsing results in a lock-free manner.
[0072] In a possible implementation, S3 specifically includes sub-steps S301 to S303:
[0073] S301: Create a circular stack to store the parsed data. Each element of the circular stack corresponds to a structure element generated after parsing a data packet. The member variables of the structure element contain all the data content that needs to be parsed. Then, write and read threads are created respectively to generate structure elements from the parsed data packets and to read and use the generated structure elements.
[0074] Optionally, the circular stack is a custom structure type. The member variables of the circular stack include at least a physically contiguous data element buffer `szElem[ELEM_CNTMAX]`, the stack top position `top`, and an overflow flag `isOverFlow`. `ELEM_CNTMAX` is the maximum number of data elements that can be stored in the data element buffer. The initial value of the stack top position `top` is set to -1, and the initial value of the overflow flag `isOverFlow` is set to 0. The purpose of using a circular stack is essentially to ensure that data is refreshed in real time, and old data can be overwritten. This ensures that the latest frame or multiple frames of data are always read. Unlike traditional circular queues, the circular stack defined in this application has a single-end read and write position; that is, data is written to and read from the stack top position. However, when reading data, only the data is copied without clearing it, so the stack top position is not moved during data reading.
[0075] S302: In the write thread, after parsing each new data packet, a new structure element is generated and written to the position after the top of the circular stack. Only after the writing is completed is the top of the stack updated to point to the position of the newly written element.
[0076] Alternatively, the method to update the stack top position in S302 is: top = (top + 1) % ELEM_CNTMAX.
[0077] Before updating the top position of the stack, it is necessary to calculate whether the circular stack has overflowed. If top + 1 = ELEM_CNTMAX, then the overflow flag isOverFlow must be updated to 1 before updating the top position of the stack.
[0078] Furthermore, before writing elements to the parsed structure, the write thread uses the tail sequence counting approach to atomically obtain the current write sequence number and uses it as the seqid of the current write operation.
[0079]
[0080] Among them, seqid w This indicates the write sequence number obtained by the write thread in this write operation. FAA represents the Fetch-And-Add atomic addition operation. tail represents the write end sequence counter corresponding to the circular stack. 1 indicates the increment step of tail for each write operation.
[0081] Based on the write sequence number seqid_w and the ring stack capacity ELEM_CNTMAX, determine the target write position pos_w of the structure element in this parsing operation within the ring stack:
[0082]
[0083] Where, pos w This indicates the target physical location where the writing thread is writing to the parsed structure element this time. ELEM_CNTMAX represents the capacity of the circular stack, and mod represents the modulo operation.
[0084] The write thread reads the element sequence number `elemSeq_pos` at the target write position `pos_w` and determines whether writing is allowed at that target write position. If `elemSeq_pos` ≤ `seqid_w` and the target position does not contain any unread valid elements, then writing is allowed at that target write position. Otherwise, writing is temporarily prohibited at that target write position.
[0085] When the target write position allows writing, the parsed structure element is written to the data element buffer position corresponding to pos_w in the circular stack, and the valid flag validFlag and the element sequence number elemSeq at that position are updated after the writing is completed.
[0086] The write thread uses a CAS operation to replace the old node in the target write position with the new element node, and confirms the write is complete after the CAS replacement is successful.
[0087] After the write thread parses and writes the structure elements completely, it updates the top position of the stack, so that the read thread can only read the structure elements that have been completely written.
[0088] S303: In the read thread, each time it is necessary to read one or more recently parsed data elements, the starting position of the element is first calculated by the current stack top position and the number of data elements to be read. Then, the corresponding data element is read from the circular stack by calling the function memcpy. The stack top position is not changed during the reading process.
[0089] Optionally, the method for reading one or more recently parsed frames of data elements in S303 is as follows: the number of data elements actually stored in the current circular stack is calculated from the current stack top position (top) and the overflow flag (isOverFlow). When the number of frames to be read (rdCnt) is less than or equal to the number of data elements actually stored in the circular stack, the position distribution of the data elements to be read is deduced by combining the current stack top position and the overflow flag, and then the rdCnt frame data elements to be read are copied by calling the memcpy function. When top + 1 < rdCnt and isOverFlow = 1, it means that the position distribution of the multiple frames of data elements to be read crosses the physical right boundary of the circular stack buffer and is divided into two segments. In this case, the two segments of data elements need to be copied and read in segments by calling the memcpy function twice. Otherwise, it means that the data elements to be read are stored in a continuous manner and only one memcpy function is needed to copy them completely.
[0090] Furthermore, the read thread uses a CAS operation to replace the valid element node in the read position with an empty node, completing the read confirmation and space reuse marking, enabling the write thread to subsequently determine that the position is reusable. When the write thread or read thread experiences consecutive CAS failures at the target position, the failure count (fails) is recorded. If the failure count reaches the preset maximum failure count (MAX_FAILS), the current operation is written to the operation announcement table, and other threads assist in completing the write or read operation.
[0091] When other threads discover that there are incomplete operations in the operation announcement table, they call the helper function to complete the operation, so that the corresponding write or read operation is completed in a finite number of steps.
[0092] Furthermore, the maximum number of retries a single thread can make in the normal path can be limited, and after the maximum number of failures is exceeded, it can enter the assisted path, so that each read and write operation is completed within a limited number of attempts.
[0093] It should be noted that the core of the method for fast asynchronous reading and writing of data packet parsing results in a lock-free manner is the use of a circular stack to achieve lock-free data synchronization. This ensures that read and write threads can simultaneously read and write data from the circular stack in parallel without a lock mechanism. The circular stack is a custom data structure defined in this application. Its member variables include at least a physically contiguous data element buffer `szElem[ELEM_CNTMAX]`, the stack top position `top`, and an overflow flag `isOverFlow`. `ELEM_CNTMAX` is the maximum number of data elements that can be stored in the data element buffer. The initial value of the stack top position `top` is set to -1, and the initial value of the overflow flag `isOverFlow` is set to 0. When reading data, the circular stack does not update the stack top position; that is, it does not remove the read data from the circular stack. Instead, it uses `memcpy` to copy the data. When writing data to the circular stack for storage, the method to update the stack top position is `top = (top + 1) %ELEM_CNTMAX`. Before updating the top position of the stack, it is necessary to calculate whether the circular stack has overflowed. If top + 1 = ELEM_CNTMAX, then the overflow flag isOverFlow must be updated to 1 before updating the top position. This process of writing data to the circular stack first and then updating the top position, and reading the circular stack first and then copying the data, ensures that there will be no situation where half a data packet is written and then read as a whole packet. This achieves asynchronous parallel read and write and data synchronization without locks. As long as the circular stack is large enough, when reading the most recent multi-frame data, there will be no situation where the data being read is overwritten by newly written data because the read is slightly slower. This is because such a situation can only occur within a single time period when the written data has covered an entire circle of the circular stack, which is impossible when the circular stack is large enough.
[0094] In this embodiment of the invention, by adopting a single-end read-write circular stack structure, data writing and reading are performed uniformly at the top of the stack. This ensures that the write thread always sequentially appends the latest parsing result, while the read thread obtains the latest data in a "copy-only, no-move" manner, thereby avoiding the synchronization overhead caused by frequent movement of read and write pointers in traditional queues. At the same time, the circular overlay mechanism implemented by modulo operation allows old data to be automatically overwritten by new data, ensuring that the latest data is always retained while maintaining a fixed and controllable memory space, thus improving system real-time performance. Combined with an overflow flag and a segmented copy strategy, cross-boundary reading remains efficient and correct, thereby achieving high-throughput, low-latency data sharing access in a multi-threaded, lock-free environment, and improving overall data processing efficiency and system stability.
[0095] Reference manual attached Figure 2 The diagram illustrates a code example of a circular stack implementation provided in an embodiment of the present invention. To facilitate faster understanding and application of this solution by those implementing it, the following is directly provided: Figure 2 The illustrated code example of a circular stack directly shows the definition of the circular stack data structure, its read interface function, and its write interface function. It's important to note that the initialization process of the circular stack is omitted in the diagram. In reality, during initialization, the top position `top` is initialized to -1, and the overflow flag `isOverFlow` is initialized to 0. This code has several unique features. In the write interface function `void StoreFSMPos(FSM_LWE02A_POS *pstFSMPos)`, the data element `pstFSMPos` to be written to the circular stack is first copied to the position after the current top position using the `memcpy` function. Only after the data copy is complete is the top position `gFSMStack.top` updated to point to the newly written element. This ensures that before the copy of the new element data in the current frame is complete, the top position `gFSMStack.top` read by the read thread will always point to the complete data element of the previous frame, thus avoiding the blunder of asynchronous read and write operations and guaranteeing fast parallel asynchronous read and write operations on the circular stack without the need for locking mechanisms.
[0096] Figure 2The function `int RdRecentFSMPos(FSMPOS_ELEM *buf, unsigned int rdFSMPosCnt)` provides an example of a circular stack read interface. The function takes `rdFSMPosCnt` as its input parameter, representing the number of the most recent data elements to be read. The function returns the actual number of elements read (a return value less than 0 corresponds to the number of missing data elements in the circular stack). `STORE_FSMELEM_CNTMAX` represents the maximum number of elements the circular stack can store. When `rdFSMPosCnt > STORE_FSMELEM_CNTMAX`, it means the number of elements `rdFSMPosCnt` to be read is greater than the stack's storage capacity. Therefore, it returns a negative value (`STORE_FSMELEM_CNTMAX - rdFSMPosCnt`) to indicate how many missing elements are needed to read `rdFSMPosCnt`. The function calculates dCnt = top + 1 – rdFSMPosCnt only when the number of elements to be read is less than the stack capacity. If dCnt > 0, then the consecutive rdFSMPosCnt elements physically reversed from the next element at the top of the stack are the elements to be read. Reading from a circular stack only copies the elements without deleting them from the stack, thus reducing the time overhead of reading. If dCnt < 0, it means that szElem[0]~szElem[top+1] is less than the number of rdFSMPosCnt elements to be read. At this time, the overflow flag isOverFlow is used to determine whether the circular stack has overflowed (i.e., the circular stack has already stored STORE_FSMELEM_CNTMAX) data. If it has overflowed, then the data is divided into two segments, szElem[0]~szElem[top+1] and szElem[STORE_FSMELEM_CNTMAX + dCnt], and memcpy is called to read them respectively. Conversely, if there has never been an overflow, it means that there is only one data element szElem[0]~szElem[top+1] in the circular stack, so only the top+1 data elements can be read.
[0097] It's worth noting that the first step of the `RdRecentFSMPos` function is `int top = gFSMStack.top`, which immediately reads the current `top` value. This ensures that even if a new element is added to the circular stack during the read process, causing `gFSMStack.top` to be affected, the reading of the element pointed to by `top` will not be affected. Therefore, the core idea of lock-free read-write synchronization using a circular stack is that the `StoreFSMPos` function, which writes to the circular stack, only updates the top position `gFSMStack.top` after the data is copied onto the circular stack using `memcpy`. This guarantees that the `RdRecentFSMPos` function will not read an element that is only partially copied, because the update of the top position `gFSMStack.top` during the write process is only done after the data copy is complete, and the element at the next position pointed to by the `top` value used during the read process is complete.
[0098] Furthermore, when using multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read / write methods on an operating system that employs request-based segmented paging, memory locks can be used to lock the storage space used in these methods, thus avoiding additional time overhead that may be caused by page replacement and page faults.
[0099] Finally, it should be noted that the above embodiments are only used to illustrate the technical solutions of the embodiments of the present invention, and are not intended to limit them. Although the present invention has been described in detail with reference to the foregoing embodiments, those skilled in the art should understand that modifications can still be made to the technical solutions described in the foregoing embodiments, or equivalent substitutions can be made to some of the technical features. These modifications or substitutions do not cause the essence of the corresponding technical solutions to deviate from the spirit and scope of the technical solutions of the embodiments of the present invention. Any changes or substitutions that can be easily conceived by those skilled in the art within the scope of the technology disclosed in the present invention should be included within the protection scope of the present invention.
Claims
1. A method for multi-channel persistent fast-packet receiving, ordering and lock-free asynchronous read-write, characterized in that, include: S1: Employs a dynamic expansion mechanism to continuously receive and store multi-channel data packets; S2: Classify and sort the stored data packets; S3: Perform asynchronous reading and writing of data packet parsing results in a lock-free manner.
2. The multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read / write method according to claim 1, characterized in that, S1 specifically includes: S101: By dynamically allocating memory, a message stack is created in advance for each channel to store the received data packets; S102: When a new data packet is received, first check whether the remaining space of the corresponding message stack is sufficient to store the new data packet; if the remaining space is sufficient, store the new data packet sequentially in the corresponding message stack; if the remaining space is insufficient, call the function realloc to reallocate a larger storage space starting from the original message stack head address, then store the received new data packets sequentially, update the stack top position, and record the current time. S103: Whenever a larger space is reallocated to the data stack corresponding to a certain channel, the data flow rate of the most recent period is calculated by the time difference and storage space difference with the last time the storage space was allocated, and the size of the next reallocated storage space is dynamically adjusted according to the data flow rate, so that the faster the data flow rate of the channel, the more storage space is allocated each time.
3. The multi-lane persistent fast gather packet, ordering and lock-free asynchronous read-write method of claim 2, wherein, The message stack is a custom structure type. The structure members of the message stack include at least: a contiguous buffer of physical storage space, the starting position and length of each stored data packet, the total space size and remaining space size of the message stack, the total number of stored data packets and the top position of the stack, and the physical storage space can be allocated by calling the functions malloc, calloc or realloc.
4. The multi-lane persistent fast gather packet, ordering and lock-free asynchronous read-write method of claim 1, wherein, S2 specifically includes: S201: Generate a sorting node for each stored data packet, wherein each sorting node points to the storage start address of the corresponding data packet; S202: Generate a corresponding sorting key for each sorting node according to the specific sorting requirements; S203: Sort the sort nodes by comparing their keys; S204: Save the sorting results by generating a hash table or a binary search tree.
5. The multi-lane persistent fast gather packet, ordering and lock-free asynchronous read-write method of claim 4, wherein, S204 specifically includes: A hash table is generated, and the starting address pointer of each sorting node is stored sequentially as an array element in the position array of the hash table. The function qsort is called to quickly sort the pointers of each sorting node by comparing the sorting keys of each sorting node. Alternatively, each sorting node can be treated as a child node of a binary tree, and the nodes can be sorted by inserting them into the corresponding positions in the binary search tree using the sorting key.
6. The multi-lane persistent fast gather packet, ordering and lock-free asynchronous read-write method of claim 1, wherein, S3 specifically includes: S301: Create a circular stack to store the parsed data content. Each element of the circular stack corresponds to a structure element generated after parsing a data packet. The member variables of the structure element contain all the data content to be parsed. Then, write and read threads are created to generate structure elements from the parsed data packet and read the generated structure elements, respectively. S302: In the write thread, after parsing each new data packet, a new structure element is generated and written to the position after the top of the circular stack. Only after the writing is completed is the top of the stack updated to point to the position of the newly written element. S303: In the read thread, each time it is necessary to read one or more recently parsed data elements, the starting position of the element is first calculated by the current stack top position and the number of data elements to be read. Then, the corresponding data element is read from the circular stack by calling the function memcpy. The stack top position is not changed during the reading process.
7. The multi-lane persistent fast gather packet, ordering and lock-free asynchronous read-write method of claim 6, wherein, The circular stack is a custom structure type. The member variables of the circular stack include at least a physical space contiguous data element buffer szElem[ELEM_CNTMAX], the stack top position top, and the overflow flag isOverFlow. ELEM_CNTMAX is the maximum number of data elements that can be stored in the data element buffer. The initial value of the stack top position top is set to -1, and the initial value of the overflow flag isOverFlow is set to 0.
8. The multi-lane persistent fast gather packet, ordering and lock-free asynchronous read-write method of claim 7, wherein, The method for updating the stack top position in S302 is: top = (top + 1) % ELEM_CNTMAX; Before updating the stack top position, it is necessary to calculate whether the circular stack storage has overflowed. If top + 1 = ELEM_CNTMAX, then the overflow flag isOverFlow needs to be updated to 1 before updating the stack top position.
9. The multi-lane persistent fast-packet collecting, ordering and lock-free asynchronous read-write method according to claim 8, characterized in that, The method for reading one or more recently parsed data elements in S303 is as follows: the number of data elements actually stored in the current circular stack is calculated from the current stack top position top and the overflow flag isOverFlow value. When the number of frames to be read, rdCnt, is less than or equal to the number of data elements actually stored in the circular stack, the distribution of the data elements to be read is deduced by combining the current stack top position and the overflow flag. Then, the data elements of the rdCnt frames to be read are copied by calling the memcpy function. When top + 1 < rdCnt and isOverFlow = 1, it means that the distribution of the data elements of the multiple frames to be read crosses the physical right boundary of the circular stack buffer and is divided into two segments. In this case, the data elements of the two segments need to be copied and read in segments by calling the memcpy function twice. Otherwise, it means that the data elements to be read are stored in a continuous manner and only one memcpy function is needed to copy them completely.
10. The multi-lane persistent fast gather packet, ordering and lock-free asynchronous read-write method of claim 1, wherein, When using the multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read / write method on an operating system that employs request-based segmented paging, the storage space used in the multi-channel continuous fast packet reception, sorting, and lock-free asynchronous read / write method can be locked using a memory lock.
