LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: sybaselu

file_operation这个关键的数据结构在那个头文件中?

[复制链接]
发表于 2004-7-30 10:45:13 | 显示全部楼层
1.fd怎么会标识文件打开的模式?你是上那里得来的知识。fd只是用户进程中用来标识用户打开了第几个文件的索引而已。一个用户进程打开了第n个文件,返回的fd就是n-1。这和打开的模式有什么关系?
3.int 0x80是系统调用的入口地址,也就是一个开放给用户的软中断的入口地址。它的实现过程和中断一样。
发表于 2004-7-30 12:04:29 | 显示全部楼层
最初由 sybaselu 发表
1。用户态用open()打开后返回fd(文件描述符), fd是标识一个文件被打开的模式, 因为一个文件可以本不同的用户以不同的方式打开,fd用于找出在系统打开表和用户进程打开表中的标识,标明用户不同的操作方式对文件!
2。斑竹提到系统调用“asmlinkage datatype _sys_open(parameter table)”用/fs/open.c实现, 可是open.c是个编译单位c源码, 而asmlinkage datatype _sys_open()这是个函数,而且有带参数啊!这是咋回事?为什么系统调用的实现不放在一个目录下,这样不更清晰吗?
3。指令int ox80是中断服务程序的入口地址吗?由他转向中断子程序处理表,如果是, 要不要还乘四个字节呢?

内核结构精密巧妙,很多不惑之处恰恰是其精髓之处而非其错漏,请多加思考领悟。

1.相关数据结构

我最后认真说一次文件描述符以及系统打开文件表的关系,希望你能体会。
操作系统的引擎在于进程,它统率着用户态所有的行为。
进程控制块task_struct则是描述进程的数据结构,由内核进行维护,我们观察用户态的open()系统调用,最好的观察角度就是调用前后对task_struct的影响。

请看task_struct这个数据结构与文件相关的一个成员files_struct:

  1. [b][color=green]/*include/linux/sched.h*/[/color][/b]
  2. struct task_struct{
  3. ...
  4. /* open file information */
  5.         [b][color=red]struct files_struct *files;[/color][/b]
  6. ...
  7. }
复制代码

这个files_struct,顾名思义,就是进程所打开的文件描述结构指针。
再看看这个指针所指向的数据结构吧。

  1. [b][color=green]/*include/linux/file.h*/[/color][/b]
  2. struct files_struct {
  3.         atomic_t count;
  4.         spinlock_t file_lock;     /* Protects all the below members.  Nests inside tsk->alloc_lock */
  5.         int max_fds;
  6.         int max_fdset;
  7.         int next_fd;
  8.         [b][color=red]struct file ** fd;[/color][/b]      [b][color=green]/*指向文件对象的指针数组*/[/color][/b]
  9.         fd_set *close_on_exec;
  10.         fd_set *open_fds;
  11.         fd_set close_on_exec_init;
  12.         fd_set open_fds_init;
  13.         struct file * fd_array[NR_OPEN_DEFAULT];
  14. };
复制代码

如注释,fd成员指向文件对象,也就是系统打开文件对象。
所谓文件对象,就是struct file结构,请看它的源码。

  1. [b][color=green]/*include/linux/sched.h*/[/color][/b]
  2. struct file {
  3.         struct list_head        f_list;
  4.         struct dentry                *f_dentry;
  5.         struct vfsmount         *f_vfsmnt;
  6.         [b][color=red]struct file_operations        *f_op;[/color][/b]
  7.         atomic_t                f_count;
  8.         unsigned int                 f_flags;
  9.         mode_t                        f_mode;
  10.         int                        f_error;
  11.         loff_t                        f_pos;
  12.         struct fown_struct        f_owner;
  13.         unsigned int                f_uid, f_gid;
  14.         struct file_ra_state        f_ra;

  15.         unsigned long                f_version;
  16.         void                        *f_security;

  17.         /* needed for tty driver, and maybe others */
  18.         void                        *private_data;

  19. #ifdef CONFIG_EPOLL
  20.         /* Used by fs/eventpoll.c to link all the hooks to this file */
  21.         struct list_head        f_ep_links;
  22.         spinlock_t                f_ep_lock;
  23. #endif /* #ifdef CONFIG_EPOLL */
  24.         struct address_space        *f_mapping;
  25. };
