mirror of
https://github.com/RGBCube/serenity
synced 2025-05-20 18:15:07 +00:00
Kernel: Add /proc/{pid}/children to ProcFS
This exposes the child processes for a process as a directory of symlinks to the respective /proc entries for each child. This makes for an easier and possibly more efficient way to find and count a process's children. Previously the only method was to parse the entire /proc/all JSON file.
This commit is contained in:
parent
222079cd80
commit
d951e2ca97
7 changed files with 73 additions and 0 deletions
|
@ -295,6 +295,8 @@ ErrorOr<NonnullRefPtr<Inode>> ProcFSProcessDirectoryInode::lookup(StringView nam
|
||||||
return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions, associated_pid()));
|
return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions, associated_pid()));
|
||||||
if (name == "stacks"sv)
|
if (name == "stacks"sv)
|
||||||
return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::Stacks, associated_pid()));
|
return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::Stacks, associated_pid()));
|
||||||
|
if (name == "children"sv)
|
||||||
|
return TRY(ProcFSProcessSubDirectoryInode::try_create(procfs(), SegmentedProcFSIndex::ProcessSubDirectory::Children, associated_pid()));
|
||||||
if (name == "unveil"sv)
|
if (name == "unveil"sv)
|
||||||
return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::Unveil, associated_pid()));
|
return TRY(ProcFSProcessPropertyInode::try_create_for_pid_property(procfs(), SegmentedProcFSIndex::MainProcessProperty::Unveil, associated_pid()));
|
||||||
if (name == "pledge"sv)
|
if (name == "pledge"sv)
|
||||||
|
@ -367,6 +369,8 @@ ErrorOr<void> ProcFSProcessSubDirectoryInode::traverse_as_directory(Function<Err
|
||||||
return process->traverse_file_descriptions_directory(procfs().fsid(), move(callback));
|
return process->traverse_file_descriptions_directory(procfs().fsid(), move(callback));
|
||||||
case SegmentedProcFSIndex::ProcessSubDirectory::Stacks:
|
case SegmentedProcFSIndex::ProcessSubDirectory::Stacks:
|
||||||
return process->traverse_stacks_directory(procfs().fsid(), move(callback));
|
return process->traverse_stacks_directory(procfs().fsid(), move(callback));
|
||||||
|
case SegmentedProcFSIndex::ProcessSubDirectory::Children:
|
||||||
|
return process->traverse_children_directory(procfs().fsid(), move(callback));
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -384,6 +388,8 @@ ErrorOr<NonnullRefPtr<Inode>> ProcFSProcessSubDirectoryInode::lookup(StringView
|
||||||
return process->lookup_file_descriptions_directory(procfs(), name);
|
return process->lookup_file_descriptions_directory(procfs(), name);
|
||||||
case SegmentedProcFSIndex::ProcessSubDirectory::Stacks:
|
case SegmentedProcFSIndex::ProcessSubDirectory::Stacks:
|
||||||
return process->lookup_stacks_directory(procfs(), name);
|
return process->lookup_stacks_directory(procfs(), name);
|
||||||
|
case SegmentedProcFSIndex::ProcessSubDirectory::Children:
|
||||||
|
return process->lookup_children_directory(procfs(), name);
|
||||||
default:
|
default:
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -401,6 +407,10 @@ ErrorOr<NonnullRefPtr<ProcFSProcessPropertyInode>> ProcFSProcessPropertyInode::t
|
||||||
{
|
{
|
||||||
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, main_property_type, pid));
|
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, main_property_type, pid));
|
||||||
}
|
}
|
||||||
|
ErrorOr<NonnullRefPtr<ProcFSProcessPropertyInode>> ProcFSProcessPropertyInode::try_create_for_child_process_link(ProcFS const& procfs, ProcessID child_pid, ProcessID pid)
|
||||||
|
{
|
||||||
|
return adopt_nonnull_ref_or_enomem(new (nothrow) ProcFSProcessPropertyInode(procfs, child_pid, pid));
|
||||||
|
}
|
||||||
|
|
||||||
ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, SegmentedProcFSIndex::MainProcessProperty main_property_type, ProcessID pid)
|
ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, SegmentedProcFSIndex::MainProcessProperty main_property_type, ProcessID pid)
|
||||||
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(pid, main_property_type))
|
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(pid, main_property_type))
|
||||||
|
@ -423,6 +433,13 @@ ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, Thr
|
||||||
m_possible_data.property_index = thread_stack_index.value();
|
m_possible_data.property_index = thread_stack_index.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProcFSProcessPropertyInode::ProcFSProcessPropertyInode(ProcFS const& procfs, ProcessID child_pid, ProcessID pid)
|
||||||
|
: ProcFSProcessAssociatedInode(procfs, pid, SegmentedProcFSIndex::build_segmented_index_for_children(pid, child_pid))
|
||||||
|
, m_parent_sub_directory_type(SegmentedProcFSIndex::ProcessSubDirectory::Children)
|
||||||
|
{
|
||||||
|
m_possible_data.property_index = child_pid.value();
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<void> ProcFSProcessPropertyInode::attach(OpenFileDescription& description)
|
ErrorOr<void> ProcFSProcessPropertyInode::attach(OpenFileDescription& description)
|
||||||
{
|
{
|
||||||
return refresh_data(description);
|
return refresh_data(description);
|
||||||
|
@ -440,6 +457,8 @@ static mode_t determine_procfs_process_inode_mode(SegmentedProcFSIndex::ProcessS
|
||||||
return S_IFLNK | 0400;
|
return S_IFLNK | 0400;
|
||||||
if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Stacks)
|
if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Stacks)
|
||||||
return S_IFREG | 0400;
|
return S_IFREG | 0400;
|
||||||
|
if (parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Children)
|
||||||
|
return S_IFLNK | 0400;
|
||||||
VERIFY(parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved);
|
VERIFY(parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved);
|
||||||
if (main_property == SegmentedProcFSIndex::MainProcessProperty::BinaryLink)
|
if (main_property == SegmentedProcFSIndex::MainProcessProperty::BinaryLink)
|
||||||
return S_IFLNK | 0777;
|
return S_IFLNK | 0777;
|
||||||
|
@ -531,6 +550,10 @@ ErrorOr<void> ProcFSProcessPropertyInode::try_to_acquire_data(Process& process,
|
||||||
TRY(process.procfs_get_thread_stack(m_possible_data.property_index, builder));
|
TRY(process.procfs_get_thread_stack(m_possible_data.property_index, builder));
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
if (m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Children) {
|
||||||
|
TRY(process.procfs_get_child_proccess_link(m_possible_data.property_index, builder));
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
VERIFY(m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved);
|
VERIFY(m_parent_sub_directory_type == SegmentedProcFSIndex::ProcessSubDirectory::Reserved);
|
||||||
switch (m_possible_data.property_type) {
|
switch (m_possible_data.property_type) {
|
||||||
|
|
|
@ -172,11 +172,14 @@ public:
|
||||||
static ErrorOr<NonnullRefPtr<ProcFSProcessPropertyInode>> try_create_for_file_description_link(ProcFS const&, unsigned, ProcessID);
|
static ErrorOr<NonnullRefPtr<ProcFSProcessPropertyInode>> try_create_for_file_description_link(ProcFS const&, unsigned, ProcessID);
|
||||||
static ErrorOr<NonnullRefPtr<ProcFSProcessPropertyInode>> try_create_for_thread_stack(ProcFS const&, ThreadID, ProcessID);
|
static ErrorOr<NonnullRefPtr<ProcFSProcessPropertyInode>> try_create_for_thread_stack(ProcFS const&, ThreadID, ProcessID);
|
||||||
static ErrorOr<NonnullRefPtr<ProcFSProcessPropertyInode>> try_create_for_pid_property(ProcFS const&, SegmentedProcFSIndex::MainProcessProperty, ProcessID);
|
static ErrorOr<NonnullRefPtr<ProcFSProcessPropertyInode>> try_create_for_pid_property(ProcFS const&, SegmentedProcFSIndex::MainProcessProperty, ProcessID);
|
||||||
|
static ErrorOr<NonnullRefPtr<ProcFSProcessPropertyInode>> try_create_for_child_process_link(ProcFS const&, ProcessID, ProcessID);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProcFSProcessPropertyInode(ProcFS const&, SegmentedProcFSIndex::MainProcessProperty, ProcessID);
|
ProcFSProcessPropertyInode(ProcFS const&, SegmentedProcFSIndex::MainProcessProperty, ProcessID);
|
||||||
ProcFSProcessPropertyInode(ProcFS const&, ThreadID, ProcessID);
|
ProcFSProcessPropertyInode(ProcFS const&, ThreadID, ProcessID);
|
||||||
ProcFSProcessPropertyInode(ProcFS const&, unsigned, ProcessID);
|
ProcFSProcessPropertyInode(ProcFS const&, unsigned, ProcessID);
|
||||||
|
ProcFSProcessPropertyInode(ProcFS const&, ProcessID, ProcessID);
|
||||||
|
|
||||||
// ^Inode
|
// ^Inode
|
||||||
virtual ErrorOr<void> attach(OpenFileDescription& description) override;
|
virtual ErrorOr<void> attach(OpenFileDescription& description) override;
|
||||||
virtual void did_seek(OpenFileDescription&, off_t) override;
|
virtual void did_seek(OpenFileDescription&, off_t) override;
|
||||||
|
|
|
@ -591,6 +591,9 @@ public:
|
||||||
ErrorOr<size_t> procfs_get_file_description_link(unsigned fd, KBufferBuilder& builder) const;
|
ErrorOr<size_t> procfs_get_file_description_link(unsigned fd, KBufferBuilder& builder) const;
|
||||||
ErrorOr<void> traverse_file_descriptions_directory(FileSystemID, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const;
|
ErrorOr<void> traverse_file_descriptions_directory(FileSystemID, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const;
|
||||||
ErrorOr<NonnullRefPtr<Inode>> lookup_file_descriptions_directory(ProcFS const&, StringView name) const;
|
ErrorOr<NonnullRefPtr<Inode>> lookup_file_descriptions_directory(ProcFS const&, StringView name) const;
|
||||||
|
ErrorOr<NonnullRefPtr<Inode>> lookup_children_directory(ProcFS const&, StringView name) const;
|
||||||
|
ErrorOr<void> traverse_children_directory(FileSystemID, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const;
|
||||||
|
ErrorOr<size_t> procfs_get_child_proccess_link(ProcessID child_pid, KBufferBuilder& builder) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline PerformanceEventBuffer* current_perf_events_buffer()
|
inline PerformanceEventBuffer* current_perf_events_buffer()
|
||||||
|
|
|
@ -67,6 +67,11 @@ InodeIndex build_segmented_index_for_file_description(ProcessID pid, unsigned fd
|
||||||
return build_segmented_index_with_unknown_property(pid, ProcessSubDirectory::OpenFileDescriptions, fd);
|
return build_segmented_index_with_unknown_property(pid, ProcessSubDirectory::OpenFileDescriptions, fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InodeIndex build_segmented_index_for_children(ProcessID pid, ProcessID child_pid)
|
||||||
|
{
|
||||||
|
return build_segmented_index_with_unknown_property(pid, ProcessSubDirectory::Children, child_pid.value());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static size_t s_allocate_global_inode_index()
|
static size_t s_allocate_global_inode_index()
|
||||||
|
|
|
@ -36,6 +36,7 @@ enum class ProcessSubDirectory {
|
||||||
Reserved = 0,
|
Reserved = 0,
|
||||||
OpenFileDescriptions = 1,
|
OpenFileDescriptions = 1,
|
||||||
Stacks = 2,
|
Stacks = 2,
|
||||||
|
Children = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
void read_segments(u32& primary, ProcessSubDirectory& sub_directory, MainProcessProperty& property);
|
void read_segments(u32& primary, ProcessSubDirectory& sub_directory, MainProcessProperty& property);
|
||||||
|
@ -45,6 +46,8 @@ InodeIndex build_segmented_index_for_main_property(ProcessID, ProcessSubDirector
|
||||||
InodeIndex build_segmented_index_for_main_property_in_pid_directory(ProcessID, MainProcessProperty property);
|
InodeIndex build_segmented_index_for_main_property_in_pid_directory(ProcessID, MainProcessProperty property);
|
||||||
InodeIndex build_segmented_index_for_thread_stack(ProcessID, ThreadID);
|
InodeIndex build_segmented_index_for_thread_stack(ProcessID, ThreadID);
|
||||||
InodeIndex build_segmented_index_for_file_description(ProcessID, unsigned);
|
InodeIndex build_segmented_index_for_file_description(ProcessID, unsigned);
|
||||||
|
InodeIndex build_segmented_index_for_children(ProcessID, ProcessID);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class ProcFSComponentRegistry {
|
class ProcFSComponentRegistry {
|
||||||
|
|
|
@ -55,6 +55,7 @@ ErrorOr<void> Process::ProcessProcFSTraits::traverse_as_directory(FileSystemID f
|
||||||
TRY(callback({ "..", { fsid, ProcFSComponentRegistry::the().root_directory().component_index() }, DT_DIR }));
|
TRY(callback({ "..", { fsid, ProcFSComponentRegistry::the().root_directory().component_index() }, DT_DIR }));
|
||||||
TRY(callback({ "fd", { fsid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(process->pid(), SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions) }, DT_DIR }));
|
TRY(callback({ "fd", { fsid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(process->pid(), SegmentedProcFSIndex::ProcessSubDirectory::OpenFileDescriptions) }, DT_DIR }));
|
||||||
TRY(callback({ "stacks", { fsid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(process->pid(), SegmentedProcFSIndex::ProcessSubDirectory::Stacks) }, DT_DIR }));
|
TRY(callback({ "stacks", { fsid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(process->pid(), SegmentedProcFSIndex::ProcessSubDirectory::Stacks) }, DT_DIR }));
|
||||||
|
TRY(callback({ "children", { fsid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(process->pid(), SegmentedProcFSIndex::ProcessSubDirectory::Children) }, DT_DIR }));
|
||||||
TRY(callback({ "unveil", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(process->pid(), SegmentedProcFSIndex::MainProcessProperty::Unveil) }, DT_REG }));
|
TRY(callback({ "unveil", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(process->pid(), SegmentedProcFSIndex::MainProcessProperty::Unveil) }, DT_REG }));
|
||||||
TRY(callback({ "pledge", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(process->pid(), SegmentedProcFSIndex::MainProcessProperty::Pledge) }, DT_REG }));
|
TRY(callback({ "pledge", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(process->pid(), SegmentedProcFSIndex::MainProcessProperty::Pledge) }, DT_REG }));
|
||||||
TRY(callback({ "fds", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(process->pid(), SegmentedProcFSIndex::MainProcessProperty::OpenFileDescriptions) }, DT_DIR }));
|
TRY(callback({ "fds", { fsid, SegmentedProcFSIndex::build_segmented_index_for_main_property_in_pid_directory(process->pid(), SegmentedProcFSIndex::MainProcessProperty::OpenFileDescriptions) }, DT_DIR }));
|
||||||
|
|
|
@ -80,6 +80,41 @@ ErrorOr<NonnullRefPtr<Inode>> Process::lookup_stacks_directory(ProcFS const& pro
|
||||||
return thread_stack_inode.release_value();
|
return thread_stack_inode.release_value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ErrorOr<void> Process::traverse_children_directory(FileSystemID fsid, Function<ErrorOr<void>(FileSystem::DirectoryEntryView const&)> callback) const
|
||||||
|
{
|
||||||
|
TRY(callback({ ".", { fsid, SegmentedProcFSIndex::build_segmented_index_for_sub_directory(pid(), SegmentedProcFSIndex::ProcessSubDirectory::Children) }, 0 }));
|
||||||
|
TRY(callback({ "..", { fsid, m_procfs_traits->component_index() }, 0 }));
|
||||||
|
return Process::all_instances().with([&](auto& processes) -> ErrorOr<void> {
|
||||||
|
for (auto& process : processes) {
|
||||||
|
if (process.ppid() == pid()) {
|
||||||
|
StringBuilder builder;
|
||||||
|
builder.appendff("{}", process.pid());
|
||||||
|
TRY(callback({ builder.string_view(), { fsid, SegmentedProcFSIndex::build_segmented_index_for_children(pid(), process.pid()) }, DT_LNK }));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<NonnullRefPtr<Inode>> Process::lookup_children_directory(ProcFS const& procfs, StringView name) const
|
||||||
|
{
|
||||||
|
auto maybe_pid = name.to_uint();
|
||||||
|
if (!maybe_pid.has_value())
|
||||||
|
return ENOENT;
|
||||||
|
|
||||||
|
auto child_process = Process::from_pid(*maybe_pid);
|
||||||
|
if (!child_process || child_process->ppid() != pid())
|
||||||
|
return ENOENT;
|
||||||
|
|
||||||
|
return TRY(ProcFSProcessPropertyInode::try_create_for_child_process_link(procfs, *maybe_pid, pid()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ErrorOr<size_t> Process::procfs_get_child_proccess_link(ProcessID child_pid, KBufferBuilder& builder) const
|
||||||
|
{
|
||||||
|
TRY(builder.appendff("/proc/{}", child_pid.value()));
|
||||||
|
return builder.length();
|
||||||
|
}
|
||||||
|
|
||||||
ErrorOr<size_t> Process::procfs_get_file_description_link(unsigned fd, KBufferBuilder& builder) const
|
ErrorOr<size_t> Process::procfs_get_file_description_link(unsigned fd, KBufferBuilder& builder) const
|
||||||
{
|
{
|
||||||
auto file_description = TRY(open_file_description(fd));
|
auto file_description = TRY(open_file_description(fd));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue