open调用过程
1. 首先传到vfs的do_sys_open,在open.c中。
long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
此时,我们只知道open传递过来的一些参数,比如filename,open调用是这样的
int open(const char *pathname, int flags, mode_t mode);
因此,只有dfd是新加的,我们先不管他的作用。
do_sys_open主要做以下事情
(1) int fd = build_open_flags(flags, mode, &op);//将open传递过来的flags和mode进行整理,赋值给op
fd = get_unused_fd_flags(flags);//分配一个未使用的fd
这个fd就是返回给用户open函数的fd。
(2) tmp = getname(filename); 将文件名做整理,并填充给tmp结构//struct filename *tmp;
(3) struct file *f = do_filp_open(dfd, tmp, &op); 这个就是实际的打开函数,填充struct file
(4) fd_install(fd, f); 将fd与 f进行关联。
2. 上面第(3)步是核心内容。首先我们在这里看struct file结构,/include/linux/fs.h
里面有三个比较重要的域。
struct inode *f_inode; /* cached value */
const struct file_operations *f_op;
struct address_space *f_mapping;
我们看do_filp_open如何对他们进行填充。
(1)首先创建struct nameidata nd; set_nameidata(&nd, dfd, pathname);
struct nameidata {
struct path path;
struct qstr last;
struct path root;
struct inode *inode; /* path.dentry.d_inode */
unsigned int flags;
unsigned seq;
int last_type;
unsigned depth;
char *saved_names[MAX_NESTED_LINKS + 1]; /* Intent data */
union {
struct open_intent open;
} intent;
};
set_nameidata主要使用参数 pathname 。
static void set_nameidata(struct nameidata *p, int dfd, struct filename *name)
{
struct nameidata *old = current->nameidata;
p->stack = p->internal;
p->dfd = dfd;
p->name = name;
p->total_link_count = old ? old->total_link_count : 0;
p->saved = old;
current->nameidata = p;
}
struct task_struct首先使用局部指针指向当前进程的nameidata, struct nameidata *old = current->nameidata; 也即是说,每个进程结构包含一个nameidata
然后只是给nd的total_link_count和pathname赋值。inode并没有管。total_link_count据说是用来防止循环死链的。
(2) filp = path_openat(&nd, op, flags | LOOKUP_RCU);
首先是file = get_empty_filp(); 为struct file 分配内存。
path_init为nd的path和inode赋值,为path->dentry赋值. static int link_path_walk 为nd->last 赋值
(3)主要的打开操作在 do_last 中。
link_path_walk 用于一级一级解析文件路径,每一级都调用do_last。 参考:http://alanwu.blog.51cto.com/3652632/1120652
3. 现在我们来分析 link_path_walk
函数原型:static int link_path_walk(const char *name, struct nameidata *nd)
调用方式:link_path_walk(s, nd) ,调用时,s通过 s=path_init(nd, flags)进行了赋值。
(1)首先,while (*name=='/') name++;假设name是/home/user/xxx,这条语句将name定位到h这个地方。疑惑:这里为什么要用while?这不是会导致路径名可以有多个斜杠?
如果while后name为null,则直接返回0. 这表明路径是一个目录。
(2)
4. 最终,do_last 调用 lookup_open, 调用atmoic_open,调用dir->i_op->atomic_open
dir是struct inode类型的,定义在/include/linux/fs.h,其中的 struct inode_operations i_op结构含有 atomic_open指针。
open调用过程的更多相关文章
- FormatMessage与GetLastError配合使用,排查windows api调用过程中的错误
前一段时间在学习windows api调用过程中,遇到过一些调用错误或者程序没能显示预期的结果,或者直接出现vc运行时错误. 这对新手来说是司空见惯的事,因为不太熟悉难免会出错,出错的信息如果能显示很 ...
- pro*c调用过程
数据库内有无参数过程名为procedure. pro*c调用过程 EXEC SQL EXECUTE BEGIN procedure; END; END-EXEC; 需要在cfg配置文件 ...
- Hadoop中客户端和服务器端的方法调用过程
1.Java动态代理实例 Java 动态代理一个简单的demo:(用以对比Hadoop中的动态代理) Hello接口: public interface Hello { void sayHello(S ...
- Hbase的WAL在RegionServer基本调用过程
版权声明:本文由熊训德原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/221 来源:腾云阁 https://www.qclo ...
- Servlet视频学习笔记 57-58 (servlet入门和调用过程)
网易云课堂<30天轻松掌握JavaWeb视频>servlet部分 课时57 servlet开发入门 servlet简介 Servlet是sun公司提供的一门用于开发动态web资源的技术.S ...
- 最原始的COM组件调用过程(不使用注册表信息)
最原始的COM组件调用过程(不使用注册表信息) 最近因为项目的关系开始研究COM组件了,以前都认为COM过时了,所以也没怎么接触. 现在好好补补课了. 一般调用COM都是通过注册表找到它的位置, 然后 ...
- oracle顺序控制语句goto、null和分页过程中输入输出存储、java程序的调用过程
顺序控制语句1 goto建议不要使用 declare i number:=; begin loop dbms_output.put_line(i); then goto end_loop; end i ...
- .net ADF 中 Ajax 的调用过程.
图示是 .net ADF Ajax调用过程的简略过程: 1,2)当页面初始化之后, 浏览器一旦触发回调事件, 脚本函数负责处理回调信息, 并调用 ASP.NET 2.0/3.5 中的 WebForm_ ...
- alsa声卡分析alsa-utils调用过程
如何分析tinyplay 播放音频和tinymix的过程?需要相应的工具来支持追查: 一.利用strace工具分析tinyplay和tinymix: strace -o tinyplay.log ti ...
- springMVC源码分析--HandlerInterceptor拦截器调用过程(二)
在上一篇博客springMVC源码分析--HandlerInterceptor拦截器(一)中我们介绍了HandlerInterceptor拦截器相关的内容,了解到了HandlerInterceptor ...
随机推荐
- Security arrangements for extended USB protocol stack of a USB host system
Security arrangements for a universal serial bus (USB) protocol stack of a USB host system are provi ...
- bash变量类型详解
本地变量:作用于当前shell,对当前shell之外的其他shell进程和当前shell子进程均无效. 本地变量赋值为 name='value' value可以是字符串或者是变量,引用变量使用${na ...
- 5.JAVA语言基础部分—多线程
一个应用有一个进程,一个进程里可以用多个线程 1)定义 定义线程有两种方式,一是继承java.lang.Thread类,二是实现java.lang.Runnable接口.其实Thread类就是实现了R ...
- centos下开启htaccess
不知道原本 centOS是否默认支持 .htaccess 可能是因为我总弄配置文件无意中给搞坏了 今天要用到就查了下怎么开启 想要顺利开启需注意以下几点, 这几点都是在httpd.conf 这个配置文 ...
- Android中的多线程编程(一)附源代码
Android中多线程编程:Handler类.Runnable类.Thread类之概念分析 1.Handler类: Handler是谷歌封装的一种机制:能够用来更新UI以及消息的发送和处理.Handl ...
- 1054. 求平均值 (20)-PAT乙级真题
今天刚刚到学校,2017年学习正式开始了,今天看到了浙大的<数据结构>这学期又要开课了,决定一定要跟着学习一遍:在大学生mooc网上学习:http://www.icourse163.org ...
- C#获取电脑的相关信息
/* 创建者:菜刀居士的博客 * 创建日期: 2014年08月31号 * 功能:获取电脑的相关信息 * */ namespace Net.String.ConsoleApplication { ...
- MAC Intellij IDEA 经常使用快捷键(本人亲自測试过)
MAC Intellij IDEA 经常使用快捷键 keymap 设置 MAC OS X 10.5+ alt+f7查找变量方法使用的地方 F3加入书签 Ctrl + O快捷覆写方法 Alt + F3 ...
- windows核心编程之进程间共享数据
有时候我们会遇到window进程间共享数据的需求,例如说我想知道系统当前有多少某个进程的实例. 我们能够在程序中定义一个全局变量.初始化为0.每当程序启动后就加1.当然我们我们能够借助第三方介质来储存 ...
- Android Studio 使用正式签名进行调试
在Android Studio中,能够使用Gradle进行打包时自己主动签名. 事实上Android Studio默认会给调试应用加上Debug签名,但有时候调一些第三方SDK时.须要正式签名才干调起 ...