转自: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. Mysql bench执行sql语句批量操作数据所遇到的问题

    一.错误 rror Code: 1175. You are using safe update mode and you tried to update a table without a WHERE ...

  2. OpenCV 3.0 CvMat and cv::Mat Conversion

    After OpenCV 3.0, CvMat cannot be directly converted to cv::Mat, we need to use function cvarrToMat( ...

  3. Python 3.x下消除print()自动换行

    Python 2.x下的print语句在输出字符串之后会默认换行,如果不希望换行,只要在语句最后加一个“,”即可.但是在Python 3.x下,print()变成内置函数,加“,”的老方法就行不通了. ...

  4. linux中,常用的账号管理命令

    创建新用户:adduser 用户名创建新用户并将其加入一个现有组中:adduser 用户名 -G 组名创建新用户并使其只属于该组:adduser 用户名 -g 组名创建用户密码:passwd 用户名创 ...

  5. 数位DP HDU3555

    Bomb Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)Total Submi ...

  6. OSI七层&TCP&IP协议

    OSI七层: OSI七层与ICP/IP概念层的对应: ICP/IP概念层上的网络设备: IP(Internet Protocol网际协议):计算机之间的通信 IP(网络协议)位于网络层,作用是把各种数 ...

  7. 使用UEditor 的时候,ajax注意使用同步的方法

    使用UEditor 的时候,ajax注意使用同步的方法去读取后台数据,然后填写到前端的文本域当中.

  8. 示例Oracle 10.2.0.1.0升级到10.2.0.4.0一例

    1.查看当前系统版本 [oracle@std Disk1]$ sqlplus '/as sysdba' SQL*Plus: Release - Production on Thu Jan :: Cop ...

  9. iOS -- AVAudioPlayer播放音乐

    一. AVAudioPlayer:                          声明音乐控件AVAudioPlayer,必须声明为全局属性变量,否则可能不会播放,AVAudioPlayer只能播 ...

  10. Oracle 常用数据类型(转)

    varchar2(6) 张三 --在jbk中是两个字节,在utm中是三个字节char(6) 张 三 --可以确定长度的用charclob --大存储,没事少用,当多余4000字节时,会用lob来存储, ...