struct file
struct file结构体定义在include/linux/fs.h中定义。文件结构体代表一个打开的文件,系统中的每个打开的文件在内核空间都有一个关联的 struct file。它由内核在打开文件时创建,并传递给在文件上进行操作的任何函数。在文件的所有实例都关闭后,内核释放这个数据结构。在内核创建和驱动源码中,struct file的指针通常被命名为file或filp。
struct file 的最重要成员在这展示.
1.mode_t f_mode;
文件模式确定文件是可读的或者是可写的(或者都是), 通过位 FMODE_READ 和FMODE_WRITE. 你可能想在你的 open 或者 ioctl 函数中检查这个成员的读写许可, 但是不需要检查读写许可, 因为内核在调用你的方法之前检查. 当文件还没有为那种存取而打开时读或写的企图被拒绝, 驱动甚至不知道这个情况.
2.loff_t f_pos;
当前读写位置. loff_t 在所有平台都是 64 位( 在 gcc 术语里是 long long ). 驱动可以读这个值,如果它需要知道文件中的当前位置, 但是正常地不应该改变它; 读和写应当使用它们作为最后参数而收到的指针来更新一个位置, 代替直接作用于 filp->f_pos. 这个规则的一个例外是在 llseek 方法中, 它的目的就是改变文件位置.
3.unsigned int f_flags;
这些是文件标志, 例如 O_RDONLY, O_NONBLOCK, 和 O_SYNC. 驱动应当检查O_NONBLOCK 标志来看是否是请求非阻塞操作; 其他标志很少使用. 特别地, 应当检查读/写许可, 使用 f_mode 而不是f_flags. 所有的标志在头文件 中定义.
4.struct file_operations *f_op;
和文件关联的操作. 内核安排指针作为它的open 实现的一部分, 接着读取它当它需要分派任何的操作时. filp->f_op 中的值从不由内核保存为后面的引用; 这意味着你可改变你的文件关联的文件操作, 在你返回调用者之后新方法会起作用. 例如, 关联到主编号 1 (/dev/null, /dev/zero, 等等)的 open 代码根据打开的次编号来替代 filp->f_op 中的操作. 这个做法允许实现几种行为, 在同一个主编号下而不必在每个系统调用中引入开销. 替换文件操作的能力是面向
对象编程的"方法重载"的内核对等体.
5.void *private_data;
open 系统调用设置这个指针为 NULL, 在为驱动调用 open 方法之前. 你可自由使用这个成员或者忽略它; 你可以使用这个成员来指向分配的数据, 但是接着你必须记住在内核销毁文件结构之前, 在 release 方法中释放那个内存. private_data 是一个有用的资源, 在系统调用间保留状态信息, 我们大部分例子模块都使用它.
6.struct dentry *f_dentry;
关联到文件的目录入口( dentry )结构. 设备驱动编写者正常地不需要关心 dentry 结构, 除了作为 filp->f_dentry->d_inode 存取 inode 结构.
struct file {
union {
struct list_head fu_list; 文件对象链表指针linux/include/linux/list.h
struct rcu_head fu_rcuhead; RCU(Read-Copy Update)是Linux 2.6内核中新的锁机制
} f_u;
struct path f_path; 包含dentry和mnt两个成员,用于确定文件路径
#define f_dentry f_path.dentry f_path的成员之一,当前文件的dentry结构
#define f_vfsmnt f_path.mnt 表示当前文件所在文件系统的挂载根目录
const struct file_operations *f_op; 与该文件相关联的操作函数
atomic_t f_count; 文件的引用计数(有多少进程打开该文件)
unsigned int f_flags; 对应于open时指定的flag
mode_t f_mode; 读写模式:open的mod_t mode参数
off_t f_pos; 该文件在当前进程中的文件偏移量
struct fown_struct f_owner; 该结构的作用是通过信号进行I/O时间通知的数据。
unsigned int f_uid, f_gid; 文件所有者id,所有者组id
struct file_ra_state f_ra; 在linux/include/linux/fs.h中定义,文件预读相关
unsigned long f_version;
#ifdef CONFIG_SECURITY
void *f_security;
#endif
void *private_data;
#ifdef CONFIG_EPOLL
struct list_head f_ep_links;
spinlock_t f_ep_lock;
#endif
struct address_space *f_mapping;
};
filp->f_flags & O_NONBLOCK 中,O_NONBLOCK表示不等待,struct file结构体描述了文件描述符,即一个打开的文件(包括设备文件)信息,如果一个文件描述符设置了O_NONBLOCK,表示非阻塞的操作,显然,非阻塞操作的意思是,操作这个文件,例如读,即使没有数据,读仍然不等待,而是返回-EAGAIN,-EAGAIN的意思是again的意思,即要求用户try again。
即用户层使用fcntl设置文件描述符为非阻塞,如下:fcntl(fd, F_SETFL, O_NONBLOCK)
在内核层就会导致filp->f_flags被设置O_NONBLOCK位为1,因此,这个代码的意思是,如果没有数据,就进入while中,但如果设置了O_NONBLOCK,就返回-EAGAIN,否则加入等待队列中。
sizeof 解释:
int a[3]={1,2,3}; int b=sizeof(a)/sizeof(a[0]);计算b
sizeof 表示返回一个对象或者类型所占的内存字节数。
一般来讲,不同的机器,运行不同的对象是不一样的。
方法一:
因此,建议你在你运行的计算机上面输入如下代码:
#include
int main(void)
{
int a[3] = {1,2,3};
int b = sizeof(a)/sizeof(a[0]);
printf("sizeof(a):%d\n",sizeof(a));
printf("sizeof(a[0]):%d\n",sizeof(a[0]));
printf("b:%d\n",b);
}
编译后执行:
root@wusi-virtual-machine:/work/app/test_c/sizeof# ./sizeof
sizeof(a):12
sizeof(a[0]):4
b:3
方法二:
目前几乎所有的机器都是32位,很少16位的,所以一般考试都是基于32位的window和linux的。
int a[3]={1,2,3};// 整个数组占用的内存单元,以byte计。对于32位系统,int表示4个字节,一共三个元素,因此sizeof(a)=12,sizeof(a[0])=4;
int b = sizeof(a)/sizeof(a[0]); // 一维数组元素总个数
因此,b等于数组a元素的总个数,即3。
拓展:
对于char类型的要注意末尾多了一个NULL字符。
例如
char a1[] = "abc";
int a2[3];
sizeof( a1 ); // 结果为4,字符 末尾还存在一个NULL终止符
sizeof( a2 ); // 结果为3*4=12(依赖于int)
阅读(1454) | 评论(0) | 转发(0) |