1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 07:48:11 +00:00

Add basic character device support. Start with null and zero.

This commit is contained in:
Andreas Kling 2018-10-14 02:59:22 +02:00
parent fa3b11ac64
commit 93556d6743
14 changed files with 157 additions and 2 deletions

View file

@ -0,0 +1,7 @@
#include "CharacterDevice.h"
CharacterDevice::~CharacterDevice()
{
}

View file

@ -0,0 +1,15 @@
#pragma once
#include <AK/Types.h>
#include "Limits.h"
class CharacterDevice {
public:
virtual ~CharacterDevice();
virtual ssize_t read(byte* buffer, size_t bufferSize) = 0;
virtual ssize_t write(const byte* buffer, size_t bufferSize) = 0;
protected:
CharacterDevice() { }
};

View file

@ -1,5 +1,6 @@
#include "FileHandle.h" #include "FileHandle.h"
#include "FileSystem.h" #include "FileSystem.h"
#include "CharacterDevice.h"
FileHandle::FileHandle(RetainPtr<VirtualFileSystem::Node>&& vnode) FileHandle::FileHandle(RetainPtr<VirtualFileSystem::Node>&& vnode)
: m_vnode(std::move(vnode)) : m_vnode(std::move(vnode))
@ -10,8 +11,15 @@ FileHandle::~FileHandle()
{ {
} }
ByteBuffer FileHandle::read() const ByteBuffer FileHandle::read()
{ {
if (m_vnode->isCharacterDevice()) {
auto buffer = ByteBuffer::createUninitialized(1024);
ssize_t nread = m_vnode->characterDevice()->read(buffer.pointer(), buffer.size());
buffer.trim(nread);
return buffer;
}
return m_vnode->fileSystem()->readInode(m_vnode->inode); return m_vnode->fileSystem()->readInode(m_vnode->inode);
} }

View file

@ -8,7 +8,7 @@ public:
explicit FileHandle(RetainPtr<VirtualFileSystem::Node>&&); explicit FileHandle(RetainPtr<VirtualFileSystem::Node>&&);
~FileHandle(); ~FileHandle();
ByteBuffer read() const; ByteBuffer read();
private: private:
friend class VirtualFileSystem; friend class VirtualFileSystem;

View file

@ -0,0 +1,6 @@
#pragma once
typedef dword size_t;
typedef signed_dword ssize_t;
static const size_t GoodBufferSize = 4096;

View file

@ -20,6 +20,7 @@ VFS_OBJS = \
InodeIdentifier.o \ InodeIdentifier.o \
CharacterDevice.o \ CharacterDevice.o \
ZeroDevice.o \ ZeroDevice.o \
NullDevice.o \
test.o test.o
OBJS = $(AK_OBJS) $(VFS_OBJS) OBJS = $(AK_OBJS) $(VFS_OBJS)

View file

