Hierarchy and Movement
Relevant source files
This page explains the hierarchical relationships between sessions, process groups, and processes in the axprocess crate, and details how processes can move between different groups and sessions. For information about parent-child relationships between processes, see Parent-Child Relationships. For details about thread management within processes, see Thread Management.
Hierarchical Structure Overview
The axprocess system implements a three-level hierarchical structure inspired by Unix-like operating systems:
- Sessions: The top-level container that groups related process groups
- Process Groups: The middle-level container that groups related processes
- Processes: The individual execution units that can contain multiple threads
This hierarchy is used for organizing processes and implementing features like job control. Each entity in the hierarchy is identified by a unique process identifier (Pid).
flowchart TD
subgraph Session["Session"]
S["Session (sid)"]
PG1["ProcessGroup (pgid1)"]
PG2["ProcessGroup (pgid2)"]
P1["Process (pid1)"]
P2["Process (pid2)"]
P3["Process (pid3)"]
P4["Process (pid4)"]
end
PG1 --> P1
PG1 --> P2
PG2 --> P3
PG2 --> P4
S --> PG1
S --> PG2
Sources: src/session.rs(L1 - L45) src/process_group.rs(L1 - L56) src/process.rs(L83 - L89)
Process Group and Session Relationships
In the axprocess crate, the relationships between sessions, process groups, and processes are implemented using strong and weak references:
- Each process stores a strong reference (
Arc) to its process group - Each process group stores a strong reference to its session
- Both process groups and sessions store weak references (
WeakMap) to their contained entities to prevent reference cycles
classDiagram
class Session {
sid: Pid
process_groups: WeakMap~
+sid() Pid
+process_groups() Vec~
}
class ProcessGroup {
pgid: Pid
session: Arc
processes: WeakMap~
+pgid() Pid
+session() Arc
+processes() Vec~
}
class Process {
pid: Pid
group: SpinNoIrq~
+group() Arc
+set_group() void
+create_session() Option~(Arc, Arc) ~
+create_group() Option~
+move_to_group() bool
}
Process "1" --> "*" ProcessGroup : belongs to
Process "1" --> "*" ProcessGroup : belongs to
Sources: src/session.rs(L12 - L18) src/process_group.rs(L12 - L17) src/process.rs(L83 - L164)
Creating New Sessions
A process can create a new session and become its session leader by calling the create_session() method. This operation also creates a new process group within the new session, with the process as the process group leader.
sequenceDiagram
participant Process as Process
participant NewSession as New Session
participant NewProcessGroup as New Process Group
participant OldProcessGroup as Old Process Group
Process ->> Process: create_session()
Note over Process: Check if already session leader
Process ->> NewSession: Session::new(pid)
Process ->> NewProcessGroup: ProcessGroup::new(pid, &new_session)
Process ->> OldProcessGroup: Remove process from old group
Process ->> NewProcessGroup: Add process to new group
Process ->> Process: Update group reference
Process -->> Process: Return (new_session, new_group)
Key features of session creation:
- A process cannot create a new session if it is already a session leader (when
process.group().session.sid() == process.pid()) - When a new session is created, a new process group is also created with the same ID
- The process is moved from its old process group to the new one
Sources: src/process.rs(L100 - L123) tests/session.rs(L21 - L44)
Creating New Process Groups
A process can create a new process group within its current session and become its group leader by calling the create_group() method.
sequenceDiagram
participant Process as Process
participant Session as Session
participant NewProcessGroup as New Process Group
participant OldProcessGroup as Old Process Group
Process ->> Process: create_group()
Note over Process: Check if already group leader
Process ->> NewProcessGroup: ProcessGroup::new(pid, ¤t_session)
Process ->> OldProcessGroup: Remove process from old group
Process ->> NewProcessGroup: Add process to new group
Process ->> Process: Update group reference
Process -->> Process: Return new_group
Key features of process group creation:
- A process cannot create a new process group if it is already a process group leader (when
process.group().pgid() == process.pid()) - The new process group is created within the process's current session
- The process is moved from its old process group to the new one
Sources: src/process.rs(L124 - L143) tests/group.rs(L22 - L43)
Moving Between Process Groups
A process can move to a different process group within the same session by calling the move_to_group() method.
sequenceDiagram
participant Process as Process
participant DestinationProcessGroup as Destination Process Group
participant CurrentProcessGroup as Current Process Group
Process ->> Process: move_to_group(destination_group)
alt Already in the group
Process -->> Process: Return true (no action needed)
else Different session
Process -->> Process: Return false (operation not allowed)
else Move allowed
Process ->> CurrentProcessGroup: Remove process from current group
Process ->> DestinationProcessGroup: Add process to destination group
Process ->> Process: Update group reference
Process -->> Process: Return true (move successful)
end
Key constraints on process movement:
- A process can only move to a process group within the same session
- If a process is already in the specified process group, no action is taken
- The process is removed from its old process group and added to the new one
Sources: src/process.rs(L145 - L163) tests/group.rs(L77 - L100) tests/session.rs(L86 - L96)
Process Creation and Inheritance
When a new process is created using Process::fork() and then ProcessBuilder::build(), it inherits its parent's process group by default. This behavior ensures that related processes stay within the same group unless explicitly moved.
flowchart TD PP["Parent Process"] PB["ProcessBuilder"] CP["Child Process"] PPG["Parent Process Group"] PB --> CP PP --> PB PPG --> CP
Sources: src/process.rs(L285 - L332)
Resource Cleanup and Memory Management
The hierarchical structure is designed to ensure proper cleanup of resources:
- When a process moves to a different group, its reference to the old group is dropped
- If a process was the last one in a group, the group will be automatically cleaned up when all references to it are dropped
- Similarly, when a process group is removed from a session, the session will be cleaned up if it was the last group
This approach prevents memory leaks while maintaining the hierarchical relationships.
flowchart TD
subgraph subGraph1["After Move"]
GC["Garbage Collection"]
subgraph Before["Before"]
P2["Process"]
PG3["Process Group"]
S2["Session"]
PG4["Process Group (empty)"]
P1["Process"]
PG1["Process Group"]
S["Session"]
PG2["Process Group"]
end
end
P1 --> PG1
P2 --> PG3
PG1 --> S
PG2 --> S
PG3 --> S2
PG4 --> GC
PG4 --> S2
Sources: tests/group.rs(L54 - L65) tests/group.rs(L102 - L113) tests/session.rs(L52 - L64)
Example: Moving Processes Between Groups
Here's a practical example of how process groups can be manipulated in code:
sequenceDiagram
participant Parent as Parent
participant Child1 as Child1
participant Child2 as Child2
participant Group1 as Group1
participant Group2 as Group2
Parent ->> Child1: new_child()
Child1 ->> Group1: create_group()
Parent ->> Child2: new_child()
Child2 ->> Group2: create_group()
Child2 ->> Child2: move_to_group(Group1)
Note over Child2,Group1: Child2 now belongs to Group1
Note over Group2: Group2 is now empty
This diagram illustrates the flow from tests where:
- A parent process creates two child processes
- Each child creates its own process group
- The second child moves to the first child's group
- The second child's original group becomes empty
Sources: tests/group.rs(L77 - L100)
Constraints and Rules Summary
The following rules govern process movement in the hierarchy:
| Operation | Condition | Result |
|---|---|---|
| Create session | Process is already a session leader | Operation fails, returnsNone |
| Create session | Process is not a session leader | New session and group created, process moved |
| Create group | Process is already a group leader | Operation fails, returnsNone |
| Create group | Process is not a group leader | New group created, process moved |
| Move to group | Target group in different session | Operation fails, returnsfalse |
| Move to group | Target group in same session | Process moved, returnstrue |
| Move to group | Already in target group | No action, returnstrue |
Sources: src/process.rs(L100 - L163) tests/group.rs(L44 - L52) tests/session.rs(L46 - L48)
Practical Implications
Understanding the hierarchical structure and movement capabilities in axprocess allows for effective process management:
- Related processes can be grouped together for collective management
- Session boundaries provide isolation between unrelated process groups
- Process movement enables dynamic reorganization of processes based on their relationships or roles
- The hierarchy forms the foundation for implementing job control and terminal management
By organizing processes into groups and sessions, the system can implement sophisticated process management features commonly found in Unix-like operating systems.
Sources: src/process.rs(L83 - L164) src/process_group.rs(L1 - L56) src/session.rs(L1 - L45)