用户态的read、write等系统调用,陷入内核态,会首先调用到 SyS_read、SyS_write函数
1、write
用户态的系统调用:write
SyS_write
vfs_write
__vfs_write
fops->write
先看看 SyS_write 的定义
// fs/read_write.c
577 SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,
578 size_t, count)
579 {
580 struct fd f = fdget_pos(fd);
581 ssize_t ret = -EBADF;
582
583 if (f.file) {
584 loff_t pos = file_pos_read(f.file);
585 ret = vfs_write(f.file, buf, count, &pos);
586 if (ret >= 0)
587 file_pos_write(f.file, pos);
588 fdput_pos(f);
589 }
590
591 return ret;
592 }
SYSCALL_DEFINE3 的定义
// include/linux/syscalls.h
184 #define SYSCALL_DEFINE3(name, ...) SYSCALL_DEFINEx(3, _##name, __VA_ARGS__)
189 #define SYSCALL_DEFINEx(x, sname, ...) \
190 SYSCALL_METADATA(sname, x, __VA_ARGS__) \
191 __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
194 #define __SYSCALL_DEFINEx(x, name, ...) \
195 asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \
196 __attribute__((alias(__stringify(SyS##name)))); \
197 static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \
198 asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)); \
// 此处产生 SyS_xx 函数的定义
199 asmlinkage long SyS##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
200 { \
201 long ret = SYSC##name(__MAP(x,__SC_CAST,__VA_ARGS__)); \
202 __MAP(x,__SC_TEST,__VA_ARGS__); \
203 __PROTECT(x, ret,__MAP(x,__SC_ARGS,__VA_ARGS__)); \
204 return ret; \
205 } \
206 static inline long SYSC##name(__MAP(x,__SC_DECL,__VA_ARGS__))
// 注意,上面的这个 SYSC##name 内联函数正好接上第一个函数块中的函数实现,形成完整的内联函数定义
从用户态的 write 到 内核态的 SyS_write 这一步是通过 compat_sys_call_table 这个函数数组 和 宏__SYSCALL实现的,详见博客
ARM64系统中兼容系统调用表compat_sys_call_table的定义和初始化
最终 compat_sys_call_table 对应一个个函数指针元素
通过c库函数 syscall(int a) syscall.h 执行数组的a元素
2、read
SyS_read
vfs_read
__vfs_read
fops->read
3、io_submit
SyS_io_submit
do_io_submit
aio_write / aio_write
fops->write_iter / fops->read_iter
文章详细阐述了在Linux系统中,用户态的write系统调用如何进入内核态并执行SyS_write的过程,涉及fdget_pos、vfs_write等内核函数,以及SYSCALL_DEFINE3宏的使用和系统调用表的作用。
1338

被折叠的 条评论
为什么被折叠?



