Compare commits

...

11 Commits

Author SHA1 Message Date
Bananymous 762b7a4276 Userspace: Add meminfo command that parses /proc/{pid}/meminfo 2023-09-30 21:20:53 +03:00
Bananymous a511441f7e Kernel: /proc/{pid}/meminfo now reports per process memory usage 2023-09-30 21:20:18 +03:00
Bananymous cd61d710df Kernel: Add procfs that contains only pids 2023-09-30 21:19:36 +03:00
Bananymous f88ad7efcd Kernel: All process' memory areas can report their virtual mem usage 2023-09-30 21:15:46 +03:00
Bananymous 38320018dc LibC: Implement stpcpy since gcc seems to need it
gcc seems to optimize some calls to strcpy to stpcpy
2023-09-30 20:58:19 +03:00
Bananymous d883d212b1 Kernel/LibC: dirent now contains file type 2023-09-30 20:46:57 +03:00
Bananymous dedb2a2399 Kernel: RamInode verifies that you have not specified mode type
This is kinda weird behaviour, but it ensures the user cannot
create e.g. CharacterDevice with mode having IFLNK.

The Inode overrider is the only one setting the mode.
2023-09-30 20:46:57 +03:00
Bananymous 8604c55de8 Kernel: Add API for RamDirectoryInodes to delete containing inodes 2023-09-30 19:22:30 +03:00
Bananymous e949e8550c Kernel: Rework RamInode API
RamInode is now a general RamInode with no data. RamFileInode is now
a inode for regular files. This is much cleaner and more intuitive
since there is no reason for most non-regular inodes to hold data
Vector.
2023-09-30 19:22:30 +03:00
Bananymous eb5c6cf736 BAN: Remove endianness functions from Math
There is now a Endianness.h for these. The functions were super slow.
2023-09-29 19:38:07 +03:00
Bananymous 94ce2c97be Shell: Quick fix to not freeze for multiple seconds
When sync is writing to disk, it reserves whole disk to itself.
This commit makes Shell to read username only once from getpwuid().
We used to get username every time prompt was printed.
2023-09-29 19:20:48 +03:00
31 changed files with 494 additions and 117 deletions

View File

@ -102,22 +102,4 @@ namespace BAN::Math
return result; return result;
} }
template<integral T>
inline constexpr T little_endian_to_host(const uint8_t* bytes)
{
T result = 0;
for (size_t i = 0; i < sizeof(T); i++)
result |= (T)bytes[i] << (i * 8);
return result;
}
template<integral T>
inline constexpr T big_endian_to_host(const uint8_t* bytes)
{
T result = 0;
for (size_t i = 0; i < sizeof(T); i++)
result |= (T)bytes[i] << (8 * (sizeof(T) - i - 1));
return result;
}
} }

View File

@ -124,6 +124,8 @@ namespace LibELF
dprintln("Invalid program header"); dprintln("Invalid program header");
return BAN::Error::from_errno(EINVAL); return BAN::Error::from_errno(EINVAL);
} }
m_virtual_page_count += BAN::Math::div_round_up<size_t>((pheader.p_vaddr % PAGE_SIZE) + pheader.p_memsz, PAGE_SIZE);
} }
return {}; return {};

View File

@ -33,6 +33,8 @@ namespace LibELF
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> clone(Kernel::PageTable&); BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> clone(Kernel::PageTable&);
size_t virtual_page_count() const { return m_virtual_page_count; }
private: private:
LoadableELF(Kernel::PageTable&, BAN::RefPtr<Kernel::Inode>); LoadableELF(Kernel::PageTable&, BAN::RefPtr<Kernel::Inode>);
BAN::ErrorOr<void> initialize(); BAN::ErrorOr<void> initialize();
@ -42,6 +44,7 @@ namespace LibELF
Kernel::PageTable& m_page_table; Kernel::PageTable& m_page_table;
ElfNativeFileHeader m_file_header; ElfNativeFileHeader m_file_header;
BAN::Vector<ElfNativeProgramHeader> m_program_headers; BAN::Vector<ElfNativeProgramHeader> m_program_headers;
size_t m_virtual_page_count = 0;
}; };
} }

Binary file not shown.

View File