@ -0,0 +1,25 @@
#include "NullDevice.h"
#include "Limits.h"
#include <AK/StdLib.h>
#include <cstring>
#include <cstdio>
NullDevice::NullDevice()
{
}
NullDevice::~NullDevice()
{
}
ssize_t NullDevice::read(byte*, size_t)
{
printf("read from null\n");
return 0;
}
ssize_t NullDevice::write(const byte*, size_t bufferSize)
{
return min(GoodBufferSize, bufferSize);
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "CharacterDevice.h"
class NullDevice final : public CharacterDevice {
public:
NullDevice();
virtual ~NullDevice();
ssize_t read(byte* buffer, size_t bufferSize) override;
ssize_t write(const byte* buffer, size_t bufferSize) override;
};

View file

@ -7,6 +7,11 @@
//#define VFS_DEBUG //#define VFS_DEBUG
static dword encodedDevice(unsigned major, unsigned minor)
{
return (minor & 0xff) | (major << 8) | ((minor & ~0xff) << 12);
}
VirtualFileSystem::VirtualFileSystem() VirtualFileSystem::VirtualFileSystem()
{ {
m_maxNodeCount = 16; m_maxNodeCount = 16;
@ -28,6 +33,17 @@ auto VirtualFileSystem::makeNode(InodeIdentifier inode) -> RetainPtr<Node>
if (!metadata.isValid()) if (!metadata.isValid())
return nullptr; return nullptr;
CharacterDevice* characterDevice = nullptr;
if (metadata.isCharacterDevice()) {
auto it = m_characterDevices.find(encodedDevice(metadata.majorDevice, metadata.minorDevice));
if (it != m_characterDevices.end()) {
characterDevice = (*it).value;
} else {
printf("[VFS] makeNode() no such character device %u,%u\n", metadata.majorDevice, metadata.minorDevice);
return nullptr;
}
}
auto vnode = allocateNode(); auto vnode = allocateNode();
ASSERT(vnode); ASSERT(vnode);
@ -41,6 +57,7 @@ auto VirtualFileSystem::makeNode(InodeIdentifier inode) -> RetainPtr<Node>
#endif #endif
m_inode2vnode.set(inode, vnode.ptr()); m_inode2vnode.set(inode, vnode.ptr());
vnode->m_characterDevice = characterDevice;
return vnode; return vnode;
} }
@ -118,6 +135,7 @@ void VirtualFileSystem::freeNode(Node* node)
m_inode2vnode.remove(node->inode); m_inode2vnode.remove(node->inode);
node->inode.fileSystem()->release(); node->inode.fileSystem()->release();
node->inode = InodeIdentifier(); node->inode = InodeIdentifier();
node->m_characterDevice = nullptr;
m_nodeFreeList.append(std::move(node)); m_nodeFreeList.append(std::move(node));
} }
@ -415,3 +433,7 @@ VirtualFileSystem::Mount::Mount(InodeIdentifier host, RetainPtr<FileSystem>&& gu
{ {
} }
void VirtualFileSystem::registerCharacterDevice(unsigned major, unsigned minor, CharacterDevice& device)
{
m_characterDevices.set(encodedDevice(major, minor), &device);
}

View file

@ -7,6 +7,7 @@
#include <AK/Vector.h> #include <AK/Vector.h>
#include "InodeIdentifier.h" #include "InodeIdentifier.h"
class CharacterDevice;
class FileHandle; class FileHandle;
class FileSystem; class FileSystem;
@ -17,6 +18,9 @@ public:
bool inUse() const { return inode.isValid(); } bool inUse() const { return inode.isValid(); }
bool isCharacterDevice() const { return m_characterDevice; }
CharacterDevice* characterDevice() { return m_characterDevice; }
void retain(); void retain();
void release(); void release();
@ -27,6 +31,7 @@ public:
friend class VirtualFileSystem; friend class VirtualFileSystem;
VirtualFileSystem* vfs { nullptr }; VirtualFileSystem* vfs { nullptr };
unsigned retainCount { 0 }; unsigned retainCount { 0 };
CharacterDevice* m_characterDevice { nullptr };
}; };
VirtualFileSystem(); VirtualFileSystem();
@ -52,6 +57,8 @@ public:
bool touch(const String&path); bool touch(const String&path);
void registerCharacterDevice(unsigned major, unsigned minor, CharacterDevice&);
private: private:
template<typename F> void enumerateDirectoryInode(InodeIdentifier, F func); template<typename F> void enumerateDirectoryInode(InodeIdentifier, F func);
InodeIdentifier resolvePath(const String& path); InodeIdentifier resolvePath(const String& path);
@ -80,6 +87,7 @@ private:
Mount* findMountForGuest(InodeIdentifier); Mount* findMountForGuest(InodeIdentifier);
HashMap<InodeIdentifier, Node*> m_inode2vnode; HashMap<InodeIdentifier, Node*> m_inode2vnode;
HashMap<dword, Node*> m_device2vnode;
Vector<OwnPtr<Mount>> m_mounts; Vector<OwnPtr<Mount>> m_mounts;
@ -89,5 +97,7 @@ private:
Vector<Node*> m_nodeFreeList; Vector<Node*> m_nodeFreeList;
RetainPtr<Node> m_rootNode; RetainPtr<Node> m_rootNode;
HashMap<dword, CharacterDevice*> m_characterDevices;
}; };

View file

@ -0,0 +1,27 @@
#include "ZeroDevice.h"
#include "Limits.h"
#include <AK/StdLib.h>
#include <cstring>
#include <cstdio>
ZeroDevice::ZeroDevice()
{
}
ZeroDevice::~ZeroDevice()
{
}
ssize_t ZeroDevice::read(byte* buffer, size_t bufferSize)
{
printf("read from zero device\n");
size_t count = min(GoodBufferSize, bufferSize);
memset(buffer, 0, count);
return count;
}
ssize_t ZeroDevice::write(const byte*, size_t bufferSize)
{
return min(GoodBufferSize, bufferSize);
}

View file

@ -0,0 +1,13 @@
#pragma once
#include "CharacterDevice.h"
class ZeroDevice final : public CharacterDevice {
public:
ZeroDevice();
virtual ~ZeroDevice();
ssize_t read(byte* buffer, size_t bufferSize) override;
ssize_t write(const byte* buffer, size_t bufferSize) override;
};

Binary file not shown.

View file

@ -3,6 +3,8 @@
#include "VirtualFileSystem.h" #include "VirtualFileSystem.h"
#include "FileHandle.h" #include "FileHandle.h"
#include "SyntheticFileSystem.h" #include "SyntheticFileSystem.h"
#include "ZeroDevice.h"
#include "NullDevice.h"
#include <cstring> #include <cstring>
#include <AK/SimpleMalloc.h> #include <AK/SimpleMalloc.h>
#include <AK/kmalloc.h> #include <AK/kmalloc.h>
@ -17,6 +19,12 @@ int main(int c, char** v)
VirtualFileSystem vfs; VirtualFileSystem vfs;
auto zero = make<ZeroDevice>();
vfs.registerCharacterDevice(1, 5, *zero);
auto null = make<NullDevice>();
vfs.registerCharacterDevice(1, 3, *null);
if (!vfs.mountRoot(makeFileSystem(filename))) { if (!vfs.mountRoot(makeFileSystem(filename))) {
printf("Failed to mount root :(\n"); printf("Failed to mount root :(\n");
return 1; return 1;