1.FILE结构体?
FILE 是 C语言文件结构定义, 打开文件和文件操作要用到这类结构。可以看成变量类型,用于变量声明。这个是一种数据结构类型,用来表示一个文件的相关信息,如果定义了一个文件指针,就用这个指针来指向某个文件,然后就能使用这个指针对文件来进行操作了。
FILE在"stdio.h"中有如下定义:
struct _iobuf {
char *_ptr; //文件输入的下一个位置
int _cnt; //当前缓冲区的相对位置
char *_base; //指基础位置(即是文件的其始位置)
int _flag; //文件标志
int _file; //文件的有效性验证
int _charbuf; //检查缓冲区状况,如果无缓冲区则不读取
int _bufsiz; //文件的大小
char *_tmpfname; //临时文件名
};
typedef struct _iobuf FILE;
2.文件表:文件描述,inode?
文件描述符:文件描述符是一个简单的整数,用以标明每一个被进程所打开的文件和socket。
open函数返回小整数,进程运行内部文件标识符。
第一个打开的文件是0,第二个是1,依此类推。三种标准输入流:标准输入/输出(默认)
文件描述:0(标准输入),1(标准输出),2(标准错误)
Linux下,一切皆文件思想,一个文件对应一个inode.内核中,对应于每个进程都有一个文件描述符表,表示这个进程打开的所有文件。文件描述表中每一项都是一个指针,指向一个用于描述打开的文件的数据块———file对象,file对象中描述了文件的打开模式,读写位置等重要信息,当进程打开一个文件时,内核就会创建一个新的file对象。需要注意的是,file对象不是专属于某个进程的,不同进程的文件描述符表中的指针可以指向相同的file对象,从而共享这个打开的文件。file对象有引用计数,记录了引用这个对象的文件描述符个数,只有当引用计数为0时,内核才销毁file对象,因此某个进程关闭文件,不影响与之共享同一个file对象的进程.file对象中包含一个指针,指向dentry对象。dentry对象代表一个独立的文件路径,如果一个文件路径被打开多次,那么会建立多个file对象,但它们都指向同一个dentry对象。dentry对象中又包含一个指向inode对象的指针。inode对象代表一个独立文件。因为存在硬链接与符号链接,因此不同的dentry对象可以指向相同的inode对象.inode 对象包含了最终对文件进行操作所需的所有信息,如文件系统类型、文件的操作方法、文件的权限、访问日期等。打开文件后,进程得到的文件描述符实质上就是文件描述符表的下标,内核根据这个下标值去访问相应的文件对象,从而实现对文件的操作。
注意,同一个进程多次打开同一个文件时,内核会创建多个file对象。当进程使用fork系统调用创建一个子进程后,子进程将继承父进程的文件描述符表,因此在父进程中打开的文件可以在子进程中用同一个描述符访问。
3.硬链接与软连接?
Linux链接分两种,一种被称为硬链接(Hard Link),另一种被称为符号链接(Symbolic Link)。
默认情况下,ln命令产生硬链接。
【硬连接】
硬连接指通过索引节点来进行连接。在Linux的文件系统中,保存在磁盘分区中的文件不管是什么类型都给它分配一个编号,称为索引节点号(Inode Index)。在Linux中,多个文件名指向同一索引节点是存在的。一般这种连接就是硬连接。硬连接的作用是允许一个文件拥有多个有效路径名,这样用户就可以建立硬连接到重要文件,以防止“误删”的功能。其原因如上所述,因为对应该目录的索引节点有一个以上的连接。只删除一个连接并不影响索引节点本身和其它的连接,只有当最后一个连接被删除后,文件的数据块及目录的连接才会被释放。也就是说,文件真正删除的条件是与之相关的所有硬连接文件均被删除。
【软连接】
另外一种连接称之为符号连接(Symbolic Link),也叫软连接。软链接文件有类似于Windows的快捷方式。它实际上是一个特殊的文件。在符号连接中,文件实际上是一个文本文件,其中包含的有另一文件的位置信息。
3.vfork()和fork(),return()和exit()返回不同,为什么?
fork()在创建时没规定调度顺序,而fork()保证子进程先运行。
vfork()父子进程共用地址空间,当子进程调用exit或exec(程序替换),父进程才运行。
1、fork:子进程拷贝父进程的数据段
vfork:子进程与父进程共享数据段
2、fork:父子进程的执行次序不确定
vfork:子进程先运行,父进程后运行
C程序中,程序运行时,入口是_start,它首先做一些初始化工作也称为启动例程,然后调用我们的main函数,由于main函数是被启动例程调用的,所以从main函数return时就返回到启动例程中,exit是libc的库函数,它首先做一些清理工作,然后调_exit系统调用终止进程,main函数的返回值最终会被传给_exit系统调用,成为进程的退出状态。我们也可以在main函数中直接调用exit函数终止进程而不返回启动例程。
//vfrok时父、子进程共享数据段,fork时是进行拷贝如果,vfork子进程中,使用return返回时,出现段错误。