@ -24,6 +24,8 @@ set(KERNEL_SOURCES
kernel/FS/Ext2/Inode.cpp kernel/FS/Ext2/Inode.cpp
kernel/FS/Inode.cpp kernel/FS/Inode.cpp
kernel/FS/Pipe.cpp kernel/FS/Pipe.cpp
kernel/FS/ProcFS/FileSystem.cpp
kernel/FS/ProcFS/Inode.cpp
kernel/FS/RamFS/FileSystem.cpp kernel/FS/RamFS/FileSystem.cpp
kernel/FS/RamFS/Inode.cpp kernel/FS/RamFS/Inode.cpp
kernel/FS/VirtualFileSystem.cpp kernel/FS/VirtualFileSystem.cpp

View File

@ -25,9 +25,9 @@ namespace Kernel
{ {
protected: protected:
BlockDevice(mode_t mode, uid_t uid, gid_t gid) BlockDevice(mode_t mode, uid_t uid, gid_t gid)
: Device(Mode::IFBLK | mode, uid, gid) : Device(mode, uid, gid)
{ {
ASSERT(Device::mode().ifblk()); m_inode_info.mode |= Inode::Mode::IFBLK;
} }
}; };
@ -35,9 +35,9 @@ namespace Kernel
{ {
protected: protected:
CharacterDevice(mode_t mode, uid_t uid, gid_t gid) CharacterDevice(mode_t mode, uid_t uid, gid_t gid)
: Device(Mode::IFCHR | mode, uid, gid) : Device(mode, uid, gid)
{ {
ASSERT(Device::mode().ifchr()); m_inode_info.mode |= Inode::Mode::IFCHR;
} }
}; };

View File

@ -89,6 +89,7 @@ namespace Kernel
BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode(BAN::StringView); BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode(BAN::StringView);
BAN::ErrorOr<void> list_next_inodes(off_t, DirectoryEntryList*, size_t); BAN::ErrorOr<void> list_next_inodes(off_t, DirectoryEntryList*, size_t);
BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t); BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t);
BAN::ErrorOr<void> delete_inode(BAN::StringView);
// Link API // Link API
BAN::ErrorOr<BAN::String> link_target(); BAN::ErrorOr<BAN::String> link_target();
@ -104,6 +105,7 @@ namespace Kernel
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); } virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> list_next_inodes_impl(off_t, DirectoryEntryList*, size_t) { return BAN::Error::from_errno(ENOTSUP); } virtual BAN::ErrorOr<void> list_next_inodes_impl(off_t, DirectoryEntryList*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); } virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) { return BAN::Error::from_errno(ENOTSUP); }
virtual BAN::ErrorOr<void> delete_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
// Link API // Link API
virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); } virtual BAN::ErrorOr<BAN::String> link_target_impl() { return BAN::Error::from_errno(ENOTSUP); }

View File

@ -0,0 +1,26 @@
#pragma once
#include <kernel/FS/RamFS/FileSystem.h>
#include <kernel/FS/RamFS/Inode.h>
#include <kernel/Process.h>
namespace Kernel
{
class ProcFileSystem final : public RamFileSystem
{
public:
static void initialize();
static ProcFileSystem& get();
BAN::ErrorOr<void> on_process_create(Process&);
void on_process_delete(Process&);
private:
ProcFileSystem(size_t size);
private:
BAN::RefPtr<RamDirectoryInode> m_root_inode;
};
}

View File

@ -0,0 +1,44 @@
#pragma once
#include <kernel/FS/RamFS/FileSystem.h>
#include <kernel/FS/RamFS/Inode.h>
#include <kernel/Process.h>
namespace Kernel
{
class ProcPidInode final : public RamDirectoryInode
{
public:
static BAN::ErrorOr<BAN::RefPtr<ProcPidInode>> create(Process&, RamFileSystem&, mode_t, uid_t, gid_t);
~ProcPidInode() = default;
private:
ProcPidInode(Process&, RamFileSystem&, const FullInodeInfo&);
private:
Process& m_process;
};
class ProcMemInode final : public RamInode
{
public:
static BAN::ErrorOr<BAN::RefPtr<ProcMemInode>> create(Process&, RamFileSystem&, mode_t, uid_t, gid_t);
~ProcMemInode() = default;
protected:
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
// You may not write here and this is always non blocking
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override { return BAN::Error::from_errno(EINVAL); }
virtual BAN::ErrorOr<void> truncate_impl(size_t) override { return BAN::Error::from_errno(EINVAL); }
virtual bool has_data_impl() const override { return true; }
private:
ProcMemInode(Process&, RamFileSystem&, const FullInodeInfo&);
private:
Process& m_process;
};
}

View File

