read、write等系统调用

文章详细阐述了在Linux系统中,用户态的write系统调用如何进入内核态并执行SyS_write的过程,涉及fdget_pos、vfs_write等内核函数,以及SYSCALL_DEFINE3宏的使用和系统调用表的作用。

用户态的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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值