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;
}
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");
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 {};

View File

@ -33,6 +33,8 @@ namespace LibELF
BAN::ErrorOr<BAN::UniqPtr<LoadableELF>> clone(Kernel::PageTable&);
size_t virtual_page_count() const { return m_virtual_page_count; }
private:
LoadableELF(Kernel::PageTable&, BAN::RefPtr<Kernel::Inode>);
BAN::ErrorOr<void> initialize();
@ -42,6 +44,7 @@ namespace LibELF
Kernel::PageTable& m_page_table;
ElfNativeFileHeader m_file_header;
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/Inode.cpp
kernel/FS/Pipe.cpp
kernel/FS/ProcFS/FileSystem.cpp
kernel/FS/ProcFS/Inode.cpp
kernel/FS/RamFS/FileSystem.cpp
kernel/FS/RamFS/Inode.cpp
kernel/FS/VirtualFileSystem.cpp

View File

@ -25,9 +25,9 @@ namespace Kernel
{
protected:
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:
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<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> delete_inode(BAN::StringView);
// Link API
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<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> delete_inode_impl(BAN::StringView) { return BAN::Error::from_errno(ENOTSUP); }
// Link API
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
{
public:
static BAN::ErrorOr<BAN::RefPtr<RamInode>> create(RamFileSystem&, mode_t, uid_t, gid_t);
virtual ~RamInode() = default;
virtual ino_t ino() const override { return m_inode_info.ino; }
@ -31,16 +30,10 @@ namespace Kernel
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:
struct FullInodeInfo
{
FullInodeInfo(RamFileSystem&, mode_t, uid_t, gid_t);
ino_t ino;
mode_t mode;
nlink_t nlink;
@ -56,16 +49,38 @@ namespace Kernel
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:
RamFileSystem& m_fs;
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;
friend class RamFileSystem;
};
class RamDirectoryInode final : public RamInode
class RamDirectoryInode : public RamInode
{
public:
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>);
protected:
RamDirectoryInode(RamFileSystem&, const FullInodeInfo&, ino_t parent);
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> create_file_impl(BAN::StringView, mode_t, uid_t, gid_t) override;
private:
RamDirectoryInode(RamFileSystem&, ino_t parent, mode_t, uid_t, gid_t);
virtual BAN::ErrorOr<void> delete_inode_impl(BAN::StringView) override;
private:
static constexpr size_t m_name_max = NAME_MAX;
@ -88,11 +103,12 @@ namespace Kernel
char name[m_name_max + 1];
size_t name_len = 0;
ino_t ino;
uint8_t type;
};
private:
BAN::Vector<Entry> m_entries;
ino_t m_parent;
const ino_t m_parent;
friend class RamFileSystem;
};
@ -111,7 +127,7 @@ namespace Kernel
virtual BAN::ErrorOr<BAN::String> link_target_impl() override;
private:
RamSymlinkInode(RamFileSystem&, mode_t, uid_t, gid_t);
RamSymlinkInode(RamFileSystem&, const FullInodeInfo&, BAN::String&&);
private:
BAN::String m_target;

View File

@ -37,6 +37,8 @@ namespace Kernel
size_t size() const { return m_size; }
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 true if page was succesfully allocated
// Returns false if page was already allocated

View File

@ -13,6 +13,7 @@
#include <kernel/Terminal/TTY.h>
#include <kernel/Thread.h>
#include <sys/banan-os.h>
#include <sys/mman.h>
#include <termios.h>
@ -138,6 +139,8 @@ namespace 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; }
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; }
size_t virtual_page_count() const { return m_stack->size() / PAGE_SIZE; }
#if __enable_sse
void save_sse() { asm volatile("fxsave %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)
: 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);
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));
s_instance->add_device("null", MUST(NullDevice::create(0666, 0, 0)));

View File

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

View File

@ -84,6 +84,15 @@ namespace Kernel
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()
{
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
{
/*
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)
RamInode::FullInodeInfo::FullInodeInfo(RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
{
timespec current_time = SystemTimer::get().real_time();
m_inode_info.ino = fs.next_ino();
m_inode_info.mode = mode;
m_inode_info.nlink = 1;
m_inode_info.uid = uid;
m_inode_info.gid = gid;
m_inode_info.size = 0;
m_inode_info.atime = current_time;
m_inode_info.mtime = current_time;
m_inode_info.ctime = current_time;
m_inode_info.blksize = fs.blksize();
m_inode_info.blocks = 0;
m_inode_info.dev = 0;
m_inode_info.rdev = 0;
this->ino = fs.next_ino();
this->mode = mode;
this->nlink = 1;
this->uid = uid;
this->gid = gid;
this->size = 0;
this->atime = current_time;
this->mtime = current_time;
this->ctime = current_time;
this->blksize = fs.blksize();
this->blocks = 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);
if (offset >= size())
@ -50,7 +58,7 @@ namespace Kernel
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);
if (offset + bytes > (size_t)size())
@ -59,7 +67,7 @@ namespace Kernel
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));
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)
{
ASSERT(Mode(mode).ifdir());
auto* ram_inode = new RamDirectoryInode(fs, parent, mode, uid, gid);
FullInodeInfo inode_info(fs, 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)
return BAN::Error::from_errno(ENOMEM);
return BAN::RefPtr<RamDirectoryInode>::adopt(ram_inode);
}
RamDirectoryInode::RamDirectoryInode(RamFileSystem& fs, ino_t parent, mode_t mode, uid_t uid, gid_t gid)
: RamInode(fs, mode, uid, gid)
RamDirectoryInode::RamDirectoryInode(RamFileSystem& fs, const FullInodeInfo& inode_info, ino_t parent)
: RamInode(fs, inode_info)
, m_parent(parent)
{
// "." links to this
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;
}
m_inode_info.mode |= Inode::Mode::IFDIR;
}
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_type = DT_DIR;
ptr->rec_len = sizeof(DirectoryEntry) + 2;
strcpy(ptr->dirent.d_name, ".");
ptr = ptr->next();
@ -159,6 +169,7 @@ namespace Kernel
// ".."
{
ptr->dirent.d_ino = m_parent;
ptr->dirent.d_type = DT_DIR;
ptr->rec_len = sizeof(DirectoryEntry) + 3;
strcpy(ptr->dirent.d_name, "..");
ptr = ptr->next();
@ -167,6 +178,7 @@ namespace Kernel
for (auto& entry : m_entries)
{
ptr->dirent.d_ino = entry.ino;
ptr->dirent.d_type = entry.type;
ptr->rec_len = sizeof(DirectoryEntry) + entry.name_len + 1;
strcpy(ptr->dirent.d_name, entry.name);
ptr = ptr->next();
@ -181,7 +193,7 @@ namespace Kernel
{
BAN::RefPtr<RamInode> inode;
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())
inode = TRY(RamDirectoryInode::create(m_fs, ino(), mode, uid, gid));
else
@ -192,6 +204,25 @@ namespace Kernel
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)
{
if (name.size() > m_name_max)
@ -206,6 +237,7 @@ namespace Kernel
strcpy(entry.name, name.data());
entry.name_len = name.size();
entry.ino = inode->ino();
entry.type = get_type(inode->mode());
if (auto ret = m_fs.add_inode(inode); ret.is_error())
{
@ -216,26 +248,44 @@ namespace Kernel
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
*/
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());
auto* ram_inode = new RamSymlinkInode(fs, mode, uid, gid);
FullInodeInfo inode_info(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)
return BAN::Error::from_errno(ENOMEM);
auto ref_ptr = BAN::RefPtr<RamSymlinkInode>::adopt(ram_inode);
TRY(ref_ptr->set_link_target(target));
return ref_ptr;
return BAN::RefPtr<RamSymlinkInode>::adopt(ram_inode);
}
RamSymlinkInode::RamSymlinkInode(RamFileSystem& fs, mode_t mode, uid_t uid, gid_t gid)
: RamInode(fs, mode, uid, gid)
{ }
RamSymlinkInode::RamSymlinkInode(RamFileSystem& fs, const FullInodeInfo& inode_info, BAN::String&& target)
: RamInode(fs, inode_info)
, m_target(BAN::move(target))
{
m_inode_info.mode |= Inode::Mode::IFLNK;
}
BAN::ErrorOr<BAN::String> RamSymlinkInode::link_target_impl()
{

View File

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

View File

@ -2,6 +2,7 @@
#include <BAN/StringView.h>
#include <kernel/CriticalScope.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/ProcFS/FileSystem.h>
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/IDT.h>
#include <kernel/InterruptController.h>
@ -81,6 +82,8 @@ namespace Kernel
auto* process = new Process(credentials, pid, parent, sid, pgrp);
ASSERT(process);
MUST(ProcFileSystem::get().on_process_create(*process));
return process;
}
@ -194,6 +197,8 @@ namespace Kernel
s_processes.remove(i);
s_process_lock.unlock();
ProcFileSystem::get().on_process_delete(*this);
m_lock.lock();
m_exit_status.exited = true;
while (m_exit_status.waiting > 0)
@ -247,6 +252,21 @@ namespace Kernel
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)
{
exit(status, 0);

View File

@ -32,7 +32,7 @@ namespace Kernel
if (inode_or_error.is_error())
{
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
dwarnln("{}", inode_or_error.error());
return;

View File

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

View File

@ -13,10 +13,20 @@ __BEGIN_DECLS
struct __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
{
ino_t d_ino; /* File serial number. */
char d_name[]; /* Filename string of entry. */
ino_t d_ino; /* File serial number. */
unsigned char d_type; /* File type. One of DT_* definitions. */
char d_name[]; /* Filename string of entry. */
};
int alphasort(const struct dirent** d1, const struct dirent** d2);

View File

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

View File

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

View File

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

View File

@ -701,11 +701,17 @@ BAN::String get_prompt()
}
case 'u':
{
auto* passwd = getpwuid(geteuid());
if (passwd == nullptr)
break;
MUST(prompt.append(passwd->pw_name));
endpwent();
static char* username = nullptr;
if (username == nullptr)
{
auto* passwd = getpwuid(geteuid());
if (passwd == nullptr)
break;
username = new char[strlen(passwd->pw_name) + 1];
strcpy(username, passwd->pw_name);
endpwent();
}
MUST(prompt.append(username));
break;
}
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);
}