diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2026-01-04 14:12:24 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2026-01-04 14:12:24 +0800 |
| commit | a64d25c07b31d57f8706073e11cd774d0880d6dd (patch) | |
| tree | a4bbae6cff94fa69eea30db865267b211eb4c86b /src/fs/file.cc | |
| parent | 210025560c80b48af4875af199f183ad709e3bf0 (diff) | |
| parent | d3cf3f08d1343d6b265516d5a79ce2d197b59d26 (diff) | |
| download | lume-a64d25c07b31d57f8706073e11cd774d0880d6dd.tar.gz lume-a64d25c07b31d57f8706073e11cd774d0880d6dd.tar.xz | |
Merge pull request #5 from Richard-Qin-001/dev/file-system
feat(file-system): implement read and write FAT32 File System and basic shell
Diffstat (limited to 'src/fs/file.cc')
| -rw-r--r-- | src/fs/file.cc | 137 |
1 files changed, 135 insertions, 2 deletions
diff --git a/src/fs/file.cc b/src/fs/file.cc index 99bb65d..623b535 100644 --- a/src/fs/file.cc +++ b/src/fs/file.cc @@ -3,12 +3,135 @@ #include "kernel/mm.h" #include "drivers/uart.h" #include "kernel/proc.h" +#include "kernel/slab.h" #define NFILE 100 #define SEEK_SET 0 #define SEEK_CUR 1 #define SEEK_END 2 +extern void *operator new(unsigned long, void *p); + +int Pipe::create_pair(file** f0, file** f1) +{ + void *mem = Slab::kmalloc(sizeof(Pipe)); + if (!mem) + return -1; + Pipe *pi = new (mem) Pipe(); + + *f0 = FileTable::alloc(); + *f1 = FileTable::alloc(); + + if (*f0 == nullptr || *f1 == nullptr) + { + if (*f0) + FileTable::close(*f0); + if (*f1) + FileTable::close(*f1); + pi->~Pipe(); + Slab::kfree(pi); + return -1; + } + + (*f0)->type = FD_PIPE; + (*f0)->readable = 1; + (*f0)->writable = 0; + (*f0)->pipe = pi; + + (*f1)->type = FD_PIPE; + (*f1)->readable = 0; + (*f1)->writable = 1; + (*f1)->pipe = pi; + + return 0; +} + +void Pipe::close(bool is_writer) +{ + lock.acquire(); + if (is_writer) + { + write_open = false; + ProcManager::wakeup(&nread); // Wake up the process that is currently reading + } + else + { + read_open = false; + ProcManager::wakeup(&nwrite); // Wake up the process that is writing + } + + bool empty = !read_open && !write_open; + lock.release(); + + if (empty) + { + this->~Pipe(); + Slab::kfree(this); + } +} + +int Pipe::write(uint64_t addr, int n) +{ + int i = 0; + struct Proc *p = myproc(); + + lock.acquire(); + while (i < n) + { + if (!read_open || p->xstate) // The read end is closed or the process is abnormal + { + lock.release(); + return -1; + } + + if (nwrite == nread + SIZE) // buffer is full + { + ProcManager::wakeup(&nread); + ProcManager::sleep(&nwrite, &lock); + } + else + { + char ch; + if (VM::copyin(p->pagetable, &ch, addr + i, 1) < 0) + break; + data[nwrite++ % SIZE] = ch; + i++; + } + } + ProcManager::wakeup(&nread); + lock.release(); + return i; +} + +int Pipe::read(uint64_t addr, int n) +{ + int i = 0; + struct Proc *p = myproc(); + + lock.acquire(); + while (nread == nwrite && write_open) // The buffer is empty and the write end is not closed + { + if (p->xstate) + { + lock.release(); + return -1; + } + ProcManager::sleep(&nread, &lock); + } + + for (i = 0; i < n; ++i) + { + if (nread == nwrite) + break; + char ch = data[nread++ % SIZE]; + if (VM::copyout(p->pagetable, addr + i, &ch, 1) < 0) + break; + } + ProcManager::wakeup(&nwrite); + lock.release(); + return i; +} + namespace FileTable { struct @@ -82,7 +205,8 @@ namespace FileTable } else if (ff.type == FD_PIPE) { - // pipeclose(ff.pipe, ff.writable); + if (ff.pipe) + ff.pipe->close(ff.writable); } } @@ -101,6 +225,11 @@ namespace FileTable VFS::iunlock(f->ip); return r; } + else if (f->type == FD_PIPE) + { + if (f->pipe) + return f->pipe->read(addr, n); + } return -1; } @@ -119,7 +248,11 @@ namespace FileTable VFS::iunlock(f->ip); return r; } - // else if (f->type == FD_PIPE) ... + else if (f->type == FD_PIPE) + { + if (f->pipe) + return f->pipe->write(addr, n); + } return -1; } |
