linux内核如何根据inet_bind_bucket结构体指针获取该结构体指针所属的进程pid

1490人阅读
在C语言中,对文件操作的时候,我们要定义一个FILE指针,用来指向打开的文件。这个FILE结构体的定义是这样的:
typedef struct &file
int & & & & & & & & &/* fill/empty level of buffer */
unsigned & & & & & & &/* File status flags & & & & &*/
char & & & & & & & & & & /* File descriptor & & & & & &*/
unsigned char & & & & /* Ungetc char if no buffer & */
int & & & & & & & & &/* Buffer size & & & & & & & &*/
unsigned char & * & &/* Data transfer buffer & & & */
unsigned char & * & & &/* Current active pointer & & */
unsigned & & & & & & /* Temporary file indicator & */
short & & & & & & & &/* Used for validity checking */
在C语言中,对文件的操作是通过fopen,fread,fwrite等标准C函数实现的.这些函数都是通过FILE指针来实现的.
在linux中关于struct file结构体是这样定义的,这个结构体是定义在/include/linux/fs.h中:
struct file {
* fu_list becomes invalid after file_free is called and queued via
* fu_rcuhead for RCU freeing
struct list_head fu_ &//文件链表
struct rcu_head
struct path
#define f_dentry f_path.dentry
#define f_vfsmnt f_path.mnt
const struct file_operations *f_ &//文件操作结构体
unsigned int
f_ &//文件标记
f_ &//文件打开模式
f_ & //文件指针的当前位置
struct fown_struct f_ &//文件的拥有者
unsigned int
f_uid, f_ & //文件的拥有者的用户ID和组ID
struct file_ra_state f_
unsigned long
#ifdef CONFIG_SECURITY
/* needed for tty driver, and maybe others */
#ifdef CONFIG_EPOLL
/* Used by fs/eventpoll.c to link all the hooks to this file */
struct list_head f_ep_
spinlock_t
#endif /* #ifdef CONFIG_EPOLL */
struct address_space *f_ &
我们来逐个了解一下内部包含的结构体:
1)/include/linux/list.h中:
struct list_head {
struct list_head *next, *
list_head是内核中最常用的建立双向循环链表的结构,在此用于通用文件对象链表的指针。
2)/include/linux/rcupdate.h中:
&* struct rcu_head - callback structure for use with RCU
&* @next: next update requests in a list
&* @func: actual update function to call after the grace period.
struct rcu_head {
struct rcu_head *
void (*func)(struct rcu_head *head);
RCU(Read-Copy Update)是Linux 2.6内核中新的锁机制.在此用于更新文件。
fu_list在file_free()函数被调用以后就无效了,队列通过rcu_head来释放RCU。
3)include/linux/namei.h中:
struct path {
struct vfsmount * &//作用是指出该文件的已安装文件系统
struct dentry * //是与文件相关的目录项对象
struct vfsmount {
struct list_head mnt_
struct vfsmount *mnt_ /* fs we are mounted on */
struct dentry *mnt_ /* dentry of mountpoint */
struct dentry *mnt_ /* root of the mounted tree */
struct super_block *mnt_ /* pointer to superblock */
struct list_head mnt_ /* list of children, anchored here */
struct list_head mnt_ /* and going through their mnt_child */
/* 4 bytes hole on 64bits arches */
char *mnt_
/* Name of device e.g. /dev/dsk/hda1 */
struct list_head mnt_
struct list_head mnt_ /* link in fs-specific expiry list */
struct list_head mnt_ /* circular list of shared mounts */
struct list_head mnt_slave_/* list of slave mounts */
struct list_head mnt_ /* slave list entry */
struct vfsmount *mnt_ /* slave is on master-&mnt_slave_list */
struct mnt_namespace *mnt_ /* containing namespace */
* We put mnt_count & mnt_expiry_mark at the end of struct vfsmount
* to let these frequently modified fields in a separate cache line
* (so that reads of mnt_flags wont ping-pong on SMP machines)
atomic_t mnt_
int mnt_expiry_
/* true if marked for expiry */
struct dentry {
atomic_t d_
unsigned int d_
/* protected by d_lock */
spinlock_t d_
/* per dentry lock */
struct inode *d_
/* Where the name belongs to - NULL is
* negative */
* The next three fields are touched by __d_lookup. &Place them here
* so they all fit in a cache line.
struct hlist_node d_ /* lookup hash list */
struct dentry *d_ /* parent directory */
struct qstr d_
struct list_head d_
/* LRU list */
* d_child and d_rcu can share memory
struct list_head d_ /* child of parent list */
struct rcu_head d_
struct list_head d_ /* our children */
struct list_head d_ /* inode alias list */
unsigned long d_
/* used by d_revalidate */
struct dentry_operations *d_
struct super_block *d_ /* The root of the dentry tree */
/* fs-specific data */
#ifdef CONFIG_PROFILING
struct dcookie_struct *d_ /* cookie, if any */
unsigned char d_iname[DNAME_INLINE_LEN_MIN]; /* small names */
4)linux/include/linux/fs.h中:
&* read, write, poll, fsync, readv, writev, unlocked_ioctl and compat_ioctl
&* can be called without the big kernel lock held in all filesystems.
struct file_operations {
struct module *
loff_t (*llseek) (struct file *, loff_t, int);
ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);
ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);
ssize_t (*aio_read) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
ssize_t (*aio_write) (struct kiocb *, const struct iovec *, unsigned long, loff_t);
int (*readdir) (struct file *, void *, filldir_t);
unsigned int (*poll) (struct file *, struct poll_table_struct *);
int (*ioctl) (struct inode *, struct file *, unsigned int, unsigned long);
long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
int (*mmap) (struct file *, struct vm_area_struct *);
int (*open) (struct inode *, struct file *);
int (*flush) (struct file *, fl_owner_t id);
int (*release) (struct inode *, struct file *);
int (*fsync) (struct file *, struct dentry *, int datasync);
int (*aio_fsync) (struct kiocb *, int datasync);
int (*fasync) (int, struct file *, int);
int (*lock) (struct file *, int, struct file_lock *);
ssize_t (*sendfile) (struct file *, loff_t *, size_t, read_actor_t, void *);
ssize_t (*sendpage) (struct file *, struct page *, int, size_t, loff_t *, int);
unsigned long (*get_unmapped_area)(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
int (*check_flags)(int);
int (*dir_notify)(struct file *filp, unsigned long arg);
int (*flock) (struct file *, int, struct file_lock *);
ssize_t (*splice_write)(struct pipe_inode_info *, struct file *, loff_t *, size_t, unsigned int);
ssize_t (*splice_read)(struct file *, loff_t *, struct pipe_inode_info *, size_t, unsigned int);
当打开一个文件时,内核就创建一个与该文件相关联的struct file结构,其中的*f_op就指向的是具体对该文件进行操作的函数。
例如用户调用系统调用read来读取该文件的内容时,那么系统调用read最终会陷入内核调用sys_read函数,
而 sys_read最终会调用与该文件关联的struct file结构中的f_op-&read函数对文件内容进行读取。
5)linux/include/linux/asm-i386.h中:
typedef struct {
} atomic_t;
volatile修饰字段告诉gcc不要对该类型的数据做优化处理,对它的访问都是对内存的访问,而不是对寄存器的访问。
本质是int类型,之所以这样写是让编译器对基于该类型变量的操作进行严格的类型检查。此处f_count的作用是记录对文件对象的引用计数,
也即当前有多少个使用CLONE_FILES标志克隆的进程在使用该文件。典型的应用是在POSIX线程中。就像在内核中普通的引用计数模块一样,
最后一个进程调用put_files_struct()来释放文件描述符。
6)unsigned int f_flags:
当打开文件时指定的标志,对应系统调用open的int flags参数。驱动程序为了支持非阻塞型操作需要检查这个标志.
7)mode_t f_
对文件的读写模式,对应系统调用open的mod_t mode参数。如果驱动程序需要这个值,可以直接读取这个字段.
mod_t被定义为:
typedef unsigned int __kernel_mode_t;
typedef __kernel_mode_t mode_t;
8)loff_t f_
当前的文件指针位置,即文件的读写位置。
loff_t被定义为:
typedef long long __kernel_loff_t;
typedef __kernel_loff_t loff_t;
9)linux/include/linux/fs.h中:
struct fown_struct {
rwlock_ & & & & &/* protects pid, uid, euid fields */
struct pid * /* pid or -pgrp where SIGIO should be sent */
enum pid_type pid_ /* Kind of process group SIGIO should be sent to */
uid_t uid, /* uid/euid of process setting the owner */
/* posix.1b rt signal to be delivered on IO */
该结构的作用是通过信号进行I/O时间通知的数据.
10)unsigned int f_uid, f_
标识文件的所有者id,所有者所在组的id.
11)/linux/include/linux/fs.h中:
&* Track a single file's readahead state
struct file_ra_state {
/* Current window */
/* ra flags RA_FLAG_xxx*/
unsigned long cache_ /* cache hit count*/
unsigned long prev_ /* Cache last read() position */
unsigned long ahead_ /* Ahead window */
unsigned long ahead_
unsigned long ra_
/* Maximum readahead window */
unsigned long mmap_
/* Cache hit stat for mmap accesses */
unsigned long mmap_ /* Cache miss stat for mmap accesses */
unsigned int prev_ /* Offset where last read() ended in a page */
文件预读状态,文件预读算法使用的主要数据结构,当打开一个文件时,f_ra中出了perv_page(默认为-1)和ra_apges(对该文件允许的最大预读量)这两个字段外,
其他的所有字端都置为0.
12)unsigned long f_
记录文件的版本号,每次使用后都自动递增.
#ifdef CONFIG_SECURITY
此处我的理解是如果在编译内核时配置了安全措施,那么struct file结构中就会有void *f_security数据项,用来描述安全措施或者是记录与安全有关的信息
13)void *private_
系统在调用驱动程序的open方法前将这个指针置为NULL。驱动程序可以将这个字段用于任意目的,也可以忽略这个字段。驱动程序可以用这个字段指向已分配的数据,
但是一定要在内核释放file结构前的release方法中清除它。
14)#ifdef CONFIG_EPOLL
/* Used by fs/eventpoll.c to link all the hooks to this file */
struct list_head f_ep_
spinlock_t f_ep_
#endif /* #ifdef CONFIG_EPOLL */
被用在fs/eventpoll.c来链接所有钩到这个文件上。其中f_ep_links是文件的事件轮询等待者链表的头,f_ep_lock是保护f_ep_links链表的自旋锁。
15)/linux/include/linux/fs.h中:
struct address_space {
struct inode
/* owner: inode, block_device */
struct radix_tree_root page_ /* radix tree of all pages */
tree_ /* and rwlock protecting it */
unsigned int
i_mmap_/* count VM_SHARED mappings */
struct prio_tree_root i_
/* tree of private and shared mappings */
struct list_head i_mmap_/*list VM_NONLINEAR mappings */
spinlock_t
i_mmap_ /* protect tree, count, list */
unsigned int
truncate_ /* Cover race condition with truncate */
unsigned long
/* number of total pages */
writeback_/* writeback starts here */
const struct address_space_operations *a_ /* methods */
unsigned long
/* error bits/gfp mask */
struct backing_dev_info *backing_dev_ /* device readahead, etc */
spinlock_t
private_ /* for use by the address_space */
struct list_head private_ /* ditto */
struct address_space *assoc_ /* ditto */
此处是指向文件地址空间的指针.
在linux中对文件的操作是通过Linux的系统调用实现的,如open,read,write等来实现的,这些函数是在内核空间实现操作的。与标准C中的使用不同。而在用户空间是通过一个文件描述符来对文件进行操作的.
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:28969次
排名:千里之外
原创:28篇
(1)(3)(10)(4)(10)您现在的位置: &&&&&&&&&&&&文章内容
快捷导航:
Linux内核数据结构
来源:考试大&&&【学而优则进,考试大以成!】&&日
  操作系统内核, 如同其他程序, 常常需要维护数据结构的列表. 有时, Linux 内核已经同时有几个列表实现. 为减少复制代码的数量, 内核开发者已经创建了一个标准环形的, 双链表; 鼓励需要操作列表的人使用这个设施.
  当使用链表接口时, 你应当一直记住列表函数不做加锁. 如果你的驱动可能试图对同一个列表并发操作, 你有责任实现一个加锁方案. 可选项( 破坏的列表结构, 数据丢失, 内核崩溃) 肯定是难以诊断的.
  为使用列表机制, 你的驱动必须包含文件 &linux/list.h&. 这个文件定义了一个简单的类型 list_head 结构:
  struct list_head { struct list_head *next, * };
  真实代码中使用的链表几乎是不变地由几个结构类型组成, 每一个描述一个链表中的入口项. 为在你的代码中使用 Linux 列表, 你只需要嵌入一个 list_head 在构成这个链表的结构里面. 假设, 如果你的驱动维护一个列表, 它的声明可能看起来象这样:
  struct todo_struct
  struct list_
  列表的头常常是一个独立的 list_head 结构. 图链表头数据结构显示了这个简单的 struct list_head 是如何用来维护一个数据结构的列表的.
  图 11.1. 链表头数据结构
  链表头数据结构
  链表头必须在使用前用 INIT_LIST_HEAD 宏来初始化. 一个"要做的事情"的链表头可能声明并且初始化用:
  struct list_head todo_
  INIT_LIST_HEAD(&todo_list);
  &para&可选地, 链表可在编译时初始化:&/para&
  LIST_HEAD(todo_list);
  几个使用链表的函数定义在 &linux/list.h&:
  list_add(struct list_head *new, struct list_head *head);
  在紧接着链表 head 后面增加新入口项 -- 正常地在链表的开头. 因此, 它可用来构建堆栈. 但是, 注意, head 不需要是链表名义上的头; 如果你传递一个 list_head 结构, 它在链表某处的中间, 新的项紧靠在它后面. 因为 Linux 链表是环形的, 链表的头通常和任何其他的项没有区别.
  list_add_tail(struct list_head *new, struct list_head *head);
  刚好在给定链表头前面增加一个新入口项 -- 在链表的尾部, 换句话说. list_add_tail 能够, 因此, 用来构建先入先出队列.
  list_del(struct list_head *entry);
  list_del_init(struct list_head *entry);
  给定的项从队列中去除. 如果入口项可能注册在另外的链表中, 你应当使用 list_del_init, 它重新初始化这个链表指针.
  list_move(struct list_head *entry, struct list_head *head);
  list_move_tail(struct list_head *entry, struct list_head *head);
  给定的入口项从它当前的链表里去除并且增加到 head 的开始. 为安放入口项在新链表的末尾, 使用 list_move_tail 代替.
  list_empty(struct list_head *head);
  如果给定链表是空, 返回一个非零值.
  list_splice(struct list_head *list, struct list_head *head);
  将 list 紧接在 head 之后来连接 2 个链表.
  list_head 结构对于实现一个相似结构的链表是好的, 但是调用程序常常感兴趣更大的结构, 它组成链表作为一个整体. 一个宏定义, list_entry, 映射一个 list_head 结构指针到一个指向包含它的结构的指针. 它如下被调用:
  list_entry(struct list_head *ptr, type_of_struct, field_name);
  这里 ptr 是一个指向使用的 struct list_head 的指针, type_of_struct 是包含 ptr 的结构的类型, field_name 是结构中列表成员的名子. 在我们之前的 todo_struct 结构中, 链表成员称为简单列表. 因此, 我们应当转变一个列表入口项为它的包含结构, 使用这样一行:
  struct todo_struct *todo_ptr = list_entry(listptr, struct todo_struct, list);
  list_entry 宏定义使用了一些习惯的东西但是不难用.
  链表的遍历是容易的: 只要跟随 prev 和 next 指针. 作为一个例子, 假设我们想保持 todo_struct 项的列表已降序的优先级顺序排列. 一个函数来添加新项应当看来如此:
  void todo_add_entry(struct todo_struct *new)
  struct list_head *
  struct todo_struct *
  for (ptr = todo_list. ptr != &todo_ ptr = ptr-&next)
  entry = list_entry(ptr, struct todo_struct, list);
  if (entry-&priority & new-&priority) {
  list_add_tail(&new-&list, ptr);
  list_add_tail(&new-&list, &todo_struct)
  但是, 作为一个通用的规则, 最好使用一个预定义的宏来创建循环, 它遍历链表. 前一个循环, 例如, 可这样编码:
  void todo_add_entry(struct todo_struct *new)
  struct list_head *
  struct todo_struct *
  list_for_each(ptr, &todo_list)
  entry = list_entry(ptr, struct todo_struct, list);
  if (entry-&priority & new-&priority) {
  list_add_tail(&new-&list, ptr);
  list_add_tail(&new-&list, &todo_struct)
  使用提供的宏帮助避免简单的编程错误; 宏的开发者也已做了些努力来保证它们进行正常. 存在几个变体:
  list_for_each(struct list_head *cursor, struct list_head *list)
  这个宏创建一个 for 循环, 执行一次, cursor 指向链表中的每个连续的入口项. 小心改变列表在遍历它时.
  list_for_each_prev(struct list_head *cursor, struct list_head *list)
  这个版本后向遍历链表.
  list_for_each_safe(struct list_head *cursor, struct list_head *next, struct list_head *list)
  如果你的循环可能删除列表中的项, 使用这个版本. 它简单的存储列表 next 中下一个项, 在循环的开始, 因此如果 cursor 指向的入口项被删除, 它不会被搞乱.
  list_for_each_entry(type *cursor, struct list_head *list, member)
  list_for_each_entry_safe(type *cursor, type *next, struct list_head *list, member)
  这些宏定义减轻了对一个包含给定结构类型的列表的处理. 这里, cursor 是一个指向包含数据类型的指针, member 是包含结构中 list_head 结构的名子. 有了这些宏, 没有必要安放 list_entry 调用在循环里了.
  如果你查看 &linux/list.h& 里面, 你看到有一些附加的声明. hlist 类型是一个有一个单独的, 单指针列表头类型的双向链表; 它常用作创建哈希表和类型结构. 还有宏用来遍历 2 种列表类型, 打算作使用 读取-拷贝-更新 机制(在第 5 章的"读取-拷贝-更新"一节中描述 ). 这些原语在设备驱动中不可能有用; 看头文件如果你愿意知道更多信息关于它们是如何工作的。
  编辑特别推荐:
来源:考试大-
责编:xxm&&&
王悦20¥200¥100杨海虹20¥200¥100杨海虹20¥200¥100杨海虹20¥200¥100王悦20¥200¥100
暂无跟贴,欢迎您发表意见
考试大Linux认证考试评论排行
1.&&评论5条
2.&&评论2条
3.&&评论2条
4.&&评论1条
5.&&评论1条
6.&&评论1条
主讲:杨海虹
12345678910
12345678910
12345678910Linux内核怎样获取进程任务结构
来源:&&&时间: 20:36:56&&&阅读数:
[导读] 我们现在来看看linux内核是如何获取当前进程的任务结构指针的,以下代码均参照linux内核2 4 0的源码。在includeasm-i386 current h中 ifndef_I386_CURRENT_H
define_I386_CURRENT_H structtask_ sta
我们现在来看看linux内核是如何获取当前进程的任务结构指针的,以下代码均参照linux内核2.4.0的源码。在includeasm-i386 current.h中#ifndef&_I386_CURRENT_H &&#define&_I386_CURRENT_H &&struct&task_ &&static&inline&struct&task_struct&*&get_current(void) &&{ &&&struct&task_struct&* &&&__asm__("andl&%%esp,%0;&":"=r"&(current)&:&"0"&(~8191UL)); &&&return& &&} &&#define&current&get_current() &&#endif&&每个进程都有一个task_struct任务结构,和一片用于系统空间堆栈的存储空间,他们在物理内存空间中也是联系在一起的,当给进程申请task_struct任务结构空间时,系统将连同系统的堆栈空间一起分配,如下图为某个进程切换时刻的内存图:
除非特别声明,PHP100新闻均为原创或投稿报道,转载请注明作者及原文链接原文地址:
延伸阅读 More
haowubai&&
haowubai&&
haowubai&&
haowubai&&
haowubai&&
视频教程 Video
网站服务:
专题合作 :
会员问题 : QQ
友情链接 : QQ 925939
网站投稿 :
@php100官方
php100官方微信
Copyright (C) 2007-, All Rights Reserved 版权所有 上海创恩信息技术有限公司. 沪ICP备号

我要回帖

更多关于 matlab 结构体 的文章

 

随机推荐