Linux VFS中write系统调用实现原理【转】
转自: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系统调用实现原理【转】的更多相关文章
- Linux 中open系统调用实现原理【转】
转自:http://blog.chinaunix.net/uid-25968088-id-3426026.html 目录 OPEN系统调用过程 Open在内核里面的入口函数时sys_open Sys_ ...
- 在Linux内核中添加系统调用,并编译内核
1 环境准备 运行系统:vmware下安装的ubuntu10.10 32bit桌面版. 编译内核版本: linux-2.6.32.63 内核目录: /home/wanchouchou/linuxKer ...
- ARM Linux系统调用的原理
转载自:http://blog.csdn.net/hongjiujing/article/details/6831192 ARM Linux系统调用的原理 操作系统为在用户态运行的进程与硬件设备进行交 ...
- Linux系统调用(syscall)原理(转)
引言:分析Android源码的过程中,要想从上至下完全明白一行代码,往往涉及app.framework.native一直到kernel,可能迷失到代码世界,明白了系统调用原理,或许能帮你峰回路转,找到 ...
- Linux 编程中的API函数和系统调用的关系【转】
转自:http://blog.chinaunix.net/uid-25968088-id-3426027.html 原文地址:Linux 编程中的API函数和系统调用的关系 作者:up哥小号 API: ...
- 用 set follow-fork-mode child即可。这是一个 gdb 命令,其目的是告诉 gdb 在目标应用调用fork之后接着调试子进程而不是父进程,因为在 Linux 中fork系统调用成功会返回两次,一次在父进程,一次在子进程
GDB的那些奇淫技巧 evilpan 收录于 Security 2020-09-13 约 5433 字 预计阅读 11 分钟 709 次阅读 gdb也用了好几年了,虽然称不上骨灰级玩家,但 ...
- Linux下缓冲区溢出攻击的原理及对策(转载)
前言 从逻辑上讲进程的堆栈是由多个堆栈帧构成的,其中每个堆栈帧都对应一个函数调用.当函数调用发生时,新的堆栈帧被压入堆栈:当函数返回时,相应的堆栈帧从堆栈中弹出.尽管堆栈帧结构的引入为在高级语言中实现 ...
- linux VFS 内核数据结构
<strong>简单归纳:fd只是一个整数,在open时产生.起到一个索引的作用,进程通过PCB中的文件描述符表找到该fd所指向的文件指针filp.</strong> 文件描述 ...
- 【转】在linux内核中读写文件 -- 不错
原文网址:http://blog.csdn.net/tommy_wxie/article/details/8194276 1. 序曲 在用户态,读写文件可以通过read和write这两个系统调用来完成 ...
随机推荐
- Greenplum 生成加分区语句
在使用greenplum中会使用分区表,但同时分区表需要维护分区:比如加分区,这个过程比较痛苦,查询相关资料以后有了相应的解决办法,但是该办法也不是万能的,有诸多限制,关于限制有兴趣的同学可以查看我文 ...
- AFN----AFNetworking
一.介绍 官方介绍: 1.适用于iOS和Mac OS X两个平台的网络库 2.基于Foundation URL Loading System上进行一套封装 3.提供了丰富的API接口 4.是一个轻量级 ...
- oracle结构与安全
从宏观上来看:oracle数据库服务器主要有数据库和实例组成. 在orale数据库服务器中,首先会产生一个实例,通过实例访问一个数据库. 一个实例对应着一个数据库. oracle 数据库在逻辑上是按层 ...
- Android课程---首学开发
新建一个Activity2类: package com.hanqi.test; import android.app.Activity; import android.os.Bundle; impor ...
- EmguCV 阈值化
一.public static double cvThreshold( IntPtr src, IntPtr dst, double threshold, double maxValue, //Max ...
- Empire C:游戏篇(1)
随机生成1-6的数字,我们来猜是几 猜小了就提示数字小了,请再猜 猜大了就提示数字大了,请再猜 猜对了就提示恭喜,并提示是否继续再玩 ///riddle ///Author:JA //2015-1-2 ...
- 四个查找命令find,locate,whereis,which的区别
find最强大,但是检索硬盘,比较慢: whereis只能查二进制文件.说明文档,源文件等: locate能查所有文件,但跟whereis一样都是查数据库里的内容,速度快,但有延时: which 只能 ...
- 【iCore3 双核心板_ uC/OS-III】例程五:软件定时器
实验指导书及代码包下载: http://pan.baidu.com/s/1eSHenjs iCore3 购买链接: https://item.taobao.com/item.htm?id=524229 ...
- GFS文件系统和在RedHat Linux下的配置
GFS的全称是Google file System,为了满足Google迅速增长的数据处理要求,Google设计并实现的Google文件系统(GFS).Google文件系统是一个可扩展的分布式文件系统 ...
- Unity Svn(转)
先吐个槽.关于这个国内各种简单到家的文章让人搞不懂,而且场景合并,prefab合并等关键问题都说没法解决,其实本质就是因为它们都是二进制文件,所以SVN没法对其合并,但事实上Unity是支持把这些文件 ...