一、引言

文件操作是Linux C编程中其中的一项核心技术,实际上也相当重要,这里并不是说狭义上的那种文件操作,它也非常有助于理解和学习Linux系统。为什么这样说呢?因为在Unix/Linux的世界中,一切皆文件!这种简单的设计其实非常有利于编程设计,让你可以集中在数据结构和算法的设计上,例如网络Socket和外部设备都作为文件处理,省去了很多繁琐的概念。

本文主要根据Linux文件实质原理展开讨论,其中也涉及到Linux的进程(Process)原理分析,Linux系统的进程对象持有一个文件记录表,该文件记录表保存一个该进程可处理的文件句柄数组,那么什么是文件描述符呢?它其实就是一个索引,就是文件句柄数组的下标索引,引用维基百科:

文件描述符在形式上是一个非负整数。实际上,它是一个索引值,指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时,内核向进程返回一个文件描述符。在程序设计中,一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于UNIX、Linux这样的操作系统。维基百科

这里讨论的都是广泛意义上的文件,你不需要强加想象将什么当做文件,下面会有具体的讲解。

二、进程管理与原理分析

什么是Linux进程?Linux进程是系统执行的一个程序以及该程序所管理的资源,在内存中执行一个简单的helloworld应用程序,这是一个进程,通常我们会说一个应用程序就是一个进程,严格来说并不正确,因为一个应用程序可以有多个子进程。

那么如何才能理解Linux的进程概念呢?从编程设计的角度来看,它应该被设计为一个结构体,C语言基本就是指针和结构体了,而结构体是最基本的数据结构单元。

Linux进程的源码文件为/include/linux/sched.h,取感兴趣的数据成员,进程结构体对象为:

struct task_struct {

// 进程可运行状态,-1不可执行,0可执行,>0可终止

volatile long state;

// 线程信息,在这里你可以到线程是从属于进程的

struct thread_info *thread_info;

// 进程描述符使用计数,表示该进程是否在被使用

atomic_t usage;

// 内核对每个进程的状态标识,如PF_FORKNOEXEC表示进程刚创建但未执行

unsigned long flags;

// 进程的调度策略,SCHED_FIFO和SCHED_RR为实时进程,SCHED_OTHER未分时进程

unsigned long policy;

// 进程标识符,代表一个进程

pid_t pid;

// 进程组标识符,代表该进程所属进程组别

pid_t __pgrp;

// 以下表示进程间的从属关系

struct task_struct *real_parent; /* real parent process (when being debugged) */

struct task_struct *parent;/* parent process */

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 */

// 进程的CPU状态信息

struct thread_struct thread;

// 文件系统信息

struct fs_struct *fs;

// 该进程打开的文件信息

struct files_struct *files;

// namespace

struct namespace *namespace;

};

以上代码,取了进程的一些基本信息,如进程ID,然后你会发现线程是属于进程的,但是Linux的进程和线程有什么区别呢?首先是从属关系,然后进程和线程的本质区别是,进程占据单独的内存空间,包括全局静态区、文字常量区、堆区、栈区和代码区,而线程是单独占据一个栈区,所以多线程是处理多个栈区包括主线程栈区。

接着还有进程之间的关系,子进程和父进程等,这里就表明了一个应用程序是可以有多个进程的。

最后红色加粗的struct

files_struct *files这个结构体变量表示该进程所打开的文件信息,该文件在/include/linux/file.h中:

// 打开文件表结构

struct files_struct {

// 使用该表的进程数

atomic_t count;

spinlock_t file_lock; /* Protects all the below members. Nests inside tsk->alloc_lock */

int max_fds;

int max_fdset;

int next_fd;

// 当前文件描述符数组的指针,下面fd_array的指针

struct file ** fd;

fd_set *close_on_exec;

fd_set *open_fds;

fd_set close_on_exec_init;

fd_set open_fds_init;

// 一个文件结构体指针数组,表示文件描述符数组,保存打开的文件

struct file * fd_array[NR_OPEN_DEFAULT];

};