@ -12,7 +12,6 @@ namespace Kernel
class RamInode : public Inode class RamInode : public Inode
{ {
public: public:
static BAN::ErrorOr<BAN::RefPtr<RamInode>> create(RamFileSystem&, mode_t, uid_t, gid_t);
virtual ~RamInode() = default; virtual ~RamInode() = default;
virtual ino_t ino() const override { return m_inode_info.ino; } virtual ino_t ino() const override { return m_inode_info.ino; }
@ -31,16 +30,10 @@ namespace Kernel
void add_link() { m_inode_info.nlink++; } void add_link() { m_inode_info.nlink++; }
protected:
RamInode(RamFileSystem& fs, mode_t, uid_t, gid_t);
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override;
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
protected: protected:
struct FullInodeInfo struct FullInodeInfo
{ {
FullInodeInfo(RamFileSystem&, mode_t, uid_t, gid_t);
ino_t ino; ino_t ino;
mode_t mode; mode_t mode;
nlink_t nlink; nlink_t nlink;
@ -56,16 +49,38 @@ namespace Kernel
dev_t rdev; dev_t rdev;
}; };
RamInode(RamFileSystem& fs, const FullInodeInfo& inode_info)
: m_fs(fs)
, m_inode_info(inode_info)
{
ASSERT((inode_info.mode & Inode::Mode::TYPE_MASK) == 0);
}
protected: protected:
RamFileSystem& m_fs; RamFileSystem& m_fs;
FullInodeInfo m_inode_info; FullInodeInfo m_inode_info;
};
class RamFileInode : public RamInode
{
public:
static BAN::ErrorOr<BAN::RefPtr<RamFileInode>> create(RamFileSystem&, mode_t, uid_t, gid_t);
~RamFileInode() = default;
protected:
RamFileInode(RamFileSystem&, const FullInodeInfo&);
virtual BAN::ErrorOr<size_t> read_impl(off_t, void*, size_t) override;
virtual BAN::ErrorOr<size_t> write_impl(off_t, const void*, size_t) override;
virtual BAN::ErrorOr<void> truncate_impl(size_t) override;
private:
BAN::Vector<uint8_t> m_data; BAN::Vector<uint8_t> m_data;
friend class RamFileSystem; friend class RamFileSystem;
}; };
class RamDirectoryInode final : public RamInode class RamDirectoryInode : public RamInode
{ {
public: public:
static BAN::ErrorOr<BAN::RefPtr<RamDirectoryInode>> create(RamFileSystem&, ino_t parent, mode_t, uid_t, gid_t); static BAN::ErrorOr<BAN::RefPtr<RamDirectoryInode>> create(RamFileSystem&, ino_t parent, mode_t, uid_t, gid_t);
@ -74,12 +89,12 @@ namespace Kernel
BAN::ErrorOr<void> add_inode(BAN::StringView, BAN::RefPtr<RamInode>); BAN::ErrorOr<void> add_inode(BAN::StringView, BAN::RefPtr<RamInode>);
protected: protected:
RamDirectoryInode(RamFileSystem&, const FullInodeInfo&, ino_t parent);
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override; virtual BAN::ErrorOr<BAN::RefPtr<Inode>> find_inode_impl(BAN::StringView) override;
virtual BAN::ErrorOr<void> list_next_inodes_impl(off_t, DirectoryEntryList*, size_t) override; virtual BAN::ErrorOr<void> list_next_inodes_impl(off_t, DirectoryEntryList*, size_t) override;
virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override; virtual BAN::ErrorOr<void> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
virtual BAN::ErrorOr<void> delete_inode_impl(BAN::StringView) override;
private:
RamDirectoryInode(RamFileSystem&, ino_t parent, mode_t, uid_t, gid_t);
private: private:
static constexpr size_t m_name_max = NAME_MAX; static constexpr size_t m_name_max = NAME_MAX;
@ -88,11 +103,12 @@ namespace Kernel
char name[m_name_max + 1]; char name[m_name_max + 1];
size_t name_len = 0; size_t name_len = 0;
ino_t ino; ino_t ino;
uint8_t type;
}; };
private: private:
BAN::Vector<Entry> m_entries; BAN::Vector<Entry> m_entries;
ino_t m_parent; const ino_t m_parent;
friend class RamFileSystem; friend class RamFileSystem;
}; };
@ -111,7 +127,7 @@ namespace Kernel
virtual BAN::ErrorOr<BAN::String> link_target_impl() override; virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
private: private:
RamSymlinkInode(RamFileSystem&, mode_t, uid_t, gid_t); RamSymlinkInode(RamFileSystem&, const FullInodeInfo&, BAN::String&&);
private: private:
BAN::String m_target; BAN::String m_target;

View File

@ -37,6 +37,8 @@ namespace Kernel
size_t size() const { return m_size; } size_t size() const { return m_size; }
vaddr_t vaddr() const { return m_vaddr; } vaddr_t vaddr() const { return m_vaddr; }
size_t virtual_page_count() const { return BAN::Math::div_round_up<size_t>(m_size, PAGE_SIZE); }
// Returns error if no memory was available // Returns error if no memory was available
// Returns true if page was succesfully allocated // Returns true if page was succesfully allocated
// Returns false if page was already allocated // Returns false if page was already allocated

View File

@ -13,6 +13,7 @@
#include <kernel/Terminal/TTY.h> #include <kernel/Terminal/TTY.h>
#include <kernel/Thread.h> #include <kernel/Thread.h>
#include <sys/banan-os.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <termios.h> #include <termios.h>
@ -138,6 +139,8 @@ namespace Kernel
PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::kernel(); } PageTable& page_table() { return m_page_table ? *m_page_table : PageTable::kernel(); }
void get_meminfo(proc_meminfo_t*) const;
bool is_userspace() const { return m_is_userspace; } bool is_userspace() const { return m_is_userspace; }
const userspace_info_t& userspace_info() const { return m_userspace_info; } const userspace_info_t& userspace_info() const { return m_userspace_info; }

View File

@ -83,6 +83,8 @@ namespace Kernel
bool is_userspace() const { return m_is_userspace; } bool is_userspace() const { return m_is_userspace; }
size_t virtual_page_count() const { return m_stack->size() / PAGE_SIZE; }
#if __enable_sse #if __enable_sse
void save_sse() { asm volatile("fxsave %0" :: "m"(m_sse_storage)); } void save_sse() { asm volatile("fxsave %0" :: "m"(m_sse_storage)); }
void load_sse() { asm volatile("fxrstor %0" :: "m"(m_sse_storage)); } void load_sse() { asm volatile("fxrstor %0" :: "m"(m_sse_storage)); }

View File

@ -5,7 +5,7 @@ namespace Kernel
{ {
Device::Device(mode_t mode, uid_t uid, gid_t gid) Device::Device(mode_t mode, uid_t uid, gid_t gid)
: RamInode(DevFileSystem::get(), mode, uid, gid) : RamInode(DevFileSystem::get(), FullInodeInfo(DevFileSystem::get(), mode, uid, gid))
{ } { }
} }

View File

@ -19,7 +19,7 @@ namespace Kernel
s_instance = new DevFileSystem(1024 * 1024); s_instance = new DevFileSystem(1024 * 1024);
ASSERT(s_instance); ASSERT(s_instance);
auto root_inode = MUST(RamDirectoryInode::create(*s_instance, 0, Inode::Mode::IFDIR | 0755, 0, 0)); auto root_inode = MUST(RamDirectoryInode::create(*s_instance, 0, 0755, 0, 0));
MUST(s_instance->set_root_inode(root_inode)); MUST(s_instance->set_root_inode(root_inode));
s_instance->add_device("null", MUST(NullDevice::create(0666, 0, 0))); s_instance->add_device("null", MUST(NullDevice::create(0666, 0, 0)));

