转自:http://blog.chinaunix.net/uid-28362602-id-3425881.html

目录

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

Vfs_write函数实现原理

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系统调用实现原理

Linux VFS中write系统调用实现原理【转】的更多相关文章

  1. Linux 中open系统调用实现原理【转】

    转自:http://blog.chinaunix.net/uid-25968088-id-3426026.html 目录 OPEN系统调用过程 Open在内核里面的入口函数时sys_open Sys_ ...

  2. 在Linux内核中添加系统调用,并编译内核

    1 环境准备 运行系统:vmware下安装的ubuntu10.10 32bit桌面版. 编译内核版本: linux-2.6.32.63 内核目录: /home/wanchouchou/linuxKer ...

  3. ARM Linux系统调用的原理

    转载自:http://blog.csdn.net/hongjiujing/article/details/6831192 ARM Linux系统调用的原理 操作系统为在用户态运行的进程与硬件设备进行交 ...

  4. Linux系统调用(syscall)原理(转)

    引言:分析Android源码的过程中,要想从上至下完全明白一行代码,往往涉及app.framework.native一直到kernel,可能迷失到代码世界,明白了系统调用原理,或许能帮你峰回路转,找到 ...

  5. Linux 编程中的API函数和系统调用的关系【转】

    转自:http://blog.chinaunix.net/uid-25968088-id-3426027.html 原文地址:Linux 编程中的API函数和系统调用的关系 作者:up哥小号 API: ...

  6. 用 set follow-fork-mode child即可。这是一个 gdb 命令,其目的是告诉 gdb 在目标应用调用fork之后接着调试子进程而不是父进程,因为在 Linux 中fork系统调用成功会返回两次,一次在父进程,一次在子进程

    GDB的那些奇淫技巧 evilpan 收录于 Security  2020-09-13  约 5433 字   预计阅读 11 分钟  709 次阅读  gdb也用了好几年了,虽然称不上骨灰级玩家,但 ...

  7. Linux下缓冲区溢出攻击的原理及对策(转载)

    前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实现 ...

  8. linux VFS 内核数据结构

    <strong>简单归纳:fd只是一个整数,在open时产生.起到一个索引的作用,进程通过PCB中的文件描述符表找到该fd所指向的文件指针filp.</strong> 文件描述 ...

  9. 【转】在linux内核中读写文件 -- 不错

    原文网址:http://blog.csdn.net/tommy_wxie/article/details/8194276 1. 序曲 在用户态,读写文件可以通过read和write这两个系统调用来完成 ...

随机推荐

  1. div半透明背景,文字不透明

    background: rgba(255, 255, 255, 0.8) !important; /* IE无效,FF有效 */ background: #fff; filter: alpha(opa ...

  2. Unity3D游戏引擎最详尽基础教程

    第一节 加入重力 我们先打开Unity3d,新建一个场景(Scene),新建的时候应该会有对话框要求你加入哪些Asset Package,记得选择Physics Material,因为后面我们一定要用 ...

  3. SQL 语句调用这个存储过程,生成顺序编码

    一直很讨厌存储过程,没想到今天帮了我大忙啊,或许会因为今天让我慢慢喜欢上存储过程吧,不多说了,切入正题 在使用数据库的时候,难免要在使用过程中进行删除的操作,如果是使用int类型的字段,令其自增长,这 ...

  4. mysql时间格式化,按时间段查询MYSQL语句

    描述:有一个会员表,有个birthday字段,值为'YYYY-MM-DD'格式,现在要查询一个时间段内过生日的会员,比如'06-03'到'07-08'这个时间段内所有过生日的会员. SQL语句: Se ...

  5. 【7集iCore3基础视频】7-2 iCore3原理图介绍

    iCore3原理图介绍: 高清源视频:http://pan.baidu.com/s/1hsPkifM 密码:ei8ciCore3 购买链接:https://item.taobao.com/item.h ...

  6. equals和=,==的区别

    一. ==和equals的区别 1. ==是运算符 2. equals是String对象的方法 一般有两种类型的比较 1. 基本数据类型的比较 2. 引用对象的比较 1. 基本数据类型的比较 ==和e ...

  7. Nginx + php-fpm 执行 PHP 脚本超时 报错 502 Bad Gateway + 504 Gateway Time-out 的解决办法

    上周写好的发送邮件的计划任务只发送了一部分,检查计划任务日志,发现 502 Bad Gateway 的错误(已经在脚本中设置了 set_time_limit(0)). 后来在网上查找资料,可以通过以下 ...

  8. controlling the variance of request response times and not just worrying about maximizing queries per second

    http://highscalability.com/blog/2010/11/4/facebook-at-13-million-queries-per-second-recommends-minim ...

  9. 一个ICMP单元

    unit ICMPUtils; interface {$IFDEF VER80} { This source file is *NOT* compatible with Delphi 1 becaus ...

  10. VS2015——命令行下编译、静态库动态库制作以及断点调试

    c程序编译流程 程序的基本流程如图: 1. 预处理 预处理相当于根据预处理指令组装新的C/C++程序.经过预处理,会产生一个没有宏定义,没有条件编译指令,没有特殊符号的输出文件,这个文件的含义同原本的 ...