每个进程都有这个文件描述符表,我们操作的文件对象都在fd_array中,文件描述符就是这个数组的索引,发现这样称呼也不甚准确,如果称索引为文件描述符,那么文件对象称指针会好点,不过看懂了就不用纠结了。你可以发现函数read和write,或者socket中的send和recv等,这些都是使用文件描述符来进行操作的,如果不明白其中的原理,OOP编程入门的开发者可能会想:为什么传个int就可以进行网络传输了?

三、Linux文件原理分析

这里要注意,该文件描述符数组在进程创建的时候默按顺序认初始化3个文件句柄:stdin,stdout,stderr,用于标准输入,标准输出,标准错误输出。

到这里你可以知道,对文件操作的基本元素有:文件句柄/指针,和文件描述符(索引),fdopen()函数可以将文件描述符转为文件指针,你可以想到的实现就是,根据索引从数组中获取到一个文件指针。

接着,我们需要扩展文件的概念,在linux中一切皆文件,这会很大程度上影响我们自己的编程想法,那么文件是什么样子的呢?看内核/include/linux/fs.h文件结构体的代码:

struct file {

struct list_headf_list;

// 目录结构

struct dentry*f_dentry;

struct vfsmount *f_vfsmnt;

// 文件操作,文件相关的函数操作,使用一个结构体封装函数指针

struct file_operations*f_op;

atomic_tf_count;

// 文件标志

unsigned int f_flags;

mode_tf_mode;

loff_tf_pos;

struct fown_structf_owner;

unsigned intf_uid, f_gid;

intf_error;

struct file_ra_statef_ra;

unsigned longf_version;

void*f_security;

/* needed for tty driver, and maybe others */

void*private_data;

/* Used by fs/eventpoll.c to link all the hooks to this file */

struct list_headf_ep_links;

spinlock_tf_ep_lock;

};

struct file和FILE是一样的,都代表一个文件,说了那么多,到底在Linux中具体哪些都是文件呢?

普通文件File,如一个txt文本,一个视频文件,一个字节码文件;

终端I/O,如字符终端;

管道Pipe,如普通管道和FIFO;

网络通信资源,套接字socket;

设备Device,网络设备,硬盘块设备,块设备。

以上都是我们常见的Linux文件,进一步我们可以将文件看作一种资源池,我们主要是对资源池中的数据进行读取,但是我们不说文件都是二进制表示所以说一切都是文件,基本是废话,二进制太广泛了,主要还是对数据结构和算法的理解,上面说的都是数据结构,实际相应的头文件中定义了相关操作。

