系统调用open的执行路径
代码来自Ucore教学操作系统
//用户通过open系统调用接口,执行int 0x80指令,进入内核,查找系统调用表,调用sys_open。
level 1: sys_open
//---level 1---
static uint32_t
sys_open(uint32_t arg[]) {
const char *path = (const char *)arg[0];
uint32_t open_flags = (uint32_t)arg[1];
//调用level 2.1 【VFS】
return sysfile_open(path, open_flags); //返回打开文件的文件描述符fd
}
level 2.1: sysfile_open【VFS层】
//---level 2.1【VFS】---
int
sysfile_open(const char *__path, uint32_t open_flags) {
int ret;
char *path;
if ((ret = copy_path(&path, __path)) != 0) {
//help routine 1
return ret; //返回错误信息
}
//----------------------------------------
//调用level 2.2
ret = file_open(path, open_flags);
//----------------------------------------
kfree(path); //释放path指向的内核空间
return ret;//返回打开文件的文件描述符fd
}
help routine 1: copy_path
static int copy_path(char **to, const char *from)
{
struct mm_struct *mm = current->mm;
char *buffer;
//为内核申请容纳字符串的空间
if ((buffer = kmalloc(FS_MAX_FPATH_LEN + 1)) == NULL) {
//kmalloc申请的空间来自物理内存的前896M,对应内核虚拟空间的直接映射区,物理/虚拟地址
//空间均连续
return -E_NO_MEM;
}
lock_mm(mm);
//将用户空间的路径字符串拷贝到内核空间
if (!copy_string(mm, buffer, from, FS_MAX_FPATH_LEN + 1)) {
unlock_mm(mm);
goto failed_cleanup;
}
unlock_mm(mm);
*to = buffer;//to指向buffer
return 0;
failed_cleanup:
kfree(buffer);
return -E_INVAL;
}
level 2.2: file_open
//---level 2.2---
/*
这个函数会建立一个file并加入到进程打开文件数组中,返回一个文件描述符fd作为索引
*/
int
file_open(char *path, uint32_t open_flags) {
//根据用户标志参数判断文件打开标志,用于在file结构体中设置读写标志
bool readable = 0, writable = 0;
switch (open_flags & O_ACCMODE) {
case O_RDONLY: readable = 1; break;
case O_WRONLY: writable = 1; break;
case O_RDWR:
readable = writable = 1;
break;
default:
return -E_INVAL;
}
int ret;
struct file *file;
//新建一个文件,加入到进程的打开文件数组中
if ((ret = filemap_alloc(NO_FD, &file)) != 0) {
return ret;
}
//--------------------------------------------------------
struct inode *node;
//调用level 2.3
if ((ret = vfs_open(path, open_flags, &node)) != 0) { //新建一个inode
//--------------------------------------------------------
filemap_free(file);
return ret;
}
file->pos = 0;
if (open_flags & O_APPEND) {
struct stat __stat, *stat = &__stat;
if ((ret = vop_fstat(node, stat)) != 0) {
vfs_close(node);
filemap_free(file);
return ret;
}
file->pos = stat->st_size;//设置文件指针初始偏移位置
}
file->node = node;//指向node
//设置读写模式
file->readable = readable;
file->writable = writable;
//增加文件的引用计数
filemap_open(file);
return file->fd; //返回