首页 > 系统相关 >Linux VFS中write系统调用实现原理

Linux VFS中write系统调用实现原理

时间:2023-04-25 12:07:17浏览次数:55  
标签:__ sys 调用 write file Linux NR VFS


目录

用户空间的write函数在内核里面的服务例程为sys_write. 1

Vfs_write函数实现原理... 2

 



WORD里面的目录复制过来似乎不能直接用。。还是放在这里当主线看吧..


用户空间的write 函数在内核里面的服务例程为sys_write

root@syslab ~]# grep write /usr/include/asm/unistd_64.h
#define __NR_write                              1
__SYSCALL(__NR_write, sys_write)
#define __NR_pwrite64                           18
__SYSCALL(__NR_pwrite64, sys_pwrite64)
#define __NR_writev                             20
__SYSCALL(__NR_writev, sys_writev)
#define __NR_pwritev                            296
__SYSCALL(__NR_pwritev, sys_pwritev)
#define __NR_process_vm_writev                  311
__SYSCALL(__NR_process_vm_writev, sys_process_vm_writev)

这里根据经验判断,通常write调用应该是sys_write,这里我们讨论sys_write函数的内核实现

SYSCALL_DEFINE3(write, unsigned int, fd, const char __user *, buf,size_t, count)
{
         {//这里SYSCALL_DEFINE3 write到sys_write的转换请参看前面的文章Linux 编程中的API函数和系统调用的关系
       //这里unsigned int fd表示用户空间的文件描述符
       //char __user *buf是存放从文件读取内容的一个用户空间内存区
         struct file *file;
         ssize_t ret = -EBADF;
         int fput_needed;
         file = fget_light(fd, &fput_needed);
         if (file) {
                   loff_t pos = file_pos_read(file);
                   ret = vfs_write(file, buf, count, &pos);
                   file_pos_write(file, pos);
                   fput_light(file, fput_needed);
         }
         return ret;
}

可以看到,和sys_read系统调用不同的地方就是这里调用了vfs_write函数来完成写操作,所以这里我们只看vfs_write都做了什么,其余部分请参看Linux 中read系统调用实现原理

Vfs_write 函数实现原理

ssize_t  vfs_write(struct file *file, const char __user *buf, size_t count, loff_t *pos)

即把用户空间的char __user* buf指向的内存地址里面的内容写入相应的设备文件

       基本同vfs_read,不过这里变成了

    如果文件系统没有实现file_operation或者既没有实现file_operation->write,也没有实现file_operation->aio_write,则报错。(即文件系统即没有实现同步写,也没有实现异步写,那就报错返回错误了)

如果文件系统实现了file->file_operation->write(还记得我吗在open系统调用中讲到的吗,在open系统调用中file->file_operation设置为了inode->file_operation)函数,则调用它来完成。

否则(说明文件系统没有实现write,但是实现了file_operation->aio_write)调用内核的默认函数do_sync_write(file, buf, count, pos);来做同步读写操作;而内核的do_sync_write函数内部实现是

ssize_t do_sync_write(struct file *filp, const char __user *buf, size_t len, loff_t *ppos){
struct iovec iov = { .iov_base = (void __user *)buf, .iov_len = len };
for (;;) {
                   ret = filp->f_op->aio_write(&kiocb, &iov, 1, kiocb.ki_pos);
                   if (ret != -EIOCBRETRY)
                            break;
                   wait_on_retry_sync_kiocb(&kiocb);
         }
}

这里和do_sync_read不同在于基本也就aio_read换成了aio_write了,do_sync_write最后调用的是file_operation->aio_write方法,但是iov数组长度为1,并且写入过程中如果写入操作没有完成则显式调用进程调度函数,本进程可能被挂起来且进程状态为TASK_UNINTERRUPTIBLE。直到最终写入完成,读取成功后进程状态会变为TASK_RUNNING,且存放在用户空间的buf内存区的内容已经写入硬件上为止

具体请参看Linux 中read系统调用实现原理


参考:kernel 3.6.7


标签:__,sys,调用,write,file,Linux,NR,VFS
From: https://blog.51cto.com/u_16087831/6223699

相关文章

  • 处理Linux 终端中文显示乱码问题
    问题详情:中文命名的文件或者文件夹显示?号或者□,无法正常显示文件名1、查看是否已安装中文字体#查看已安装的中文字体fc-list:lang=zh#查看已安装的中文字体并排序fc-list:lang=zh-cn|sort2、安装字体库yum-yinstallfontconfig3、添加中文字体,建立存储中文......
  • rust交叉编译配置:windows上编译linux可执行程序
    rust交叉编译配置:windows上编译linux可执行程序简述交叉编译大概指在在一种计算机环境中运行的编译程序,能编译出在另外一种环境下运行的代码.本次,我们配置的是在windows上编译出在linux上运行的rust可执行程序.我们在安装rust之后,默认会安装跟机器环境搭配的编译相关工具.......
  • xshell 传输文件后,Linux终端显示乱码
    原因:XSHELL与Linux编码设置不一致终端:xshell: 解决方法:设置为一致即可 ......
  • Linux常用技巧(十三)
    1、点亮指定硬盘:定位,磁盘闪灯/opt/MegaRAID/MegaCli/MegaCli64-PdLocate-start-physdrv[E:S]-a0/opt/MegaRAID/MegaCli/MegaCli64-PdLocate-stop-physdrv[E:S]-a02、查看证书过期时间echo|openssls_client-servername${domain}-connect${domain}:4432>/dev/null|......
  • 10 iozone Examples for Disk I/O Performance Measurement on Linux
    https://www.thegeekstuff.com/2011/05/iozone-examples/ Aswediscussedinour Linuxperformancemonitoringintroduction article,measuringIOsubsystemperformanceisveryimportant.Ifsomeoneiscomplainingthatadatabase(oranyapplication)running......
  • Linux安装Tomcat
    1.通过远程链接软件连接上我们的linux服务器,下载linux版本的jdk和tomcat压缩包并上传到我们的服务器中,如下:2.分别进行解压缩:tar-zxv-fjdk-8u371-linux-x64.tar.gz回车tar-zxv-fapache-tomcat-8.5.49.tar.gz回车3.启动防火墙systemctlstartfirewalld,查看防火墙......
  • Linux进程管理(1):进程描述和进程创建
     Linux是一种动态系统,能够适应不断变化的计算需求。Linux计算需求的表现是以进程的通用抽象为中心的。进程可以是短期的(从命令行执行的一个命令),也可以是长期的(一种网络服务)。因此,对进程及其调度进行一般管理就显得极为重要。   在用户空间,进程是由进程标识符(PID)表示的。......
  • linux中查看Python版本和路径
    1,查看python版本,输入python2,查看python路径,输入whereispython ......
  • linux批量处理脚本
    1.批量Killps-ef|grepjava|grep-vgrep|awk'{print$2}'|xargskill-92.统计进程数ps-ef|grepjava|grep-vgrep|awk'{print$2}'|wc3.批量打开防火墙端口1#!/bin/sh2ports=$13echo"$ports"4IFS=''5rea......
  • Linux安装jdk1.8
    第一步:去官网下载jdk>JavaDownloads|Oracle看你是什么系统2.把下载好的安装包(下载路径一定要记得)拖到xshell中第二步:......