复制代码

它的成员f_op就是文件操作函数了。

2.关联原理
好了,清楚了这些数据结构的关系,我们再看看操作流程吧,也就是说,它们之间究竟是如何被关联起来的。

sys_open()的内部大概流程:
1.get_unused_fd()找到进程未用的文件描述符fd
2filp_open()调用dentry_open(),根据open_namei找到的dentry结构,在内核数据区构造出一个file结构。
3.fd_install()关联这个file以及fd
4.最终sys_open()返回fd


  1. [b][color=green]/*include/linux/fs.h*/[/color][/b]
  2. struct inode {
  3.       ...
  4.         [b][color=red]struct file_operations        *i_fop;        /* former ->i_op->default_file_ops */[/color][/b]
  5.       ...
  6. };


  7. /*根据文件的dentry项构造file结构*/
  8. struct file *dentry_open(struct dentry *dentry, struct vfsmount *mnt, int flags)
  9. {
  10.         ...
  11.         [b][color=red]f->f_op = fops_get(inode->i_fop);[/b][/color] [color=green][b]/*从此可见,dentry_open用inode->i_fop填充file结构的f_op*/[/b][/color]
  12.       ...
  13. }
复制代码


总结:
用户态:文件描述符fd是一个小整数(只是1,2这样的数字而已),它通过进程控制块的files_struct的成员struct file ** fd索引系统打开文件对象file。

内核态:系统打开文件对象file是根据inode生成的由内核维护的数据结构,它包含了对文件的操作函数。
发表于 2004-7-30 12:13:47 | 显示全部楼层
至于中断,我也再说一次。

int 0x80是指令,是软中断触发指令。它本身并不是什么入口地址!
触发了中断后,系统会根据int 0x80传递的参数从系统调用表中找到入口地址,然后执行这个入口地址指向的中断服务例程。

ps:请兄弟多看源码来思考,研读内核,前提当然是看源码拉。
发表于 2004-7-30 12:52:12 | 显示全部楼层
open()这个名字是提供给标准C库的接口名字而已。
sys_open()则是内核的中断服务例程。

它们两者通过宏封装关联。
 楼主| 发表于 2004-8-2 21:17:42 | 显示全部楼层
1:那为什么不用fopen(), fclose(), fwrite()
2: fd的作用是用open()打开后使想其他的系统调用作为参数使用,如:read(int fd....), write(int fd, ....),能在系统或进程打开表中找到打开的文件
3:    user process: read(), open(), write()-------->
      system call: sys_open(), sys_read(), sys_write------->
      VFS: vop_open(), vop_read(), vop_write()------------->
      ext2/UFS/ext3 file system:ext3_open(), ext3_read(), ext3_write()--------------------->
 楼主| 发表于 2004-8-2 21:23:58 | 显示全部楼层
4:进程间如何切换, 线程间如何切换?
5:描述用户进程的tast_struct 在哪里?在linux中他整合了proc , user数据结构吗, 不再分常驻内存和磁盘.
6:什么叫做缓存区队列(framebuffer quenue)?
7:统一缓存器快存:UBC-----united buffer cache
发表于 2004-8-3 11:09:48 | 显示全部楼层
在回答之前,我想问兄弟两件事。

首先,你明白我上次的回帖吗?如果明白,可以谈谈你的思考;如果不明白,可以就此提出疑问。像兄弟这样,每次都抛开上次的问题和我的回帖不顾,而屡问新问题,我很难知道兄弟是否理解,而且,我个人也觉得很不尊重回帖者的脑力劳动。不知道兄弟有看过我的短消息了吗?