linux进程文件描述符 vnode,Linux C编程详解:进程原理分析、文件描述符和文件记录表、文件句柄和文件原理...相关推荐

  1. linux在vi创建文件,Linux下创建文本文件(vi/vim命令使用详解)

    vi test.txt 或者 vim test.txt 再或者 touch test.txt vim是vi的升级版,指令更多,功能更强. 下面是收集的vim用法,当在vim里面要实现退出,首先要做的是 ...

  2. linux下grep文件内容搜索工具及基本正则表达式详解

    linux下grep文件内容搜索工具及基本正则表达式详解 grep命令: 根据模式(文本字符和基本正则表达式的元字符组合而成之匹配条件)搜索文本, 并将符合模式的文本行显示出来. 格式:grep [选 ...

  3. linux输出文件没有找到,Linux环境下标准输入、输出、错误信息详解

    Linux环境下标准输入.输出.错误信息详解 下面我们介绍在Linux环境下标准输入.输出.错误设备.标准输入设备代号为0, 用来显示输入信息,标准输出设备代号为1,用来显示正常信息,标准错误设备代号 ...

  4. linux查找权限为755的文件,linux系统文件夹644、755、777权限设置详解

    linux系统文件夹644.755.777权限设置详解 ,左至右,第一位数字代表文件所有者的权限,第二位数字代表同组用户的权限,第三位数字代表其他用户的权限. 而具体的权限是由数字来表示的,读取的权限 ...

  5. linux复制文件scp命令,Linux 中的文件复制cp命令和scp命令详解

    Linux 中的文件复制cp命令和scp命令详解 在使用操作系统的使用过程中,常常需要复制文件到本地或者传输文件到其他电脑上,这时候用到两个命令cp和scp. cp命令用来复制文件或者目录.scp是s ...

  6. Linux串口编程详解

    Linux串口编程详解(阻塞模式.非阻塞模式.select函数) 之前一直觉得串口编程很简单,这两天仔细研究后发现串口里的各种参数还挺复杂,稍不注意就容易出错,这里总结一下网上的各种文章及自己的理解与 ...

  7. 创建三个并发进程linux,Linux下几种并发服务器的实现模式(详解)

    1>单线程或者单进程 相当于短链接,当accept之后,就开始数据的接收和数据的发送,不接受新的连接,即一个server,一个client 不存在并发. 2>循环服务器和并发服务器 1.循 ...

  8. 1 linux下tcp并发服务器的几种设计的模式套路,Linux下几种并发服务器的实现模式(详解)...

    1>单线程或者单进程 相当于短链接,当accept之后,就开始数据的接收和数据的发送,不接受新的连接,即一个server,一个client 不存在并发. 2>循环服务器和并发服务器 1.循 ...

  9. 【125】Linux 中 ps -ef|grep和ps、grep详解

    一.ps -ef|grep详解(原文见公众号python宝)         ps命令将某个进程显示出来,PS是LINUX下最常用的也是非常强大的进程查看命令         grep命令是查找,是一 ...

  10. Linux的SOCKET编程详解

    Linux的SOCKET编程详解 一. 网络中进程之间如何通信 进程通信的概念最初来源于单机系统.由于每个进程都在自己的地址范围内运行,为保证两个相互通信的进 程之间既互不干扰又协调一致工作,操作系统 ...

最新文章

  1. C#实现发送手机短信
  2. 醒醒,迪卡侬请停止“低调”!
  3. OpenCASCADE:Android交叉编译 OCCT库
  4. 如是院长说:买不起房就多买两套,大家怎么看
  5. 复旦大学长跑协会财务制度(初稿)
  6. 微信开发七(配置js-SDK,步骤2)
  7. 伪代码 嵌套循环_大学开始,跟着别人的代码敲对自己编程提高有用吗?
  8. 轻量级java web实践-6(框架源码-4)
  9. 在VC6中使用ADO读取Oracle中的BLOB字段
  10. OpenSSL SSL_connect: Connection was reset in connection to github.com:443
  11. 2020年生肖码表图_2020年十二生肖号码表 查询属相年龄岁数对照图表
  12. 阿里云部署网站全流程(基于nodejs)
  13. ES7.14报错 Invalid receiver type interface org.apache.http.Header;not a subtype XX.http.NameValuePair
  14. 学习笔记--数据通信与计算机网络
  15. 计算机识别不到硬盘,解决BIOS检测不到硬盘的问题
  16. 用python爬取隐藏内容_人民日报点赞北大保安小哥,自学Python后,人生开挂了!...
  17. 搬运+机翻 Unity插件 OBICloth插件官方CharDemo分析
  18. Android自动化测试工具调研
  19. python 自动输入验证码_python 自动生成验证码并 输入识别
  20. 虚拟桌面分屏_无需分屏软件!让一台主机为两台显示器分屏工作的方法

热门文章

  1. 13行代码实现:Python实时视频采集(附源码)
  2. 5月中旬最科技青桐汇来袭,来看武汉最新最前沿的科技产品!
  3. 佳能mx398错误代码1686如何解决
  4. 量子物理和中国传统文化中道佛两教及气功_東波_新浪博客
  5. android键盘工具栏,android-如何禁用在软键盘上显示“建议”
  6. 同步推无需越狱可以安装正版是什么原理?
  7. RTX线程通信之——线程标志
  8. 算法训练 装箱问题(贪心,动态规划,蓝桥杯,C++)
  9. 节约用电小贴士_节约用水:洗个小澡
  10. css img 居中/水平居中/垂直居中