参考: Linux 内核sys_open文件系统与设备操作流程分析
走马观花:Linux 系统调用 open 七日游
一般用户在应用程序里调用的 open, read, write 函数是 c 库的函数,这些函数会触发 swi val异常,从而引发系统调用,进入到内核空间,内核通过VFS(virtual Filesystem)来实现调用不同的驱动函数。
例一:open:使用地址的字符串如‘’/dev/led‘’,找到文件系统中的设备节点,再调用对应的open函数
open –> sys.open –> leddrv.open
在fs/open.c中
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, umode_t, mode)
{
if (force_o_largefile())
flags |= O_LARGEFILE;
return do_sys_open(AT_FDCWD, filename, flags, mode);
}
其中SYSCALL_DEFINE3是在include/linux/syscalls.h中定义的宏定义
#define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE2(name, ...) SYSCALL_DEFINEx(2, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE4(name, ...) SYSCALL_DEFINEx(4, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE5(name, ...) SYSCALL_DEFINEx(5, _##name, __VA_ARGS__)
#define SYSCALL_DEFINE6(name, ...) SYSCALL_DEFINEx(6, _##name, __VA_ARGS__)
#define SYSCALL_DEFINEx(x, sname, ...) \
SYSCALL_METADATA(sname, x, __VA_ARGS__) \
__SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
定义名中的数字3,表示你在调用函数书传入的参数个数,当在应用程序中传入几个参数,就调用对应的SYSCALL_DEFINE*(name, ...),name表示是那种系统调用,比如这里是open,对应的就是open,的系统调用。
下一步就是调用了 do_sys_open()这个函数,执行真正的系统open命令
太复杂了。。。涉及的东西太多,只写一个顺利的完整流程吧
do_sys_open
|
do_filp_open
|
path_openat
/* 关键的字符串解析处理函数,其核心思想是分级解析字符串, 通过字符串对应的目录项找到下一级目录的inode节点。 */
link_path_walk
/* do_last函数创建或者获取文件对应的inode对象,并且初始化file对象, 至此一个表示打开文件的内存对象filp诞生 */
do_last
|
//finish_open_created:
vfs_open
|
do_dentry_open
|
f->f_op = fops_get(inode->i_fop); /* 获得file_operation结构体 */
if (!open)
open = f->f_op->open;
if (open) { /* 调用真正的open函数 */
error = open(inode, f);
if (error)
goto cleanup_all;
}
例二:write:通过open得到的文件描述符fd,调用对应的drv_write
在fs/read_write.c中
SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,size_t, count)
|
struct fd f = fdget_pos(fd); /* 根据fd得到对应的文件 */
vfs_write(f.file, buf, count, &pos);
|
__vfs_write(file, buf, count, pos);
|
file->f_op->write(file, p, count, pos); /* 调用对应的write函数 */