最初由 sybaselu 发表
usr/src/linux-2.6.6/kernel/drivers/mdeida/video/saa7134目录下有如下组成部分:
xxx.c, xxx.h, kconfig, makefiel文件组成, 其中在makfile中如下:
saa7134-objs :=saa7134-cards.o saa7134-core.o saa7134-i2c.o
saa7134-oss.o saa7134-ts.o 等等
obj-$CONFIG_VIDEO_SAA7134+=saa7134.o saa6752hs.o
这里我不明白的是:变量config_video_saa7134在哪里定义的, 整个文件的意思是什么!(是不是最后在/lib/modules/kernel/2.6.6/drivers/media/video/saa7134/下面生成saa7134.ko和saa6752hs.ko两个驱动, 还是取决于在内核中的编译情况?), 而且我发现在/drivers/下面每个设备的目录下面都是有这样的部分组成的!即:xxx.c+xxx.h+kconfig+makefile. 我现在正着手研究linux下的驱动程序的编写!
生成xxx.ko或xxx.o驱动并不要求xxx.c源代码中一定有一个关键的数据结构的子程序具体的实现代码如
typedef struct file_operation{
int (*seek)(struct inode *, struct file *)
int (*open)(struct inode *, struct file *)
int (*close)(struct inode *, struct file *)
int (*ioctl)(struct inode *, struct file *)
int (*write)(struct inode *, struct file *)
int (*read)(struct inode *, struct file *)
int (*fnasyc)(struct inode *, struct file *)
这个关键的数据结构在那个头文件中?
向版主报告



最初由 sybaselu 发表
磁盘分区上的文件系统中的格局如下:
引导块--(内核和引导参数?)--超级块---inode---数据;
1 :这里的inode存放的时系统上所有文件的inode吗?就是说文件数据和inode 是分开存放的!
2: 如果是所有的文件都存放在这里, 他们存放间有没有想目录样有层次关系?
3:我不太明白inode中的struct semaphore      i_sem;
                     struct rw_semaphore   i_allc_sem;
的意思?
                     struct file_operation  *i_fop在inode 中从当什么作用?以及    struct inode_operations *i_op
4:"这个宏把系统调用展开为含有int 0x80的汇编代码,int 0x80就是软中断(系统门),"这个斑竹能否进步解释呢?迫切想知道来龙去脉
先问这么多吧!


最初由 sybaselu 发表
1。用户态用open()打开后返回fd(文件描述符), fd是标识一个文件被打开的模式, 因为一个文件可以本不同的用户以不同的方式打开,fd用于找出在系统打开表和用户进程打开表中的标识,标明用户不同的操作方式对文件!
2。斑竹提到系统调用“asmlinkage datatype _sys_open(parameter table)”用/fs/open.c实现, 可是open.c是个编译单位c源码, 而asmlinkage datatype _sys_open()这是个函数,而且有带参数啊!这是咋回事?为什么系统调用的实现不放在一个目录下,这样不更清晰吗?
3。指令int ox80是中断服务程序的入口地址吗?由他转向中断子程序处理表,如果是, 要不要还乘四个字节呢?


最初由 sybaselu 发表
1:那为什么不用fopen(), fclose(), fwrite()
2: fd的作用是用open()打开后使想其他的系统调用作为参数使用,如:read(int fd....), write(int fd, ....),能在系统或进程打开表中找到打开的文件
3:    user process: read(), open(), write()-------->
      system call: sys_open(), sys_read(), sys_write------->
      VFS: vop_open(), vop_read(), vop_write()------------->
      ext2/UFS/ext3 file system:ext3_open(), ext3_read(), ext3_write()--------------------->


从最初的问题到最后,兄弟你自己看看,它们之间有关联吗?很明显,离题了,每个旧问题在没有解决的情况下,兄弟旁征博引,又提问新问题,我个人觉得这样的效率是不可取的。

第二,你提出的问题究竟哪些是问题,哪些是你的理解呢?我个人感觉你总是把问题和自己的理解混在一起,这样不但不利于我的解答,也可见你的思维有点混乱。而且,我发现,兄弟你之所以有很多问题,或许因为你还没有重视思考,思考问题之间的核心点及共通点。
最初由 sybaselu 发表
4:进程间如何切换, 线程间如何切换?
5:描述用户进程的tast_struct 在哪里?在linux中他整合了proc , user数据结构吗, 不再分常驻内存和磁盘.
6:什么叫做缓存区队列(framebuffer quenue)?
7:统一缓存器快存:UBC-----united buffer cache


在下说话向来直率,还望包涵。我的目的只有一个,就是想让兄弟们学好知识。

提问是一种技巧,好的提问有利于交流双方的互动。
就一事论一事,否则永远不能谈在点子上。
 楼主| 发表于 2004-8-3 13:46:14 | 显示全部楼层
我今天才看到斑竹的建议!因为前几天我一直没权限法帖!
我说的是这几点:
1. 我确实是将我所理解的与问题一起提出,目的是想知道我的理解是否正确!
2. 其实我一直在紧扣上次的提问啊!没有偏题
3. 如果一个问题一直想不通,得不到解,那么我就试着换一个角度提出来!这样或许柳暗花明有一村!豁然开朗,不是吗?
4.还是要谢过斑竹得用心良苦!
发表于 2004-8-3 14:44:57 | 显示全部楼层
最初由 sybaselu 发表
我今天才看到斑竹的建议!因为前几天我一直没权限法帖!
我说的是这几点:
1. 我确实是将我所理解的与问题一起提出,目的是想知道我的理解是否正确!
2. 其实我一直在紧扣上次的提问啊!没有偏题
3. 如果一个问题一直想不通,得不到解,那么我就试着换一个角度提出来!这样或许柳暗花明有一村!豁然开朗,不是吗?
4.还是要谢过斑竹得用心良苦!

1.最好不要这样做。这样的安排是混乱的,至少不便于解答者的阅读,希望以后能分开来写

2.的确有点偏题,比如驱动程序与文件系统,内存管理在逻辑上并不存在太大的关联,可考虑发新帖来提问,这样做便于分流

3.换个角度可以,但是否也可以参考解答者的思路来换呢?

4.兄弟可有对解答内容熟阅并思考过呢?很多问题就在解答中。
比如说,你提问为什么不用fopen()呢?
我已经提及:
其实系统调用就是软中断,也几乎是用户和内核打交道的唯一途径。为了屏蔽它的复杂性以及提高平台的可移植性,系统调用都被标准C函数库(Glibc)进行外封装,这种封装其实就是一组预处理宏(放在头文件中,这也是使用系统调用就必须得包含其头文件的原因),这组宏充当着内核态与用户态的转换器。这个宏把系统调用展开为含有int 0x80的汇编代码,int 0x80就是软中断(系统门),随即内核响应中断,进入内核态。

略思考可知,既然系统调用是唯一接口,而系统调用中只有一个sys_open函数,那么C标准库提供的*open类函数当然都使用系统门调用sys_open函数,只不过fopen的用户缓冲读写方式不一样罢了(换言之,在用户区的缓冲不一样),它们的实质都一样。

再者,你问及task_struct在哪?
我也早说过:
进程控制块task_struct则是描述进程的数据结构,由内核进行维护。

易知,task_struct放在内核数据区。

5.再提醒一下,提问前自己首先要看源码。
我每次在源码注解都留下该源码文件的路径,兄弟为什么不从该文件看看源码呢?比如说task_struct这个数据结构,就可以在以下文件找到。看看它,就知道它包含了什么内容。
/*include/linux/sched.h*/

所有的提问都应该建基于你对源码的疑问,而不是纯粹的凭空发问。这里毕竟是源码研读版区嘛,前提当然是你自己必须读。
发表于 2004-8-4 15:11:01 | 显示全部楼层
还是回答你提问的进程调度问题吧。这是一个很复杂的问题(不亚于NUMA虚存的复杂度,这两者是2.6内核的亮点!)。

众所周知,2.6内核在进程调度方面有了质的飞跃。我目前还不能从很深的层次来总结这一点。

先给出一篇很有参考价值的文章:
Linux 2.6 调度系统分析
http://www-900.ibm.com/developer ... kn26sch/index.shtml

相比之下,2.4内核的调度系统更简单。
Linux 2.4 调度系统分析
http://www-900.ibm.com/developer ... -k24sch/index.shtml
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表