您的位置:首页 > 运维架构

babyos2(20) simple file system (2), file, open, close, read, write

2018-01-06 18:02 281 查看
前面已经探究了super block, inode, bitmap等基本的结构、读写,以及实现了一个简单的namei实现从path找到inode。现在准备为babyos2实现基本的文件操作,打开,创建、读写等。为简单起见,还是先不考虑多进程访问需要的锁,等功能完成后再增加锁。

1.open, close, create

int file_system_t::write_inode(inode_t* inode, void* src, uint32 offset, uint32 size)
{
if (offset > inode->m_size) {
return -1;
}
if (offset + size > MAX_FILE_SIZE * BSIZE) {
return -1;
}

int nbyte = 0, total = 0;
while (total < size) {
io_clb_t clb;
clb.init(m_dev, 1, block_map(inode, offset/ BSIZE));
os()->get_ide()->request(&clb);
nbyte = BSIZE - offset % BSIZE;
if (nbyte > size - total) {
nbyte = size - total;
}

memcpy(clb.buffer + offset % BSIZE, src, nbyte);
clb.init(m_dev, 0, block_map(inode, offset/ BSIZE));
os()->get_ide()->request(&clb);

total += nbyte;
offset += nbyte;
src += nbyte;
}

if (total > 0 && offset > inode->m_size) {
inode->m_size = offset;
update_disk_inode(inode);
}

return total;
}

int file_system_t::dir_link(inode_t* inode, char* name, uint32 inum)
{
// already present in the dir
inode_t* find = NULL;
unsigned offset = 0;
if ((find = dir_lookup(inode, name, offset)) != NULL) {
put_inode(inode);
return -1;
}

// find an empty dir_entry
dir_entry_t dir;
for (offset = 0; offset < inode->m_size; offset += sizeof(dir)) {
if (read_inode(inode, (char *) &dir, offset, sizeof(dir)) != sizeof(dir)) {
return -1;
}
if (dir.m_inum == 0) {
break;
}
}

dir.m_inum = inum;
memset(dir.m_name, 0, MAX_PATH);
strncpy(dir.m_name, name, MAX_PATH);

write_inode(inode, &dir, offset, sizeof(dir));

return 0;
}

inode_t* file_system_t::create(const char* path, uint16 type, uint16 major, uint16 minor)
{
char name[MAX_PATH] = {0};
inode_t* inode_dir = NULL;
if ((inode_dir = nameiparent(path, name)) == NULL) {
return NULL;
}

inode_t* inode = NULL;
unsigned offset = 0;
if ((inode = dir_lookup(inode_dir, name, offset)) != NULL) {
if (inode->m_type == inode_t::I_TYPE_FILE && type == inode_t::I_TYPE_FILE) {
return inode;
}
return NULL;
}

if ((inode = alloc_inode(inode_dir->m_dev, type)) == NULL) {
return NULL;
}

inode->init(major, minor, 1);
inode->m_type = type;
update_disk_inode(inode);

if (inode->m_type == inode_t::I_TYPE_DIR) {
inode_dir->m_nlinks++;
update_disk_inode(inode_dir);
if (dir_link(inode, (char *) ".", inode->m_inum) < 0 ||
dir_link(inode, (char *) "..", inode->m_inum) < 0) {
return NULL;
}
}

dir_link(inode_dir, name, inode->m_inum);
return inode;
}

file_t* file_system_t::alloc_file()
{
for (int i = 0; i < MAX_FILE_NUM; i++) {
if (m_file_table[i].m_type == file_t::TYPE_NONE) {
return &m_file_table[i];
}
}
return NULL;
}

int file_system_t::close_file(file_t* file)
{
if (file->m_ref < 1) {
return -1;
}

if (--file->m_ref > 0) {
return 0;
}

if (file->m_type == file_t::TYPE_INODE) {
file->m_type = file_t::TYPE_NONE;
put_inode(file->m_inode);
}
}

int file_system_t::do_open(const char* path, int mode)
{
inode_t* inode = NULL;
file_t* file = NULL;

if (mode & file_t::MODE_CREATE) {
if ((inode = create(path, inode_t::I_TYPE_FILE, 0, 0)) == NULL) {
return -1;
}
}
else {
if ((inode = namei(path)) == NULL) {
return -1;
}
}

int fd = -1;
do {
if (inode->m_type == inode_t::I_TYPE_DIR) {
break;
}
if ((file = alloc_file()) == NULL) {
break;
}
if ((fd = current->alloc_fd(file)) < 0) {
close_file(file);
break;
}
} while (0);

if (fd >= 0) {
file->init(file_t::TYPE_INODE, inode, 0,
!(mode & file_t::MODE_WRONLY),
(mode & file_t::MODE_WRONLY) || (mode & file_t::MODE_RDWR));
}

return fd;
}

int file_system_t::do_close(int fd)
{
file_t* file = current->get_file(fd);
if (file != NULL) {
close_file(file);
}

return 0;
}




2.read

int file_system_t::do_read(int fd, void* buffer, uint32 count)
{
file_t* file = current->get_file(fd);
if (file == NULL || file->m_readable == 0) {
return -1;
}

if (file->m_type == file_t::TYPE_INODE) {
int nbyte = 0;
if ((nbyte = read_inode(file->m_inode, (char *) buffer, file->m_offset, count)) > 0) {
file->m_offset += nbyte;
}
return nbyte;
}

return -1;
}

void file_system_t::test_read()
{
console()->kprintf(YELLOW, "test read: \n");
int fd = do_open((char *) "/test", 0);
if (fd < 0) {
return;
}

char buffer[512] = {0};
int n = do_read(fd, buffer, 512);
console()->kprintf(YELLOW, "%u bytes read from file test: \n%s\n", n, buffer);
do_close(fd);
}




3.write

int file_system_t::do_write(int fd, void* buffer, uint32 count)
{
file_t* file = current->get_file(fd);
if (file == NULL || file->m_writeable == 0) {
return -1;
}

if (file->m_type == file_t::TYPE_INODE) {
int nbyte = 0;
if ((nbyte = write_inode(file->m_inode, (char *) buffer, file->m_offset, count)) > 0) {
file->m_offset += nbyte;
}
return nbyte;
}

return -1;
}

void file_system_t::test_write()
{
console()->kprintf(PINK, "test write: \n");
int fd = do_open((char *) "/test", file_t::MODE_RDWR);
if (fd < 0) {
return;
}

// read
char buffer[512] = {0};
int n = do_read(fd, buffer, 512);
console()->kprintf(WHITE, "%u bytes read from file test: \n%s\n", n, buffer);
do_close(fd);

// write
strcpy(buffer + 37, "2) test write...\n");
fd = do_open((char *) "/test", file_t::MODE_RDWR);
n = do_write(fd, buffer, strlen(buffer));
console()->kprintf(WHITE, "%u bytes write to file\n", n);
do_close(fd);

// re-read
fd = do_open((char *) "/test", file_t::MODE_RDWR);
memset(buffer, 0, 512);
n = do_read(fd, buffer, 512);
console()->kprintf(WHITE, "%u bytes read from file test: \n%s\n", n, buffer);
do_close(fd);
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: