Linux内核分析:打开文件描述符实现

时间:2023-03-09 02:17:04
Linux内核分析:打开文件描述符实现

在Linux中每一个进程的数据是存储在一个task_struct结构(定义在sched.h中)中的。

 struct task_struct {
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */
struct thread_info *thread_info;
atomic_t usage;
unsigned long flags; /* per process flags, defined below */
unsigned long ptrace; int lock_depth; /* Lock depth */ int prio, static_prio;
struct list_head run_list;
prio_array_t *array; unsigned long sleep_avg;
unsigned long long timestamp, last_ran;
int activated; unsigned long policy;
cpumask_t cpus_allowed;
unsigned int time_slice, first_time_slice; #ifdef CONFIG_SCHEDSTATS
struct sched_info sched_info;
#endif struct list_head tasks;
/*
* ptrace_list/ptrace_children forms the list of my children
* that were stolen by a ptracer.
*/
struct list_head ptrace_children;
struct list_head ptrace_list; struct mm_struct *mm, *active_mm; /* task state */
struct linux_binfmt *binfmt;
long exit_state;
int exit_code, exit_signal;
int pdeath_signal; /* The signal sent when the parent dies */
/* ??? */
unsigned long personality;
unsigned did_exec:;
pid_t pid;
pid_t tgid;
/*
* pointers to (original) parent process, youngest child, younger sibling,
* older sibling, respectively. (p->father can be replaced with
* p->parent->pid)
*/
struct task_struct *real_parent; /* real parent process (when being debugged) */
struct task_struct *parent; /* parent process */
/*
* children/sibling forms the list of my children plus the
* tasks I'm ptracing.
*/
struct list_head children; /* list of my children */
struct list_head sibling; /* linkage in my parent's children list */
struct task_struct *group_leader; /* threadgroup leader */ /* PID/PID hash table linkage. */
struct pid pids[PIDTYPE_MAX]; struct completion *vfork_done; /* for vfork() */
int __user *set_child_tid; /* CLONE_CHILD_SETTID */
int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */ unsigned long rt_priority;
unsigned long it_real_value, it_real_incr;
cputime_t it_virt_value, it_virt_incr;
cputime_t it_prof_value, it_prof_incr;
struct timer_list real_timer;
cputime_t utime, stime;
unsigned long nvcsw, nivcsw; /* context switch counts */
struct timespec start_time;
/* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */
unsigned long min_flt, maj_flt;
/* process credentials */
uid_t uid,euid,suid,fsuid;
gid_t gid,egid,sgid,fsgid;
struct group_info *group_info;
kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
unsigned keep_capabilities:;
struct user_struct *user;
#ifdef CONFIG_KEYS
struct key *session_keyring; /* keyring inherited over fork */
struct key *process_keyring; /* keyring private to this process (CLONE_THREAD) */
struct key *thread_keyring; /* keyring private to this thread */
#endif
int oomkilladj; /* OOM kill score adjustment (bit shift). */
char comm[TASK_COMM_LEN];
/* file system info */
int link_count, total_link_count;
/* ipc stuff */
struct sysv_sem sysvsem;
/* CPU-specific state of this task */
struct thread_struct thread;
/* filesystem information */
struct fs_struct *fs;
/* open file information */
struct files_struct *files;
/* namespace */
struct namespace *namespace;
/* signal handlers */
struct signal_struct *signal;
struct sighand_struct *sighand; sigset_t blocked, real_blocked;
struct sigpending pending; unsigned long sas_ss_sp;
size_t sas_ss_size;
int (*notifier)(void *priv);
void *notifier_data;
sigset_t *notifier_mask; void *security;
struct audit_context *audit_context; /* Thread group tracking */
u32 parent_exec_id;
u32 self_exec_id;
/* Protection of (de-)allocation: mm, files, fs, tty, keyrings */
spinlock_t alloc_lock;
/* Protection of proc_dentry: nesting proc_lock, dcache_lock, write_lock_irq(&tasklist_lock); */
spinlock_t proc_lock;
/* context-switch lock */
spinlock_t switch_lock; /* journalling filesystem info */
void *journal_info; /* VM state */
struct reclaim_state *reclaim_state; struct dentry *proc_dentry;
struct backing_dev_info *backing_dev_info; struct io_context *io_context; unsigned long ptrace_message;
siginfo_t *last_siginfo; /* For ptrace use. */
/*
* current io wait handle: wait queue entry to use for io waits
* If this thread is processing aio, this points at the waitqueue
* inside the currently handled kiocb. It may be NULL (i.e. default
* to a stack based synchronous wait) if its doing sync IO.
*/
wait_queue_t *io_wait;
/* i/o counters(bytes read/written, #syscalls */
u64 rchar, wchar, syscr, syscw;
#if defined(CONFIG_BSD_PROCESS_ACCT)
u64 acct_rss_mem1; /* accumulated rss usage */
u64 acct_vm_mem1; /* accumulated virtual memory usage */
clock_t acct_stimexpd; /* clock_t-converted stime since last update */
#endif
#ifdef CONFIG_NUMA
struct mempolicy *mempolicy;
short il_next;
#endif
};

该结构中有一个用于保存打开文件信息的成员:files,该成员类型是:struct files_struct*(定义在file.h)。

 1 /*
2 * Open file table structure
3 */
4 struct files_struct {
5 atomic_t count;
6 spinlock_t file_lock; /* Protects all the below members. Nests inside tsk->alloc_lock */
7 int max_fds;
8 int max_fdset;
9 int next_fd;
10 struct file ** fd; /* current fd array */
11 fd_set *close_on_exec;
12 fd_set *open_fds;
13 fd_set close_on_exec_init;
14 fd_set open_fds_init;
15 struct file * fd_array[NR_OPEN_DEFAULT];
16 };

可以看到该结构中保存了所有与进程打开文件相关的信息,其中fd_array是一个struct file*(定义在file.h)类型的数组。

 1 struct file {
2 struct list_head f_list;
3 struct dentry *f_dentry;
4 struct vfsmount *f_vfsmnt;
5 struct file_operations *f_op;
6 atomic_t f_count;
7 unsigned int f_flags;
8 mode_t f_mode;
9 int f_error;
10 loff_t f_pos;
11 struct fown_struct f_owner;
12 unsigned int f_uid, f_gid;
13 struct file_ra_state f_ra;
14
15 size_t f_maxcount;
16 unsigned long f_version;
17 void *f_security;
18
19 /* needed for tty driver, and maybe others */
20 void *private_data;
21
22 #ifdef CONFIG_EPOLL
23 /* Used by fs/eventpoll.c to link all the hooks to this file */
24 struct list_head f_ep_links;
25 spinlock_t f_ep_lock;
26 #endif /* #ifdef CONFIG_EPOLL */
27 struct address_space *f_mapping;
28 };

struct file就是保存了每个打开文件信息的数据结构。