View File

@ -291,6 +291,7 @@ namespace Kernel
if (entry.inode) if (entry.inode)
{ {
ptr->dirent.d_ino = entry.inode; ptr->dirent.d_ino = entry.inode;
ptr->dirent.d_type = entry.file_type;
ptr->rec_len = sizeof(DirectoryEntry) + entry.name_len + 1; ptr->rec_len = sizeof(DirectoryEntry) + entry.name_len + 1;
memcpy(ptr->dirent.d_name, entry.name, entry.name_len); memcpy(ptr->dirent.d_name, entry.name, entry.name_len);
ptr->dirent.d_name[entry.name_len] = '\0'; ptr->dirent.d_name[entry.name_len] = '\0';

View File

@ -84,6 +84,15 @@ namespace Kernel
return create_file_impl(name, mode, uid, gid); return create_file_impl(name, mode, uid, gid);
} }
BAN::ErrorOr<void> Inode::delete_inode(BAN::StringView name)
{
LockGuard _(m_lock);
Thread::TerminateBlocker blocker(Thread::current());
if (!mode().ifdir())
return BAN::Error::from_errno(ENOTDIR);
return delete_inode_impl(name);
}
BAN::ErrorOr<BAN::String> Inode::link_target() BAN::ErrorOr<BAN::String> Inode::link_target()
{ {
LockGuard _(m_lock); LockGuard _(m_lock);

View File

@ -0,0 +1,46 @@
#include <kernel/FS/ProcFS/FileSystem.h>
#include <kernel/FS/ProcFS/Inode.h>
#include <kernel/FS/RamFS/Inode.h>
#include <kernel/LockGuard.h>
namespace Kernel
{
static ProcFileSystem* s_instance = nullptr;
void ProcFileSystem::initialize()
{
ASSERT(s_instance == nullptr);
s_instance = new ProcFileSystem(1024 * 1024);
ASSERT(s_instance);
s_instance->m_root_inode = MUST(RamDirectoryInode::create(*s_instance, 0, 0555, 0, 0));
MUST(s_instance->set_root_inode(s_instance->m_root_inode));
}
ProcFileSystem& ProcFileSystem::get()
{
ASSERT(s_instance);
return *s_instance;
}
ProcFileSystem::ProcFileSystem(size_t size)
: RamFileSystem(size)
{
}
BAN::ErrorOr<void> ProcFileSystem::on_process_create(Process& process)
{
auto path = BAN::String::formatted("{}", process.pid());
auto inode = TRY(ProcPidInode::create(process, *this, 0555, 0, 0));
TRY(m_root_inode->add_inode(path, inode));
return {};
}
void ProcFileSystem::on_process_delete(Process& process)
{
auto path = BAN::String::formatted("{}", process.pid());
MUST(m_root_inode->delete_inode(path));
}
}

View File

@ -0,0 +1,58 @@
#include <kernel/FS/ProcFS/Inode.h>
namespace Kernel
{
BAN::ErrorOr<BAN::RefPtr<ProcPidInode>> ProcPidInode::create(Process& process, RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
{
FullInodeInfo inode_info(fs, mode, uid, gid);
auto* inode_ptr = new ProcPidInode(process, fs, inode_info);
if (inode_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
auto inode = BAN::RefPtr<ProcPidInode>::adopt(inode_ptr);
TRY(inode->add_inode("meminfo"sv, MUST(ProcMemInode::create(process, fs, 0755, 0, 0))));
return inode;
}
ProcPidInode::ProcPidInode(Process& process, RamFileSystem& fs, const FullInodeInfo& inode_info)
: RamDirectoryInode(fs, inode_info, fs.root_inode()->ino())
, m_process(process)
{
}
BAN::ErrorOr<BAN::RefPtr<ProcMemInode>> ProcMemInode::create(Process& process, RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
{
FullInodeInfo inode_info(fs, mode, uid, gid);
auto* inode_ptr = new ProcMemInode(process, fs, inode_info);
if (inode_ptr == nullptr)
return BAN::Error::from_errno(ENOMEM);
return BAN::RefPtr<ProcMemInode>::adopt(inode_ptr);
}
ProcMemInode::ProcMemInode(Process& process, RamFileSystem& fs, const FullInodeInfo& inode_info)
: RamInode(fs, inode_info)
, m_process(process)
{
m_inode_info.mode |= Inode::Mode::IFREG;
}
BAN::ErrorOr<size_t> ProcMemInode::read_impl(off_t offset, void* buffer, size_t buffer_size)
{
ASSERT(offset >= 0);
if ((size_t)offset >= sizeof(proc_meminfo_t))
return 0;
proc_meminfo_t meminfo;
m_process.get_meminfo(&meminfo);
size_t bytes = BAN::Math::min<size_t>(buffer_size, sizeof(meminfo) - offset);
memcpy(buffer, &meminfo, bytes);
return bytes;
}
}

View File

@ -5,42 +5,50 @@
namespace Kernel namespace Kernel
{ {
/* RamInode::FullInodeInfo::FullInodeInfo(RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
RAM INODE
*/
BAN::ErrorOr<BAN::RefPtr<RamInode>> RamInode::create(RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
{
ASSERT(Mode(mode).ifreg());
auto* ram_inode = new RamInode(fs, mode, uid, gid);
if (ram_inode == nullptr)
return BAN::Error::from_errno(ENOMEM);
return BAN::RefPtr<RamInode>::adopt(ram_inode);
}
RamInode::RamInode(RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
: m_fs(fs)
{ {
timespec current_time = SystemTimer::get().real_time(); timespec current_time = SystemTimer::get().real_time();
m_inode_info.ino = fs.next_ino(); this->ino = fs.next_ino();
m_inode_info.mode = mode; this->mode = mode;
m_inode_info.nlink = 1; this->nlink = 1;
m_inode_info.uid = uid; this->uid = uid;
m_inode_info.gid = gid; this->gid = gid;
m_inode_info.size = 0; this->size = 0;
m_inode_info.atime = current_time; this->atime = current_time;
m_inode_info.mtime = current_time; this->mtime = current_time;
m_inode_info.ctime = current_time; this->ctime = current_time;
m_inode_info.blksize = fs.blksize(); this->blksize = fs.blksize();
m_inode_info.blocks = 0; this->blocks = 0;
m_inode_info.dev = 0;
m_inode_info.rdev = 0; // TODO
this->dev = 0;
this->rdev = 0;
} }
BAN::ErrorOr<size_t> RamInode::read_impl(off_t offset, void* buffer, size_t bytes) /*
RAM FILE INODE
*/
BAN::ErrorOr<BAN::RefPtr<RamFileInode>> RamFileInode::create(RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
{
FullInodeInfo inode_info(fs, mode, uid, gid);
auto* ram_inode = new RamFileInode(fs, inode_info);
if (ram_inode == nullptr)
return BAN::Error::from_errno(ENOMEM);
return BAN::RefPtr<RamFileInode>::adopt(ram_inode);
}
RamFileInode::RamFileInode(RamFileSystem& fs, const FullInodeInfo& inode_info)
: RamInode(fs, inode_info)
{
m_inode_info.mode |= Inode::Mode::IFREG;
}
BAN::ErrorOr<size_t> RamFileInode::read_impl(off_t offset, void* buffer, size_t bytes)
{ {
ASSERT(offset >= 0); ASSERT(offset >= 0);
if (offset >= size()) if (offset >= size())
@ -50,7 +58,7 @@ namespace Kernel
return to_copy; return to_copy;
} }
BAN::ErrorOr<size_t> RamInode::write_impl(off_t offset, const void* buffer, size_t bytes) BAN::ErrorOr<size_t> RamFileInode::write_impl(off_t offset, const void* buffer, size_t bytes)
{ {
ASSERT(offset >= 0); ASSERT(offset >= 0);
if (offset + bytes > (size_t)size()) if (offset + bytes > (size_t)size())
@ -59,7 +67,7 @@ namespace Kernel
return bytes; return bytes;
} }
BAN::ErrorOr<void> RamInode::truncate_impl(size_t new_size) BAN::ErrorOr<void> RamFileInode::truncate_impl(size_t new_size)
{ {
TRY(m_data.resize(new_size, 0)); TRY(m_data.resize(new_size, 0));
m_inode_info.size = m_data.size(); m_inode_info.size = m_data.size();
@ -75,30 +83,31 @@ namespace Kernel
BAN::ErrorOr<BAN::RefPtr<RamDirectoryInode>> RamDirectoryInode::create(RamFileSystem& fs, ino_t parent, mode_t mode, uid_t uid, gid_t gid) BAN::ErrorOr<BAN::RefPtr<RamDirectoryInode>> RamDirectoryInode::create(RamFileSystem& fs, ino_t parent, mode_t mode, uid_t uid, gid_t gid)
{ {
ASSERT(Mode(mode).ifdir()); FullInodeInfo inode_info(fs, mode, uid, gid);
auto* ram_inode = new RamDirectoryInode(fs, parent, mode, uid, gid);
// "." links to this
inode_info.nlink++;
// ".." links to this or parent
if (parent)
TRY(fs.get_inode(parent))->add_link();
else
{
inode_info.nlink++;
parent = inode_info.ino;
}
auto* ram_inode = new RamDirectoryInode(fs, inode_info, parent);
if (ram_inode == nullptr) if (ram_inode == nullptr)
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);
return BAN::RefPtr<RamDirectoryInode>::adopt(ram_inode); return BAN::RefPtr<RamDirectoryInode>::adopt(ram_inode);
} }
RamDirectoryInode::RamDirectoryInode(RamFileSystem& fs, ino_t parent, mode_t mode, uid_t uid, gid_t gid) RamDirectoryInode::RamDirectoryInode(RamFileSystem& fs, const FullInodeInfo& inode_info, ino_t parent)
: RamInode(fs, mode, uid, gid) : RamInode(fs, inode_info)
, m_parent(parent)
{ {
// "." links to this m_inode_info.mode |= Inode::Mode::IFDIR;
m_inode_info.nlink++;
// ".." links to this, if there is no parent
if (parent == 0)
{
m_inode_info.nlink++;
m_parent = ino();
}
else
{
MUST(fs.get_inode(parent))->add_link();
m_parent = parent;
}
} }
BAN::ErrorOr<BAN::RefPtr<Inode>> RamDirectoryInode::find_inode_impl(BAN::StringView name) BAN::ErrorOr<BAN::RefPtr<Inode>> RamDirectoryInode::find_inode_impl(BAN::StringView name)
@ -151,6 +160,7 @@ namespace Kernel
// "." // "."
{ {
ptr->dirent.d_ino = ino(); ptr->dirent.d_ino = ino();
ptr->dirent.d_type = DT_DIR;
ptr->rec_len = sizeof(DirectoryEntry) + 2; ptr->rec_len = sizeof(DirectoryEntry) + 2;
strcpy(ptr->dirent.d_name, "."); strcpy(ptr->dirent.d_name, ".");
ptr = ptr->next(); ptr = ptr->next();
@ -159,6 +169,7 @@ namespace Kernel
// ".." // ".."
{ {
ptr->dirent.d_ino = m_parent; ptr->dirent.d_ino = m_parent;
ptr->dirent.d_type = DT_DIR;
ptr->rec_len = sizeof(DirectoryEntry) + 3; ptr->rec_len = sizeof(DirectoryEntry) + 3;
strcpy(ptr->dirent.d_name, ".."); strcpy(ptr->dirent.d_name, "..");
ptr = ptr->next(); ptr = ptr->next();
@ -167,6 +178,7 @@ namespace Kernel
for (auto& entry : m_entries) for (auto& entry : m_entries)
{ {
ptr->dirent.d_ino = entry.ino; ptr->dirent.d_ino = entry.ino;
ptr->dirent.d_type = entry.type;
ptr->rec_len = sizeof(DirectoryEntry) + entry.name_len + 1; ptr->rec_len = sizeof(DirectoryEntry) + entry.name_len + 1;
strcpy(ptr->dirent.d_name, entry.name); strcpy(ptr->dirent.d_name, entry.name);
ptr = ptr->next(); ptr = ptr->next();
@ -181,7 +193,7 @@ namespace Kernel
{ {
BAN::RefPtr<RamInode> inode; BAN::RefPtr<RamInode> inode;
if (Mode(mode).ifreg()) if (Mode(mode).ifreg())
inode = TRY(RamInode::create(m_fs, mode, uid, gid)); inode = TRY(RamFileInode::create(m_fs, mode, uid, gid));
else if (Mode(mode).ifdir()) else if (Mode(mode).ifdir())
inode = TRY(RamDirectoryInode::create(m_fs, ino(), mode, uid, gid)); inode = TRY(RamDirectoryInode::create(m_fs, ino(), mode, uid, gid));
else else
@ -192,6 +204,25 @@ namespace Kernel
return {}; return {};
} }
static uint8_t get_type(Inode::Mode mode)
{
if (mode.ifreg())
return DT_REG;
if (mode.ifdir())
return DT_DIR;
if (mode.ifchr())
return DT_CHR;
if (mode.ifblk())
return DT_BLK;
if (mode.ififo())
return DT_FIFO;
if (mode.ifsock())
return DT_SOCK;
if (mode.iflnk())
return DT_LNK;
return DT_UNKNOWN;
}
BAN::ErrorOr<void> RamDirectoryInode::add_inode(BAN::StringView name, BAN::RefPtr<RamInode> inode) BAN::ErrorOr<void> RamDirectoryInode::add_inode(BAN::StringView name, BAN::RefPtr<RamInode> inode)
{ {
if (name.size() > m_name_max) if (name.size() > m_name_max)
@ -206,6 +237,7 @@ namespace Kernel
strcpy(entry.name, name.data()); strcpy(entry.name, name.data());
entry.name_len = name.size(); entry.name_len = name.size();
entry.ino = inode->ino(); entry.ino = inode->ino();
entry.type = get_type(inode->mode());
if (auto ret = m_fs.add_inode(inode); ret.is_error()) if (auto ret = m_fs.add_inode(inode); ret.is_error())
{ {
@ -216,26 +248,44 @@ namespace Kernel
return {}; return {};
} }
BAN::ErrorOr<void> RamDirectoryInode::delete_inode_impl(BAN::StringView name)
{
for (size_t i = 0; i < m_entries.size(); i++)
{
if (name == m_entries[i].name)
{
m_entries.remove(i);
return {};
}
}
return BAN::Error::from_errno(ENOENT);
}
/* /*
RAM SYMLINK INODE RAM SYMLINK INODE
*/ */
BAN::ErrorOr<BAN::RefPtr<RamSymlinkInode>> RamSymlinkInode::create(RamFileSystem& fs, BAN::StringView target, mode_t mode, uid_t uid, gid_t gid) BAN::ErrorOr<BAN::RefPtr<RamSymlinkInode>> RamSymlinkInode::create(RamFileSystem& fs, BAN::StringView target_sv, mode_t mode, uid_t uid, gid_t gid)
{ {
ASSERT(Mode(mode).iflnk()); FullInodeInfo inode_info(fs, mode, uid, gid);
auto* ram_inode = new RamSymlinkInode(fs, mode, uid, gid);
BAN::String target_str;
TRY(target_str.append(target_sv));
auto* ram_inode = new RamSymlinkInode(fs, inode_info, BAN::move(target_str));
if (ram_inode == nullptr) if (ram_inode == nullptr)
return BAN::Error::from_errno(ENOMEM); return BAN::Error::from_errno(ENOMEM);
auto ref_ptr = BAN::RefPtr<RamSymlinkInode>::adopt(ram_inode); return BAN::RefPtr<RamSymlinkInode>::adopt(ram_inode);
TRY(ref_ptr->set_link_target(target));
return ref_ptr;
} }
RamSymlinkInode::RamSymlinkInode(RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid) RamSymlinkInode::RamSymlinkInode(RamFileSystem& fs, const FullInodeInfo& inode_info, BAN::String&& target)
: RamInode(fs, mode, uid, gid) : RamInode(fs, inode_info)
{ } , m_target(BAN::move(target))
{
m_inode_info.mode |= Inode::Mode::IFLNK;
}
BAN::ErrorOr<BAN::String> RamSymlinkInode::link_target_impl() BAN::ErrorOr<BAN::String> RamSymlinkInode::link_target_impl()
{ {

View File

@ -2,6 +2,7 @@
#include <BAN/StringView.h> #include <BAN/StringView.h>
#include <kernel/FS/DevFS/FileSystem.h> #include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/Ext2/FileSystem.h> #include <kernel/FS/Ext2/FileSystem.h>
#include <kernel/FS/ProcFS/FileSystem.h>
#include <kernel/FS/RamFS/FileSystem.h> #include <kernel/FS/RamFS/FileSystem.h>
#include <kernel/FS/RamFS/Inode.h> #include <kernel/FS/RamFS/Inode.h>
#include <kernel/FS/VirtualFileSystem.h> #include <kernel/FS/VirtualFileSystem.h>
@ -26,14 +27,12 @@ namespace Kernel
s_instance->m_root_fs = MUST(Ext2FS::create(*(Partition*)partition_inode.ptr())); s_instance->m_root_fs = MUST(Ext2FS::create(*(Partition*)partition_inode.ptr()));
Credentials root_creds { 0, 0, 0, 0 }; Credentials root_creds { 0, 0, 0, 0 };
MUST(s_instance->mount(root_creds, &DevFileSystem::get(), "/dev")); MUST(s_instance->mount(root_creds, &DevFileSystem::get(), "/dev"sv));
mode_t tmpfs_mode = Inode::Mode::IFDIR MUST(s_instance->mount(root_creds, &ProcFileSystem::get(), "/proc"sv));
| Inode::Mode::IRUSR | Inode::Mode::IWUSR | Inode::Mode::IXUSR
| Inode::Mode::IRGRP | Inode::Mode::IWGRP | Inode::Mode::IXGRP auto* tmpfs = MUST(RamFileSystem::create(1024 * 1024, 0777, 0, 0));
| Inode::Mode::IROTH | Inode::Mode::IWOTH | Inode::Mode::IXOTH; MUST(s_instance->mount(root_creds, tmpfs, "/tmp"sv));
auto* tmpfs = MUST(RamFileSystem::create(1024 * 1024, tmpfs_mode, 0, 0));
MUST(s_instance->mount(root_creds, tmpfs, "/tmp"));
} }
VirtualFileSystem& VirtualFileSystem::get() VirtualFileSystem& VirtualFileSystem::get()

View File

@ -2,6 +2,7 @@
#include <BAN/StringView.h> #include <BAN/StringView.h>
#include <kernel/CriticalScope.h> #include <kernel/CriticalScope.h>
#include <kernel/FS/DevFS/FileSystem.h> #include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/ProcFS/FileSystem.h>
#include <kernel/FS/VirtualFileSystem.h> #include <kernel/FS/VirtualFileSystem.h>
#include <kernel/IDT.h> #include <kernel/IDT.h>
#include <kernel/InterruptController.h> #include <kernel/InterruptController.h>
@ -81,6 +82,8 @@ namespace Kernel
auto* process = new Process(credentials, pid, parent, sid, pgrp); auto* process = new Process(credentials, pid, parent, sid, pgrp);
ASSERT(process); ASSERT(process);
MUST(ProcFileSystem::get().on_process_create(*process));
return process; return process;
} }
@ -194,6 +197,8 @@ namespace Kernel
s_processes.remove(i); s_processes.remove(i);
s_process_lock.unlock(); s_process_lock.unlock();
ProcFileSystem::get().on_process_delete(*this);
m_lock.lock(); m_lock.lock();
m_exit_status.exited = true; m_exit_status.exited = true;
while (m_exit_status.waiting > 0) while (m_exit_status.waiting > 0)
@ -247,6 +252,21 @@ namespace Kernel
thread->set_terminating(); thread->set_terminating();
} }
void Process::get_meminfo(proc_meminfo_t* out) const
{
LockGuard _(m_lock);
out->page_size = PAGE_SIZE;
out->virt_pages = 0;
for (auto* thread : m_threads)
out->virt_pages += thread->virtual_page_count();
for (auto& region : m_mapped_regions)
out->virt_pages += region->virtual_page_count();
if (m_loadable_elf)
out->virt_pages += m_loadable_elf->virtual_page_count();
}
BAN::ErrorOr<long> Process::sys_exit(int status) BAN::ErrorOr<long> Process::sys_exit(int status)
{ {
exit(status, 0); exit(status, 0);

View File

@ -32,7 +32,7 @@ namespace Kernel
if (inode_or_error.is_error()) if (inode_or_error.is_error())
{ {
if (inode_or_error.error().get_error_code() == ENOENT) if (inode_or_error.error().get_error_code() == ENOENT)
DevFileSystem::get().add_device("tty"sv, MUST(RamSymlinkInode::create(DevFileSystem::get(), s_tty->name(), S_IFLNK | 0666, 0, 0))); DevFileSystem::get().add_device("tty"sv, MUST(RamSymlinkInode::create(DevFileSystem::get(), s_tty->name(), 0666, 0, 0)));
else else
dwarnln("{}", inode_or_error.error()); dwarnln("{}", inode_or_error.error());
return; return;

View File

@ -2,6 +2,7 @@
#include <kernel/Arch.h> #include <kernel/Arch.h>
#include <kernel/Debug.h> #include <kernel/Debug.h>
#include <kernel/FS/DevFS/FileSystem.h> #include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/ProcFS/FileSystem.h>
#include <kernel/FS/VirtualFileSystem.h> #include <kernel/FS/VirtualFileSystem.h>
#include <kernel/GDT.h> #include <kernel/GDT.h>
#include <kernel/IDT.h> #include <kernel/IDT.h>
@ -131,6 +132,9 @@ extern "C" void kernel_main()
DevFileSystem::initialize(); DevFileSystem::initialize();
dprintln("devfs initialized"); dprintln("devfs initialized");
ProcFileSystem::initialize();
dprintln("procfs initialized");
if (Serial::has_devices()) if (Serial::has_devices())
{ {
Serial::initialize_devices(); Serial::initialize_devices();

View File

@ -13,9 +13,19 @@ __BEGIN_DECLS
struct __DIR; struct __DIR;
typedef struct __DIR DIR; typedef struct __DIR DIR;
#define DT_UNKNOWN 0
#define DT_REG 1
#define DT_DIR 2
#define DT_CHR 3
#define DT_BLK 4
#define DT_FIFO 5
#define DT_SOCK 6
#define DT_LNK 7
struct dirent struct dirent
{ {
ino_t d_ino; /* File serial number. */ ino_t d_ino; /* File serial number. */
unsigned char d_type; /* File type. One of DT_* definitions. */
char d_name[]; /* Filename string of entry. */ char d_name[]; /* Filename string of entry. */
}; };

View File

@ -5,6 +5,9 @@
__BEGIN_DECLS __BEGIN_DECLS
#define __need_size_t 1
#include <stddef.h>
#define TTY_CMD_SET 0x01 #define TTY_CMD_SET 0x01
#define TTY_CMD_UNSET 0x02 #define TTY_CMD_UNSET 0x02
@ -14,6 +17,12 @@ __BEGIN_DECLS
#define POWEROFF_SHUTDOWN 0 #define POWEROFF_SHUTDOWN 0
#define POWEROFF_REBOOT 1 #define POWEROFF_REBOOT 1
struct proc_meminfo_t
{
size_t page_size;
size_t virt_pages;
};
/* /*
fildes: refers to valid tty device fildes: refers to valid tty device
command: one of TTY_CMD_* definitions command: one of TTY_CMD_* definitions

View File

@ -62,12 +62,18 @@ int strcmp(const char* s1, const char* s2)
return *u1 - *u2; return *u1 - *u2;
} }
char* strcpy(char* __restrict__ dest, const char* __restrict__ src) char* stpcpy(char* __restrict__ dest, const char* __restrict__ src)
{ {
size_t i; size_t i = 0;
for (i = 0; src[i]; i++) for (; src[i]; i++)
dest[i] = src[i]; dest[i] = src[i];
dest[i] = '\0'; dest[i] = '\0';
return &dest[i];
}
char* strcpy(char* __restrict__ dest, const char* __restrict__ src)
{
stpcpy(dest, src);
return dest; return dest;
} }

View File

@ -10,6 +10,7 @@ set(USERSPACE_PROJECTS
id id
init init
ls ls
meminfo
mmap-shared-test mmap-shared-test
poweroff poweroff
Shell Shell

View File

@ -700,12 +700,18 @@ BAN::String get_prompt()
break; break;
} }
case 'u': case 'u':
{
static char* username = nullptr;
if (username == nullptr)
{ {
auto* passwd = getpwuid(geteuid()); auto* passwd = getpwuid(geteuid());
if (passwd == nullptr) if (passwd == nullptr)
break; break;
MUST(prompt.append(passwd->pw_name)); username = new char[strlen(passwd->pw_name) + 1];
strcpy(username, passwd->pw_name);
endpwent(); endpwent();
}
MUST(prompt.append(username));
break; break;
} }
case 'h': case 'h':

View File

@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.26)
project(meminfo CXX)
set(SOURCES
main.cpp
)
add_executable(meminfo ${SOURCES})
target_compile_options(meminfo PUBLIC -O2 -g)
target_link_libraries(meminfo PUBLIC libc)
add_custom_target(meminfo-install
COMMAND sudo cp ${CMAKE_CURRENT_BINARY_DIR}/meminfo ${BANAN_BIN}/
DEPENDS meminfo
USES_TERMINAL
)

View File

@ -0,0 +1,57 @@
#include <ctype.h>
#include <dirent.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/banan-os.h>
bool is_only_digits(const char* str)
{
while (*str)
if (!isdigit(*str++))
return false;
return true;
}
int main()
{
DIR* proc = opendir("/proc");
if (proc == nullptr)
{
perror("opendir");
return 1;
}
char path_buffer[128] {};
while (dirent* proc_ent = readdir(proc))
{
if (proc_ent->d_type != DT_DIR)
continue;
if (!is_only_digits(proc_ent->d_name))
continue;
strcpy(path_buffer, proc_ent->d_name);
strcat(path_buffer, "/meminfo");
int fd = openat(dirfd(proc), path_buffer, O_RDONLY);
if (fd == -1)
{
perror("openat");
continue;
}
proc_meminfo_t meminfo;
if (read(fd, &meminfo, sizeof(meminfo)) == -1)
perror("read");
else
{
printf("process:\n");
printf(" pid: %s\n", proc_ent->d_name);
printf(" vmem: %zu pages (%zu bytes)\n", meminfo.virt_pages, meminfo.page_size * meminfo.virt_pages);
}
close(fd);
}
closedir(proc);
}